Skip to content

Commit

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

It turns out 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 committed Aug 30, 2023
1 parent 5783af4 commit 1813d5a
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 1813d5a

Please sign in to comment.