Skip to content

Commit eb49662

Browse files
authored
Fix possibly-undefined false-positive with nesting (#20276)
Closes #14309, #17055 commit 3f1c0f8 adds a test that demonstrates the false-positive commit acb345a fixes the false-positive based on the suggestion in #14309 (comment)
1 parent 9a03b81 commit eb49662

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

mypy/partially_defined.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,13 @@ def __init__(self) -> None:
206206
# disable_branch_skip is used to disable skipping a branch due to a return/raise/etc. This is useful
207207
# in things like try/except/finally statements.
208208
self.disable_branch_skip = False
209+
self.in_finally = False
209210

210211
def copy(self) -> DefinedVariableTracker:
211212
result = DefinedVariableTracker()
212213
result.scopes = [s.copy() for s in self.scopes]
213214
result.disable_branch_skip = self.disable_branch_skip
215+
result.in_finally = self.in_finally
214216
return result
215217

216218
def _scope(self) -> Scope:
@@ -579,7 +581,9 @@ def process_try_stmt(self, o: TryStmt) -> None:
579581
self.tracker.end_branch_statement()
580582

581583
if o.finally_body is not None:
584+
self.tracker.in_finally = True
582585
o.finally_body.accept(self)
586+
self.tracker.in_finally = False
583587

584588
def visit_while_stmt(self, o: WhileStmt) -> None:
585589
o.expr.accept(self)
@@ -620,7 +624,10 @@ def visit_starred_pattern(self, o: StarredPattern) -> None:
620624
def visit_name_expr(self, o: NameExpr) -> None:
621625
if o.name in self.builtins and self.tracker.in_scope(ScopeType.Global):
622626
return
623-
if self.tracker.is_possibly_undefined(o.name):
627+
if (
628+
self.tracker.is_possibly_undefined(o.name)
629+
and self.tracker.in_finally == self.tracker.disable_branch_skip
630+
):
624631
# A variable is only defined in some branches.
625632
self.variable_may_be_undefined(o.name, o)
626633
# We don't want to report the error on the same variable multiple times.

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ def f7() -> int:
628628
x = 1
629629
assert False
630630
except:
631-
pass
631+
y = x # E: Name "x" may be undefined
632632
return x # E: Name "x" may be undefined
633633
[builtins fixtures/exception.pyi]
634634

@@ -678,7 +678,7 @@ def f3() -> int:
678678
pass
679679
finally:
680680
y = x # E: Name "x" may be undefined
681-
return x
681+
return x # E: Name "x" may be undefined
682682

683683
def f4() -> int:
684684
try:
@@ -708,6 +708,17 @@ def f6() -> int:
708708
finally:
709709
a = x # E: Name "x" may be undefined
710710
return a
711+
712+
def f7() -> int:
713+
try:
714+
if int():
715+
x = 1
716+
else:
717+
raise BaseException
718+
return x # No error.
719+
finally:
720+
y = x # E: Name "x" may be undefined
721+
return 0
711722
[builtins fixtures/exception.pyi]
712723

713724
[case testTryElse]

0 commit comments

Comments
 (0)