@@ -375,7 +375,7 @@ class SemanticAnalyzer(
375375 missing_names : list [set [str ]]
376376 # Callbacks that will be called after semantic analysis to tweak things.
377377 patches : list [tuple [int , Callable [[], None ]]]
378- loop_depth = 0 # Depth of breakable loops
378+ loop_depth : list [ int ] # Depth of breakable loops
379379 cur_mod_id = "" # Current module id (or None) (phase 2)
380380 _is_stub_file = False # Are we analyzing a stub file?
381381 _is_typeshed_stub_file = False # Are we analyzing a typeshed stub file?
@@ -428,7 +428,7 @@ def __init__(
428428 self .tvar_scope = TypeVarLikeScope ()
429429 self .function_stack = []
430430 self .block_depth = [0 ]
431- self .loop_depth = 0
431+ self .loop_depth = [ 0 ]
432432 self .errors = errors
433433 self .modules = modules
434434 self .msg = MessageBuilder (errors , modules )
@@ -1808,12 +1808,14 @@ def enter_class(self, info: TypeInfo) -> None:
18081808 self .locals .append (None ) # Add class scope
18091809 self .is_comprehension_stack .append (False )
18101810 self .block_depth .append (- 1 ) # The class body increments this to 0
1811+ self .loop_depth .append (0 )
18111812 self ._type = info
18121813 self .missing_names .append (set ())
18131814
18141815 def leave_class (self ) -> None :
18151816 """Restore analyzer state."""
18161817 self .block_depth .pop ()
1818+ self .loop_depth .pop ()
18171819 self .locals .pop ()
18181820 self .is_comprehension_stack .pop ()
18191821 self ._type = self .type_stack .pop ()
@@ -3219,7 +3221,7 @@ def unwrap_final(self, s: AssignmentStmt) -> bool:
32193221 if lval .is_new_def :
32203222 lval .is_inferred_def = s .type is None
32213223
3222- if self .loop_depth > 0 :
3224+ if self .loop_depth [ - 1 ] > 0 :
32233225 self .fail ("Cannot use Final inside a loop" , s )
32243226 if self .type and self .type .is_protocol :
32253227 self .msg .protocol_members_cant_be_final (s )
@@ -4698,9 +4700,9 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
46984700 def visit_while_stmt (self , s : WhileStmt ) -> None :
46994701 self .statement = s
47004702 s .expr .accept (self )
4701- self .loop_depth += 1
4703+ self .loop_depth [ - 1 ] += 1
47024704 s .body .accept (self )
4703- self .loop_depth -= 1
4705+ self .loop_depth [ - 1 ] -= 1
47044706 self .visit_block_maybe (s .else_body )
47054707
47064708 def visit_for_stmt (self , s : ForStmt ) -> None :
@@ -4722,20 +4724,20 @@ def visit_for_stmt(self, s: ForStmt) -> None:
47224724 self .store_declared_types (s .index , analyzed )
47234725 s .index_type = analyzed
47244726
4725- self .loop_depth += 1
4727+ self .loop_depth [ - 1 ] += 1
47264728 self .visit_block (s .body )
4727- self .loop_depth -= 1
4729+ self .loop_depth [ - 1 ] -= 1
47284730
47294731 self .visit_block_maybe (s .else_body )
47304732
47314733 def visit_break_stmt (self , s : BreakStmt ) -> None :
47324734 self .statement = s
4733- if self .loop_depth == 0 :
4735+ if self .loop_depth [ - 1 ] == 0 :
47344736 self .fail ('"break" outside loop' , s , serious = True , blocker = True )
47354737
47364738 def visit_continue_stmt (self , s : ContinueStmt ) -> None :
47374739 self .statement = s
4738- if self .loop_depth == 0 :
4740+ if self .loop_depth [ - 1 ] == 0 :
47394741 self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
47404742
47414743 def visit_if_stmt (self , s : IfStmt ) -> None :
@@ -6230,6 +6232,7 @@ def enter(
62306232 self .nonlocal_decls .append (set ())
62316233 # -1 since entering block will increment this to 0.
62326234 self .block_depth .append (- 1 )
6235+ self .loop_depth .append (0 )
62336236 self .missing_names .append (set ())
62346237 try :
62356238 yield
@@ -6239,6 +6242,7 @@ def enter(
62396242 self .global_decls .pop ()
62406243 self .nonlocal_decls .pop ()
62416244 self .block_depth .pop ()
6245+ self .loop_depth .pop ()
62426246 self .missing_names .pop ()
62436247
62446248 def is_func_scope (self ) -> bool :
0 commit comments