Re-broaden type to Any if it started as Any but was narrowed in an enclosing frame #3361
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #3338.
My investigation notes:
The explanation is that the bug is caused by an interaction between
most_recent_enclosing_type
and its caller,assign_type
.assign_type
has a special case for when the most recent enclosing type is Any, commented with the following note: "If x is Any and y is int, after x = y we do not infer that x is int. This could be changed." The special case does nothing (the normal case assigns the inferred type to the variable).In my test case,
most_recent_enclosing_type
misses the frame which reassignsv
becauseint
is not a subtype ofstr
, and so returns Any and so the special case applies (this explains why declaring with type Union doesn't reproduce the problem). So it doesn't assign any new type for this assignment, causing the bug.I took the approach of fixing that special case so if
type
is not bound to Any at the moment of assignment, it re-binds it to Any (or, really, whatever is the result ofmost_recent_enclosing_type
).Another approach might be to remove the subtype check from most_recent_enclosing_type. https://github.com/python/mypy/compare/master...lincolnq:lincoln/remove-subtype-check-from-binder?expand=1 is where I tried that. I thought that change was more aggressive / likely to break things, and I didn't understand why the subtype check was put there in the first place. But it has the desirable (to me) property of inferring
int
on the reassignment rather thanAny
.Both approaches pass the automated tests.