Skip to content

Commit 91faa26

Browse files
authored
Fix bug with exception variable reuse in deferred node. (#2290)
* Fix bug with exception variable reuse in deferred node. The fix is actually by @ecprice. See #1748 (comment)
1 parent b616268 commit 91faa26

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

mypy/checker.py

+7
Original file line numberDiff line numberDiff line change
@@ -1680,7 +1680,14 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
16801680
# To support local variables, we make this a definition line,
16811681
# causing assignment to set the variable's type.
16821682
s.vars[i].is_def = True
1683+
# We also temporarily set current_node_deferred to False to
1684+
# make sure the inference happens.
1685+
# TODO: Use a better solution, e.g. a
1686+
# separate Var for each except block.
1687+
am_deferring = self.current_node_deferred
1688+
self.current_node_deferred = False
16831689
self.check_assignment(s.vars[i], self.temp_node(t, s.vars[i]))
1690+
self.current_node_deferred = am_deferring
16841691
self.accept(s.handlers[i])
16851692
if s.vars[i]:
16861693
# Exception variables are deleted in python 3 but not python 2.

test-data/unit/check-statements.test

+104
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,110 @@ e = 1 # E: Assignment to variable 'e' outside except: block
687687
e = E1() # E: Assignment to variable 'e' outside except: block
688688
[builtins fixtures/exception.pyi]
689689

690+
[case testExceptionVariableReuseInDeferredNode1]
691+
def f(*a: BaseException) -> int:
692+
x
693+
try: pass
694+
except BaseException as err: pass
695+
try: pass
696+
except BaseException as err: f(err)
697+
x = f()
698+
[builtins fixtures/exception.pyi]
699+
700+
[case testExceptionVariableReuseInDeferredNode2]
701+
def f(*a: BaseException) -> int:
702+
try: pass
703+
except BaseException as err: pass
704+
x
705+
try: pass
706+
except BaseException as err: f(err)
707+
x = f()
708+
[builtins fixtures/exception.pyi]
709+
710+
[case testExceptionVariableReuseInDeferredNode3]
711+
def f(*a: BaseException) -> int:
712+
try: pass
713+
except BaseException as err: pass
714+
try: pass
715+
except BaseException as err: f(err)
716+
x
717+
x = f()
718+
[builtins fixtures/exception.pyi]
719+
720+
[case testExceptionVariableReuseInDeferredNode4]
721+
class EA(BaseException):
722+
a = None # type: int
723+
class EB(BaseException):
724+
b = None # type: str
725+
def f(*arg: BaseException) -> int:
726+
x
727+
try: pass
728+
except EA as err:
729+
f(err)
730+
a = err.a
731+
reveal_type(a)
732+
try: pass
733+
except EB as err:
734+
f(err)
735+
b = err.b
736+
reveal_type(b)
737+
x = f()
738+
[builtins fixtures/exception.pyi]
739+
[out]
740+
main: note: In function "f":
741+
main:11: error: Revealed type is 'builtins.int'
742+
main:16: error: Revealed type is 'builtins.str'
743+
744+
[case testExceptionVariableReuseInDeferredNode5]
745+
class EA(BaseException):
746+
a = None # type: int
747+
class EB(BaseException):
748+
b = None # type: str
749+
def f(*arg: BaseException) -> int:
750+
try: pass
751+
except EA as err:
752+
f(err)
753+
a = err.a
754+
reveal_type(a)
755+
x
756+
try: pass
757+
except EB as err:
758+
f(err)
759+
b = err.b
760+
reveal_type(b)
761+
x = f()
762+
[builtins fixtures/exception.pyi]
763+
[out]
764+
main: note: In function "f":
765+
main:10: error: Revealed type is 'builtins.int'
766+
main:16: error: Revealed type is 'builtins.str'
767+
768+
[case testExceptionVariableReuseInDeferredNode6]
769+
class EA(BaseException):
770+
a = None # type: int
771+
class EB(BaseException):
772+
b = None # type: str
773+
def f(*arg: BaseException) -> int:
774+
try: pass
775+
except EA as err:
776+
f(err)
777+
a = err.a
778+
reveal_type(a)
779+
try: pass
780+
except EB as err:
781+
f(err)
782+
b = err.b
783+
reveal_type(b)
784+
x
785+
x = f()
786+
[builtins fixtures/exception.pyi]
787+
[out]
788+
main: note: In function "f":
789+
main:10: error: Revealed type is 'builtins.int'
790+
main:15: error: Revealed type is 'builtins.str'
791+
792+
793+
690794
[case testArbitraryExpressionAsExceptionType]
691795
import typing
692796
a = BaseException

0 commit comments

Comments
 (0)