Skip to content

Commit

Permalink
[partially defined] use correct error code in nested if statements (#…
Browse files Browse the repository at this point in the history
…14193)

In order to know to use `partially-defined` code vs `use-before-def`, we
had to check if a variable is defined in any branches, not just in the
current one.
This would cause an error to be reported as a `use-before-def` and not
`partially-defined` code.
  • Loading branch information
ilinum authored Nov 27, 2022
1 parent a82c288 commit 5c3d306
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
14 changes: 9 additions & 5 deletions mypy/partially_defined.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,9 @@ def is_undefined(self, name: str) -> bool:
branch = self.branches[-1]
return name not in branch.may_be_defined and name not in branch.must_be_defined

def is_defined_in_different_branch(self, name: str) -> bool:
def is_defined_in_a_branch(self, name: str) -> bool:
assert len(self.branches) > 0
if not self.is_undefined(name):
return False
for b in self.branches[: len(self.branches) - 1]:
for b in self.branches:
if name in b.must_be_defined or name in b.may_be_defined:
return True
return False
Expand Down Expand Up @@ -213,7 +211,13 @@ def is_partially_defined(self, name: str) -> bool:
def is_defined_in_different_branch(self, name: str) -> bool:
"""This will return true if a variable is defined in a branch that's not the current branch."""
assert len(self._scope().branch_stmts) > 0
return self._scope().branch_stmts[-1].is_defined_in_different_branch(name)
stmt = self._scope().branch_stmts[-1]
if not stmt.is_undefined(name):
return False
for stmt in self._scope().branch_stmts:
if stmt.is_defined_in_a_branch(name):
return True
return False

def is_undefined(self, name: str) -> bool:
assert len(self._scope().branch_stmts) > 0
Expand Down
25 changes: 22 additions & 3 deletions test-data/unit/check-partially-defined.test
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,19 @@ def f1() -> None:
else:
y = x # No error.

def f2() -> None:
if int():
x = 0
elif int():
y = x # E: Name "x" is used before definition
else:
y = x # E: Name "x" is used before definition
if int():
z = x # E: Name "x" is used before definition
x = 1
else:
x = 2
w = x # No error.

[case testDefinedDifferentBranchPartiallyDefined]
# flags: --enable-error-code partially-defined --enable-error-code use-before-def
Expand All @@ -295,11 +308,17 @@ def f0() -> None:
if first_iter:
first_iter = False
x = 0
else:
elif int():
# This is technically a false positive but mypy isn't smart enough for this yet.
y = x # E: Name "x" may be undefined
z = x # E: Name "x" may be undefined

else:
y = x # E: Name "x" may be undefined
if int():
z = x # E: Name "x" may be undefined
x = 1
else:
x = 2
w = x # No error.

def f1() -> None:
while True:
Expand Down

0 comments on commit 5c3d306

Please sign in to comment.