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
Fix incorrect tracking of "final" Instances (#6763)
* Refine how Literal and Final interact
This diff makes three changes: it fixes a bug where we incorrectly
track "final" Instances, does some related refactoring, and finally
modifies tuple indexing to be aware of literal contexts.
Specifically, here is an example of the bug. Note that mypy ignores
the mutable nature of `bar`:
def expect_3(x: Literal[3]) -> None: ...
foo: Final = 3
bar = foo
for i in range(10):
bar = i
# Currently type-check; this PR makes mypy correctly report an error
expect_3(bar)
To fix this bug, I decided to adjust the variable assignment logic: if
the variable is non-final, we now scan the inferred type we try assigning
and recursively erase all set `instance.final_value` fields.
This change ended up making the `in_final_declaration` field redundant
-- after all, we're going to be actively erasing types on non-final
assignments anyways. So, I decided to just remove this field.
I suspect this change will also result in some nice dividends down the
road: defaulting to preserving the underlying literal when inferring
expression types will probably make it easier to add more sophisticated
literal-related inference down the road.
In the process of implementing the above two, I discovered that "nested"
Instance types are effectively ignored. So, the following program does
not type check, despite the `Final` and despite that tuples are
immutable:
bar: Final = (3, 2, 1)
# 'bar[0] == 3' is always true, but we currently report an error
expect_3(bar[0])
This is mildly annoying, and also made it slightly harder for me to
verify my changes above, so I decided to modify `visit_index_expr` to
also examine the literal context.
(Actually, I found I could move this check directly into the 'accept'
method instead of special-casing things within `visit_index_expr` and
`analyze_var_ref`. But I decided against this approach: the
special-casing feels less intrusive, easier to audit, and slightly
more efficient.)
* Rename 'final_value' field to 'last_known_value'
* Adjust one existing test
0 commit comments