diff --git a/mypy/checker.py b/mypy/checker.py index 63e128f78310..163252829f94 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5036,6 +5036,8 @@ def visit_if_stmt(self, s: IfStmt) -> None: if_map, else_map = self.find_isinstance_check(e) + s.unreachable_else = else_map is None + # XXX Issue a warning if condition is always False? with self.binder.frame_context(can_skip=True, fall_through=2): self.push_type_map(if_map, from_assignment=False) diff --git a/mypy/nodes.py b/mypy/nodes.py index 040f3fc28dce..4cbd7fbb8fa2 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1792,19 +1792,21 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class IfStmt(Statement): - __slots__ = ("expr", "body", "else_body") + __slots__ = ("expr", "body", "else_body", "unreachable_else") - __match_args__ = ("expr", "body", "else_body") + __match_args__ = ("expr", "body", "else_body", "unreachable_else") expr: list[Expression] body: list[Block] else_body: Block | None + unreachable_else: bool def __init__(self, expr: list[Expression], body: list[Block], else_body: Block | None) -> None: super().__init__() self.expr = expr self.body = body self.else_body = else_body + self.unreachable_else = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_if_stmt(self) diff --git a/mypy/partially_defined.py b/mypy/partially_defined.py index 38154cf697e1..fad1f79493ad 100644 --- a/mypy/partially_defined.py +++ b/mypy/partially_defined.py @@ -395,11 +395,13 @@ def visit_if_stmt(self, o: IfStmt) -> None: continue b.accept(self) self.tracker.next_branch() - if o.else_body: - if not o.else_body.is_unreachable: - o.else_body.accept(self) - else: + if o.unreachable_else: + self.tracker.skip_branch() + elif o.else_body: + if o.else_body.is_unreachable: self.tracker.skip_branch() + else: + o.else_body.accept(self) self.tracker.end_branch_statement() def visit_match_stmt(self, o: MatchStmt) -> None: diff --git a/test-data/unit/check-possibly-undefined.test b/test-data/unit/check-possibly-undefined.test index ae277949c049..fb2edc39aa15 100644 --- a/test-data/unit/check-possibly-undefined.test +++ b/test-data/unit/check-possibly-undefined.test @@ -1043,3 +1043,27 @@ def foo(x: Union[int, str]) -> None: assert_never(x) f # OK [builtins fixtures/tuple.pyi] + +[case testOmittedUnrequiredElse] +# flags: --enable-error-code possibly-undefined +from typing import Literal + +a: Literal[True] +if a: + w = 1 +w + 1 + +b: bool +if b: + x = 1 +elif not b: + x = 2 +x + 1 + +if b: + y = 1 +elif not b: + if a: + z = 2 + y = z +y + 1