Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix error that tuple with star expr #8827

Merged
merged 3 commits into from
Jul 3, 2020
Merged

Conversation

LiuYuHui
Copy link
Contributor

fixes #7779

@LiuYuHui LiuYuHui force-pushed the TupleWithStarExpr branch 2 times, most recently from 0d44146 to bc8a3ad Compare May 15, 2020 02:46
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Looks pretty good, left some comments about how to improve this further.

mypy/checker.py Outdated
if isinstance(typs, TupleType):
rvalues.extend([TempNode(typ) for typ in typs.items])
else:
rvalues.append(TempNode(typs))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the type is an iterable, for example, the correct thing to do here would be to expand the right number of iterable item types, depending on the number of lvalues. It's okay if you don't want to implement that in this PR, however. The alternative would be to give an error about not being able to check the number of rvalues. The current behavior propagates an incorrect type, which I'd prefer to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your review, i would like to implement the correct thing, so the basic idea is that just get the right number of iterable item types, instead of constructing a new TempNode type, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more correct thing would be figure out the number of rvalues needed here so that the number of rvalues matches the number of lvalues. Then assuming the rvalue type is an iterable, look at the iterable item type and append a suitable number of TempNode instances with the iterable item type. Here we can assume that the length of the iterable is correct, as we don't know how many items there will actually be.

There will be some interesting edge cases, I assume. If the type is not iterable and not a tuple, you can probably fall back to AnyType (make sure that an error gets reported either here or elsewhere if the rvalue type is bogus).

[case testTupleWithStarExpr]
from typing import Tuple
points = (1, 2) # type: Tuple[int, int]
x, y, z = *points, 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also reveal the types of x, y, and z to check that we inferred the correct types.


[case testTupleWithStarExpr]
from typing import Tuple
points = (1, 2) # type: Tuple[int, int]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using all int types, use different types so that each of x, y and z will get distinct types. This way we can test that the types are propagated in the correct order.

Copy link
Collaborator

@msullivan msullivan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge this if Jukka's suggestions are implemented

@LiuYuHui LiuYuHui force-pushed the TupleWithStarExpr branch 2 times, most recently from 295c8e3 to 276705f Compare May 26, 2020 05:13
@LiuYuHui LiuYuHui requested a review from JukkaL May 29, 2020 08:26
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates! There are still a few edge cases that aren't quite right, but this is very close.

mypy/checker.py Outdated
num_last_iterable = 0
if len(idx_of_iterable):
num_every_iterable = int(lhs_len / len(idx_of_iterable))
num_last_iterable = lhs_len - (len(idx_of_iterable) - 1) * int(num_every_iterable)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems kind of arbitrary. We assume that the items from multiple *args rvalues are split between the values in a specific way, but we can't really predict this. Instead, I'd suggest this:

  • If all the item types of iterable *args rvalues are the same and next to each other, treat them as a single iterable.
  • If the item types vary or they aren't next to each other generate an error and fall back to some conservative approximation, such as assuming all their types are Any.

I think that the current behavior can be unsafe. Consider this:

a = [1]
b = ['x', 'y', 'z']
x1, x2, x3, x4 = *a, *b
x2 + 5  # Runtime error

mypy/checker.py Outdated
item_type_of_iterable.append(self.iterable_item_type(typs))
idx_of_iterable.append(idx)
else:
self.fail("StarExpr should not be a '{}'".format(typs), context)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nits: StarExpr is an internal name that we'd rather not use in an error message. It would be better to use something more descriptive, such as Invalid type 'x' for *expr (iterable expected)

If you pass rval as the context to fail, the error message should point to the relevant subexpression, making it easier to figure out what it going on.

It would be good to have a test case for this as well.

mypy/checker.py Outdated
if i == (len(idx_of_iterable) - 1):
rvalues[idx:idx] = [TempNode(item_type) for _ in range(num_last_iterable)]
else:
rvalues[idx:idx] = [TempNode(item_type) for _ in range(num_every_iterable)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the indices can become out of date as this modifies the length of rvalues?

reveal_type(x4) # N: Revealed type is 'builtins.str'
reveal_type(y3) # N: Revealed type is 'builtins.int*'
reveal_type(y4) # N: Revealed type is 'builtins.int*'
reveal_type(z3) # N: Revealed type is 'builtins.str'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add test case for two *expr that are both variable-length.

@LiuYuHui LiuYuHui force-pushed the TupleWithStarExpr branch 3 times, most recently from 08fb8d1 to 266e6da Compare June 28, 2020 01:25
@LiuYuHui LiuYuHui force-pushed the TupleWithStarExpr branch from 266e6da to f884bc8 Compare June 28, 2020 03:16
@LiuYuHui LiuYuHui requested a review from JukkaL June 28, 2020 11:17
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates and your persistence! Looks great now.

@JukkaL JukkaL merged commit 17b1f9c into python:master Jul 3, 2020
hauntsaninja pushed a commit to hauntsaninja/mypy that referenced this pull request Nov 8, 2021
In general, mypy doesn't promise to be able to check the remainder of
your code in the presence of syntax errors, so just make this a blocking
error.

Fixes python#9137
Fixes python#3825 (most of the reports in this issue were fixed by python#8827)
hauntsaninja added a commit that referenced this pull request Nov 15, 2022
In general, mypy doesn't promise to be able to check the remainder of
your code in the presence of syntax errors, so just make this a blocking
error.

Fixes #9137
Fixes #3825 (most of the reports in this issue were fixed by #8827)

Co-authored-by: hauntsaninja <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unpacking starred expressions in tuples
3 participants