Skip to content

Commit

Permalink
Fix partially defined in the case of missing type maps (#15995)
Browse files Browse the repository at this point in the history
Thanks AlexWaygood for sending me on this adventure. This took me a
while for me to debug!

When we don't need to warn about unreachable code, we don't end up
calling `self.is_noop_for_reachability(s)` (which is meant to tell us
whether the code should be warned about or is `raise AssertionError` or
`typing.assert_never(never)` or something).
https://github.com/python/mypy/blob/6f650cff9ab21f81069e0ae30c92eae94219ea63/mypy/checker.py#L2748

This innocuous check has a side effect that turns out to be important
for the partially undefined checks. These checks work by reaching into
the type map populated by the checker. But if we never actually ended up
analysing the code, we never populate the type map.

This therefore changes things to assume that if we couldn't find the
expression in the type map, it's probably because it was unreachable.
  • Loading branch information
hauntsaninja authored Oct 10, 2023
1 parent e87b62f commit 8b6d213
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
2 changes: 1 addition & 1 deletion mypy/partially_defined.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def visit_break_stmt(self, o: BreakStmt) -> None:
self.tracker.skip_branch()

def visit_expression_stmt(self, o: ExpressionStmt) -> None:
if isinstance(self.type_map.get(o.expr, None), UninhabitedType):
if isinstance(self.type_map.get(o.expr, None), (UninhabitedType, type(None))):
self.tracker.skip_branch()
super().visit_expression_stmt(o)

Expand Down
17 changes: 17 additions & 0 deletions test-data/unit/check-possibly-undefined.test
Original file line number Diff line number Diff line change
Expand Up @@ -1026,3 +1026,20 @@ class B:
else:
# Same as above but in a loop.
b = a # E: Name "a" may be undefined

[case testUnreachableCausingMissingTypeMap]
# flags: --enable-error-code possibly-undefined --enable-error-code used-before-def --no-warn-unreachable
# Regression test for https://github.com/python/mypy/issues/15958
from typing import Union, NoReturn

def assert_never(__x: NoReturn) -> NoReturn: ...

def foo(x: Union[int, str]) -> None:
if isinstance(x, str):
f = "foo"
elif isinstance(x, int):
f = "bar"
else:
assert_never(x)
f # OK
[builtins fixtures/tuple.pyi]

0 comments on commit 8b6d213

Please sign in to comment.