Skip to content

Commit 1bda6f5

Browse files
author
Guido van Rossum
committed
Apply the fix propsed by @ecprice instead. With tests
1 parent 38ff8a0 commit 1bda6f5

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

mypy/checker.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ def check_second_pass(self) -> bool:
202202
for node, type_name in todo:
203203
if node in done:
204204
continue
205+
## print('REDO %d %s.%s' %
206+
## (self.pass_num, type_name or '', node.fullname() or node.name()))
205207
done.add(node)
206208
if type_name:
207209
self.errors.push_type(type_name)
@@ -1704,7 +1706,12 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
17041706
# To support local variables, we make this a definition line,
17051707
# causing assignment to set the variable's type.
17061708
s.vars[i].is_def = True
1709+
# We also temporarily set current_node_deferred to False to
1710+
# make sure the inference happens.
1711+
am_deferring = self.current_node_deferred
1712+
self.current_node_deferred = False
17071713
self.check_assignment(s.vars[i], self.temp_node(t, s.vars[i]))
1714+
self.current_node_deferred = am_deferring
17081715
self.accept(s.handlers[i])
17091716
if s.vars[i]:
17101717
# Exception variables are deleted in python 3 but not python 2.
@@ -1720,8 +1727,7 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
17201727
'accept outside except: blocks even in '
17211728
'python 2)'.format(s.vars[i].name))
17221729
var = cast(Var, s.vars[i].node)
1723-
if not self.current_node_deferred:
1724-
var.type = DeletedType(source=source)
1730+
var.type = DeletedType(source=source)
17251731
self.binder.cleanse(s.vars[i])
17261732
if s.else_body:
17271733
self.accept(s.else_body)

test-data/unit/check-statements.test

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,79 @@ def f(*a: BaseException) -> int:
717717
x = f()
718718
[builtins fixtures/exception.pyi]
719719

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+
720793

721794
[case testArbitraryExpressionAsExceptionType]
722795
import typing

0 commit comments

Comments
 (0)