Skip to content

Commit

Permalink
Fix: else of while loop is executed if body is not executed
Browse files Browse the repository at this point in the history
  • Loading branch information
NMertsch committed Sep 10, 2024
1 parent e593bc8 commit 730e65a
Showing 1 changed file with 25 additions and 17 deletions.
42 changes: 25 additions & 17 deletions mypy/partially_defined.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,27 +576,35 @@ def process_try_stmt(self, o: TryStmt) -> None:

def visit_while_stmt(self, o: WhileStmt) -> None:
o.expr.accept(self)
self.tracker.start_branch_statement()
loop = Loop()
self.loops.append(loop)
o.body.accept(self)
has_break = loop.has_break
if not checker.is_true_literal(o.expr):
# If this is a loop like `while True`, we can consider the body to be
# a single branch statement (we're guaranteed that the body is executed at least once).
# If not, call next_branch() to make all variables defined there conditional.

if checker.is_true_literal(o.expr):
# `while True` loop:
# - body is always executed
# - `else` is never executed
o.body.accept(self)
else:
# body is executed conditionally: if expression was True on first evaluation
self.tracker.start_branch_statement()
o.body.accept(self)
self.tracker.next_branch()
self.tracker.end_branch_statement()
if o.else_body is not None:
# If the loop has a `break` inside, `else` is executed conditionally.
# If the loop doesn't have a `break` either the function will return or
# execute the `else`.
if has_break:
self.tracker.start_branch_statement()
self.tracker.next_branch()
o.else_body.accept(self)
if has_break:

if o.else_body is None:
self.tracker.end_branch_statement()
else:
if loop.has_break:
# `else` is executed conditionally:
# - if expression was False on first evaluation
# - if `break` was not executed
o.else_body.accept(self)
self.tracker.end_branch_statement()
else:
# `else` is always executed:
# - if expression was False on first evaluation
# - if expression was True on first evaluation (there is no break)
self.tracker.end_branch_statement()
o.else_body.accept(self)
self.loops.pop()

def visit_as_pattern(self, o: AsPattern) -> None:
Expand Down

0 comments on commit 730e65a

Please sign in to comment.