Skip to content

Commit 8b6d213

Browse files
authored
Fix partially defined in the case of missing type maps (#15995)
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.
1 parent e87b62f commit 8b6d213

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

mypy/partially_defined.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ def visit_break_stmt(self, o: BreakStmt) -> None:
506506
self.tracker.skip_branch()
507507

508508
def visit_expression_stmt(self, o: ExpressionStmt) -> None:
509-
if isinstance(self.type_map.get(o.expr, None), UninhabitedType):
509+
if isinstance(self.type_map.get(o.expr, None), (UninhabitedType, type(None))):
510510
self.tracker.skip_branch()
511511
super().visit_expression_stmt(o)
512512

test-data/unit/check-possibly-undefined.test

+17
Original file line numberDiff line numberDiff line change
@@ -1026,3 +1026,20 @@ class B:
10261026
else:
10271027
# Same as above but in a loop.
10281028
b = a # E: Name "a" may be undefined
1029+
1030+
[case testUnreachableCausingMissingTypeMap]
1031+
# flags: --enable-error-code possibly-undefined --enable-error-code used-before-def --no-warn-unreachable
1032+
# Regression test for https://github.com/python/mypy/issues/15958
1033+
from typing import Union, NoReturn
1034+
1035+
def assert_never(__x: NoReturn) -> NoReturn: ...
1036+
1037+
def foo(x: Union[int, str]) -> None:
1038+
if isinstance(x, str):
1039+
f = "foo"
1040+
elif isinstance(x, int):
1041+
f = "bar"
1042+
else:
1043+
assert_never(x)
1044+
f # OK
1045+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)