@@ -911,9 +911,9 @@ def visit_block(self, b: Block) -> Type:
911911 if b .is_unreachable :
912912 return None
913913 for s in b .body :
914- self .accept (s )
915- if self .binder .breaking_out :
914+ if self .binder .is_unreachable ():
916915 break
916+ self .accept (s )
917917
918918 def visit_assignment_stmt (self , s : AssignmentStmt ) -> Type :
919919 """Type check an assignment statement.
@@ -1354,7 +1354,10 @@ def visit_expression_stmt(self, s: ExpressionStmt) -> Type:
13541354
13551355 def visit_return_stmt (self , s : ReturnStmt ) -> Type :
13561356 """Type check a return statement."""
1357- self .binder .breaking_out = True
1357+ self .check_return_stmt (s )
1358+ self .binder .unreachable ()
1359+
1360+ def check_return_stmt (self , s : ReturnStmt ) -> None :
13581361 if self .is_within_function ():
13591362 if self .function_stack [- 1 ].is_generator :
13601363 return_type = self .get_generator_return_type (self .return_types [- 1 ])
@@ -1422,7 +1425,6 @@ def count_nested_types(self, typ: Instance, check_type: str) -> int:
14221425
14231426 def visit_if_stmt (self , s : IfStmt ) -> Type :
14241427 """Type check an if statement."""
1425- breaking_out = True
14261428 # This frame records the knowledge from previous if/elif clauses not being taken.
14271429 with self .binder .frame_context ():
14281430 for e , b in zip (s .expr , s .body ):
@@ -1444,7 +1446,6 @@ def visit_if_stmt(self, s: IfStmt) -> Type:
14441446 self .binder .push (var , type )
14451447
14461448 self .accept (b )
1447- breaking_out = breaking_out and self .binder .last_pop_breaking_out
14481449
14491450 if else_map :
14501451 for var , type in else_map .items ():
@@ -1460,9 +1461,6 @@ def visit_if_stmt(self, s: IfStmt) -> Type:
14601461 with self .binder .frame_context (2 ):
14611462 if s .else_body :
14621463 self .accept (s .else_body )
1463- breaking_out = breaking_out and self .binder .last_pop_breaking_out
1464- if breaking_out :
1465- self .binder .breaking_out = True
14661464 return None
14671465
14681466 def visit_while_stmt (self , s : WhileStmt ) -> Type :
@@ -1498,11 +1496,11 @@ def visit_assert_stmt(self, s: AssertStmt) -> Type:
14981496
14991497 def visit_raise_stmt (self , s : RaiseStmt ) -> Type :
15001498 """Type check a raise statement."""
1501- self .binder .breaking_out = True
15021499 if s .expr :
15031500 self .type_check_raise (s .expr , s )
15041501 if s .from_expr :
15051502 self .type_check_raise (s .from_expr , s )
1503+ self .binder .unreachable ()
15061504
15071505 def type_check_raise (self , e : Node , s : RaiseStmt ) -> None :
15081506 typ = self .accept (e )
@@ -1535,28 +1533,26 @@ def visit_try_stmt(self, s: TryStmt) -> Type:
15351533 with self .binder .frame_context ():
15361534 if s .finally_body :
15371535 self .binder .try_frames .add (len (self .binder .frames ) - 1 )
1538- breaking_out = self .visit_try_without_finally (s )
1536+ self .visit_try_without_finally (s )
15391537 self .binder .try_frames .remove (len (self .binder .frames ) - 1 )
15401538 # First we check finally_body is type safe for all intermediate frames
15411539 self .accept (s .finally_body )
1542- breaking_out = breaking_out or self .binder .breaking_out
15431540 else :
1544- breaking_out = self .visit_try_without_finally (s )
1541+ self .visit_try_without_finally (s )
15451542
1546- if not breaking_out and s .finally_body :
1543+ if s .finally_body :
15471544 # Then we try again for the more restricted set of options that can fall through
15481545 self .accept (s .finally_body )
1549- self . binder . breaking_out = breaking_out
1546+
15501547 return None
15511548
1552- def visit_try_without_finally (self , s : TryStmt ) -> bool :
1549+ def visit_try_without_finally (self , s : TryStmt ) -> None :
15531550 """Type check a try statement, ignoring the finally block.
15541551
15551552 Return whether we are guaranteed to be breaking out.
15561553 Otherwise, it will place the results possible frames of
15571554 that don't break out into self.binder.frames[-2].
15581555 """
1559- breaking_out = True
15601556 # This frame records the possible states that exceptions can leave variables in
15611557 # during the try: block
15621558 with self .binder .frame_context ():
@@ -1566,7 +1562,6 @@ def visit_try_without_finally(self, s: TryStmt) -> bool:
15661562 self .binder .try_frames .remove (len (self .binder .frames ) - 2 )
15671563 if s .else_body :
15681564 self .accept (s .else_body )
1569- breaking_out = breaking_out and self .binder .last_pop_breaking_out
15701565 for i in range (len (s .handlers )):
15711566 with self .binder .frame_context (3 ):
15721567 if s .types [i ]:
@@ -1592,8 +1587,6 @@ def visit_try_without_finally(self, s: TryStmt) -> bool:
15921587 var = cast (Var , s .vars [i ].node )
15931588 var .type = DeletedType (source = source )
15941589 self .binder .cleanse (s .vars [i ])
1595- breaking_out = breaking_out and self .binder .last_pop_breaking_out
1596- return breaking_out
15971590
15981591 def visit_except_handler_test (self , n : Node ) -> Type :
15991592 """Type check an exception handler test clause."""
@@ -1811,13 +1804,13 @@ def visit_member_expr(self, e: MemberExpr) -> Type:
18111804 return self .expr_checker .visit_member_expr (e )
18121805
18131806 def visit_break_stmt (self , s : BreakStmt ) -> Type :
1814- self .binder .breaking_out = True
18151807 self .binder .allow_jump (self .binder .loop_frames [- 1 ] - 1 )
1808+ self .binder .unreachable ()
18161809 return None
18171810
18181811 def visit_continue_stmt (self , s : ContinueStmt ) -> Type :
1819- self .binder .breaking_out = True
18201812 self .binder .allow_jump (self .binder .loop_frames [- 1 ])
1813+ self .binder .unreachable ()
18211814 return None
18221815
18231816 def visit_int_expr (self , e : IntExpr ) -> Type :
0 commit comments