-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Direct assignment from lambda doesn't narrow type correctly #11029
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
In general, it's not safe to apply narrowed types to variables that are captured and used in an independent execution scope because the execution time of that execution scope is not known. Consider, for example, if you made the following change to your sample. def foo(bar: Union[int, Callable[[], int]]) -> int:
int_fn: Callable[[], int]
if callable(bar):
int_fn = bar
else:
reveal_type(bar)
int_fn = lambda: bar
bar = lambda: 3 # Reassign bar here
return int_fn() The recommended workaround in this case is to assign the narrowed type to a local variable, which can then be captured by the lambda. def foo(bar: Union[int, Callable[[], int]]) -> int:
int_fn: Callable[[], int]
if callable(bar):
int_fn = bar
else:
x = bar
int_fn = lambda: x
return int_fn() |
Ah thank you Eric, that's very interesting! Sounds like this isn't a bug in that case - I'll close the issue :) |
Apologies @erictraut, I thought that I understood why the workaround that I described in my original report works, but I'm now convinced that it actually is a bug. Consider this example from collections.abc import Callable
from typing import Union
def foo(bar: Union[int, Callable[[], int]]) -> int:
int_fn: Callable[[], int]
if callable(bar):
int_fn = bar
else:
intermediate = lambda: bar
int_fn = intermediate
bar = lambda: 3 # Reassign bar here
return int_fn()
print(foo(2)) Mypy doesn't complain about this code, but This does seem like a bug? |
Yes, I agree that's a bug, but this appears to be different from the one you originally reported. In your original example, mypy was not applying narrowing in a situation where it should not, so it was doing the right thing. In this case, it is applying narrowing in a situation where it should not — namely, when inferring the type of For comparison, mypy infers the type of |
Yes I agree that this is different from what I originally reported - apologies. Do you reckon I should close this issue and raise a new one? |
(Might be a duplicate of #10993)
Bug Report
Assigning a lambda function to a variable typed as e.g.
Callable[[], int]
doesn't always work if the lambda returns a variable whose type has been previously narrowed to e.g.int
. This behaviour does not remain if the lambda returns a literal e.g.int
, or if an intermediate variable is introduced.To Reproduce
Expected Behavior
There should be no mypy errors.
Actual Behavior
There were mypy errors (I've left the
reveal_type
in for illustration):These errors do not remain if line 10 is replaced with e.g.
int_fn = lambda: 1
.In addition, these errors do not remain if line 10 is replaced with an intermediate assignment, e.g.:
Your Environment
The text was updated successfully, but these errors were encountered: