You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unpacking an iterable in a list comprehension leads to the type inferred as list[Any] #15747
@JaylenLuc Please feel free to pick it up. I couldn't come up with a solution to it. What I got is that in the example posted in the issue, [*a] is treated as a generic callable call and its type is inferred somewhere around this place (sorry for the impreciseness, I looked at it a few weeks ago).
preface: I'm a first time open source contributor :)
In the infer_constraints_for_callable() function in constraints.py it calls infer_constraints() towards the end of the function which produces "[1 :> Any]" when it should produce: "[1 :> builtins.int]".
It may be because of a previous function call not far before it in the same function called mapper.expand_actual_type() that produces "Any" instead of builtins.int. This may be because its first argument "actual_arg_type" may be incorrect. Why I say this is because "actual_arg_type" is "Spam " when i think it should be "typing.Iterator[builtins.int]" or typing.generator[builtins.int].
The aforementioned "actual_arg_type" is infer_constraints_for_callable()'s second positional argument : "arg_types: Sequence[Type | None]". This argument is supplied by infer_function_type_arguments as "arg_types" in infer.py which is called by another function of the same name in checkexpr.py. The erroneous type (Spam instead of builtins.generator) is supplied by infer_arg_types_in_context() called in the same function before in infer_function_type_arguments(). This infer_arg_types_in_context() function calls accept which actually interprets the type correctly when it calls visit_int_expr() defined in checkexpr.py which calls infer_literal_expr_type() also defined in checkexpr.py.
I dont know what is causing the arg_types parameter to be Spam instead of int in infer_function_type_arguments in infer.py. This may be a problem that has to do with Python instead of MyPy but I have no clue. But it may not because Python actually knows what the yield type of generators are when you use the builtin : type() function on *a ( type(*a) --> <class 'int'>)
Should the generator unpacking expression that is erroneous be a mypy.nodes.NameExpr instead of mypy.nodes.NameExpr?
And should the argument kind be a ArgKind.ARG_POS instead of ArgKind.ARG_STAR?
This testing.Spam object is an Instance object where testing.Spam.args length is 0. This means that MyPy thinks testing.Spam has no arguments when it checks in argmap.py line 192 and returns AnyType(TypeOfAny.from_error) on line 217 instead of the result from map_instance_to_supertype().
Yeah, I'm guessing that code dates back before structural types and Protocols. Probably want to swap out the stuff in argmap for some code from checker that analyses the return type of __iter__, like analyze_iterable_item_type. Might need to thread the checker through to make this work
submitted a PR. if you check the PR comment I made, the only issues I'm having are with dmypy_server.py which is strange since I don't know how my changes are affecting it.
And I'm not sure if my quite naive attempt in #14496 could provide any additional insights in how to resolve the issue (or if it resolves the repro case found here)
Activity
kamilturek commentedon Aug 6, 2023
I'll give it a try.
JaylenLuc commentedon Aug 25, 2023
Are you still working on it? I can give it a try as well. Any insights to the issue?
kamilturek commentedon Aug 25, 2023
@JaylenLuc Please feel free to pick it up. I couldn't come up with a solution to it. What I got is that in the example posted in the issue,
[*a]is treated as a generic callable call and its type is inferred somewhere around this place (sorry for the impreciseness, I looked at it a few weeks ago).mypy/mypy/checkexpr.py
Lines 1660 to 1687 in 9e1f4df
JaylenLuc commentedon Aug 29, 2023
working on it. made progress, ill get back to you with my findings
JaylenLuc commentedon Aug 30, 2023
preface: I'm a first time open source contributor :)
In the infer_constraints_for_callable() function in constraints.py it calls infer_constraints() towards the end of the function which produces "[1 :> Any]" when it should produce: "[1 :> builtins.int]".
It may be because of a previous function call not far before it in the same function called mapper.expand_actual_type() that produces "Any" instead of builtins.int. This may be because its first argument "actual_arg_type" may be incorrect. Why I say this is because "actual_arg_type" is "Spam " when i think it should be "typing.Iterator[builtins.int]" or typing.generator[builtins.int].
The aforementioned "actual_arg_type" is infer_constraints_for_callable()'s second positional argument : "arg_types: Sequence[Type | None]". This argument is supplied by infer_function_type_arguments as "arg_types" in infer.py which is called by another function of the same name in checkexpr.py. The erroneous type (Spam instead of builtins.generator) is supplied by infer_arg_types_in_context() called in the same function before in infer_function_type_arguments(). This infer_arg_types_in_context() function calls accept which actually interprets the type correctly when it calls visit_int_expr() defined in checkexpr.py which calls infer_literal_expr_type() also defined in checkexpr.py.
I dont know what is causing the arg_types parameter to be Spam instead of int in infer_function_type_arguments in infer.py. This may be a problem that has to do with Python instead of MyPy but I have no clue. But it may not because Python actually knows what the yield type of generators are when you use the builtin : type() function on *a ( type(*a) --> <class 'int'>)
Should the generator unpacking expression that is erroneous be a mypy.nodes.NameExpr instead of mypy.nodes.NameExpr?
And should the argument kind be a ArgKind.ARG_POS instead of ArgKind.ARG_STAR?
How do you all reckon about this issue? @hauntsaninja @kamilturek @hvenev
JaylenLuc commentedon Aug 30, 2023
im trying to figure out how the * unpacking unary operator works. is [*a.iter()] the same as reveal_type([*a])?
hauntsaninja commentedon Sep 1, 2023
I didn't understand that comment, but my guess is you'd need to trace the code into argmap.py
JaylenLuc commentedon Sep 2, 2023
JaylenLuc commentedon Sep 8, 2023
in checkexpr.py, the function infer_arg_types_in_context() on line 1985 returns [testing.Spam] when it should return typing.Iterator[builtins.int].
mypy/mypy/checkexpr.py
Lines 1984 to 2008 in 8b73cc2
This testing.Spam object is an Instance object where testing.Spam.args length is 0. This means that MyPy thinks testing.Spam has no arguments when it checks in argmap.py line 192 and returns AnyType(TypeOfAny.from_error) on line 217 instead of the result from map_instance_to_supertype().
mypy/mypy/argmap.py
Lines 191 to 219 in 8b73cc2
The main issue is that [*a] cannot be unpacked and thus the types of what the Spam object yields is not unpacked.
how do you all reckon?
hauntsaninja commentedon Sep 8, 2023
Yeah, I'm guessing that code dates back before structural types and Protocols. Probably want to swap out the stuff in argmap for some code from checker that analyses the return type of
__iter__, likeanalyze_iterable_item_type. Might need to thread the checker through to make this workfix issue python#15747
fix issue python#15747 2
JaylenLuc commentedon Sep 14, 2023
submitted a PR. if you check the PR comment I made, the only issues I'm having are with dmypy_server.py which is strange since I don't know how my changes are affecting it.
fix issue python#15747 4
flaeppe commentedon Nov 28, 2023
I think #14470 reports the same thing as well
flaeppe commentedon Nov 28, 2023
And I'm not sure if my quite naive attempt in #14496 could provide any additional insights in how to resolve the issue (or if it resolves the repro case found here)
ilevkivskyi commentedon Feb 10, 2025
Another case when this happens is when a star argument has union type: