Skip to content

Commit a1ed9c3

Browse files
committed
Avoid false possibly-undefined errors due to omitted unrequired else statements.
1 parent 1698432 commit a1ed9c3

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

mypy/checker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5036,6 +5036,8 @@ def visit_if_stmt(self, s: IfStmt) -> None:
50365036

50375037
if_map, else_map = self.find_isinstance_check(e)
50385038

5039+
s.else_irrelevant_for_possibly_undefined = else_map is None
5040+
50395041
# XXX Issue a warning if condition is always False?
50405042
with self.binder.frame_context(can_skip=True, fall_through=2):
50415043
self.push_type_map(if_map, from_assignment=False)

mypy/nodes.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,19 +1792,21 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
17921792

17931793

17941794
class IfStmt(Statement):
1795-
__slots__ = ("expr", "body", "else_body")
1795+
__slots__ = ("expr", "body", "else_body", "else_irrelevant_for_possibly_undefined")
17961796

1797-
__match_args__ = ("expr", "body", "else_body")
1797+
__match_args__ = ("expr", "body", "else_body", "else_body_irrelevant_for_possibly_undefined")
17981798

17991799
expr: list[Expression]
18001800
body: list[Block]
18011801
else_body: Block | None
1802+
else_irrelevant_for_possibly_undefined: bool
18021803

18031804
def __init__(self, expr: list[Expression], body: list[Block], else_body: Block | None) -> None:
18041805
super().__init__()
18051806
self.expr = expr
18061807
self.body = body
18071808
self.else_body = else_body
1809+
self.else_irrelevant_for_possibly_undefined = False
18081810

18091811
def accept(self, visitor: StatementVisitor[T]) -> T:
18101812
return visitor.visit_if_stmt(self)

mypy/partially_defined.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,13 @@ def visit_if_stmt(self, o: IfStmt) -> None:
395395
continue
396396
b.accept(self)
397397
self.tracker.next_branch()
398-
if o.else_body:
399-
if not o.else_body.is_unreachable:
400-
o.else_body.accept(self)
401-
else:
398+
if o.else_irrelevant_for_possibly_undefined:
399+
self.tracker.skip_branch()
400+
elif o.else_body:
401+
if o.else_body.is_unreachable:
402402
self.tracker.skip_branch()
403+
else:
404+
o.else_body.accept(self)
403405
self.tracker.end_branch_statement()
404406

405407
def visit_match_stmt(self, o: MatchStmt) -> None:

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,3 +1043,27 @@ def foo(x: Union[int, str]) -> None:
10431043
assert_never(x)
10441044
f # OK
10451045
[builtins fixtures/tuple.pyi]
1046+
1047+
[case testOmittedUnrequiredElse]
1048+
# flags: --enable-error-code possibly-undefined
1049+
from typing import Literal
1050+
1051+
a: Literal[True]
1052+
if a:
1053+
w = 1
1054+
w + 1
1055+
1056+
b: bool
1057+
if b:
1058+
x = 1
1059+
elif not b:
1060+
x = 2
1061+
x + 1
1062+
1063+
if b:
1064+
y = 1
1065+
elif not b:
1066+
if a:
1067+
z = 2
1068+
y = z
1069+
y + 1

0 commit comments

Comments
 (0)