Skip to content

Commit 8fb482f

Browse files
authored
[partially defined] handle unreachable blocks (#14161)
This adds support for unreachable blocks in `partially-defined` check. Currently, this only supports blocks that are detected as unreachable during semantic analysis (so mostly stuff like python version, etc.). This doesn't support more advanced cases (see #13926 for an example what's not covered). Closes #13929
1 parent b83ac9c commit 8fb482f

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

mypy/partially_defined.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,13 @@ def visit_if_stmt(self, o: IfStmt) -> None:
203203
e.accept(self)
204204
self.tracker.start_branch_statement()
205205
for b in o.body:
206+
if b.is_unreachable:
207+
continue
206208
b.accept(self)
207209
self.tracker.next_branch()
208210
if o.else_body:
211+
if o.else_body.is_unreachable:
212+
self.tracker.skip_branch()
209213
o.else_body.accept(self)
210214
self.tracker.end_branch_statement()
211215

@@ -218,7 +222,10 @@ def visit_match_stmt(self, o: MatchStmt) -> None:
218222
guard = o.guards[i]
219223
if guard is not None:
220224
guard.accept(self)
221-
o.bodies[i].accept(self)
225+
if not o.bodies[i].is_unreachable:
226+
o.bodies[i].accept(self)
227+
else:
228+
self.tracker.skip_branch()
222229
is_catchall = infer_pattern_value(pattern) == ALWAYS_TRUE
223230
if not is_catchall:
224231
self.tracker.next_branch()

test-data/unit/check-partially-defined.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,22 @@ def f() -> None:
367367
d = a
368368
d = b
369369
[builtins fixtures/tuple.pyi]
370+
371+
[case testUnreachable]
372+
# flags: --enable-error-code partially-defined
373+
import typing
374+
375+
if typing.TYPE_CHECKING:
376+
x = 1
377+
elif int():
378+
y = 1
379+
else:
380+
y = 2
381+
a = x
382+
383+
if not typing.TYPE_CHECKING:
384+
pass
385+
else:
386+
z = 1
387+
a = z
388+
[typing fixtures/typing-medium.pyi]

test-data/unit/check-python310.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,30 @@ def f6(a: object) -> None:
17891789
pass
17901790
[builtins fixtures/tuple.pyi]
17911791

1792+
[case testPartiallyDefinedMatchUnreachable]
1793+
# flags: --enable-error-code partially-defined
1794+
import typing
1795+
1796+
def f0(x: int) -> int:
1797+
match x:
1798+
case 1 if not typing.TYPE_CHECKING:
1799+
pass
1800+
case 2:
1801+
y = 2
1802+
case _:
1803+
y = 3
1804+
return y # No error.
1805+
1806+
def f1(x: int) -> int:
1807+
match x:
1808+
case 1 if not typing.TYPE_CHECKING:
1809+
pass
1810+
case 2:
1811+
y = 2
1812+
return y # E: Name "y" may be undefined
1813+
1814+
[typing fixtures/typing-medium.pyi]
1815+
17921816
[case testTypeAliasWithNewUnionSyntaxAndNoneLeftOperand]
17931817
from typing import overload
17941818
class C:

0 commit comments

Comments
 (0)