@@ -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 )
@@ -1810,12 +1810,14 @@ def enter_class(self, info: TypeInfo) -> None:
18101810 self .locals .append (None ) # Add class scope
18111811 self .is_comprehension_stack .append (False )
18121812 self .block_depth .append (- 1 ) # The class body increments this to 0
1813+ self .loop_depth .append (0 )
18131814 self ._type = info
18141815 self .missing_names .append (set ())
18151816
18161817 def leave_class (self ) -> None :
18171818 """Restore analyzer state."""
18181819 self .block_depth .pop ()
1820+ self .loop_depth .pop ()
18191821 self .locals .pop ()
18201822 self .is_comprehension_stack .pop ()
18211823 self ._type = self .type_stack .pop ()
@@ -3221,7 +3223,7 @@ def unwrap_final(self, s: AssignmentStmt) -> bool:
32213223 if lval .is_new_def :
32223224 lval .is_inferred_def = s .type is None
32233225
3224- if self .loop_depth > 0 :
3226+ if self .loop_depth [ - 1 ] > 0 :
32253227 self .fail ("Cannot use Final inside a loop" , s )
32263228 if self .type and self .type .is_protocol :
32273229 self .msg .protocol_members_cant_be_final (s )
@@ -4700,9 +4702,9 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
47004702 def visit_while_stmt (self , s : WhileStmt ) -> None :
47014703 self .statement = s
47024704 s .expr .accept (self )
4703- self .loop_depth += 1
4705+ self .loop_depth [ - 1 ] += 1
47044706 s .body .accept (self )
4705- self .loop_depth -= 1
4707+ self .loop_depth [ - 1 ] -= 1
47064708 self .visit_block_maybe (s .else_body )
47074709
47084710 def visit_for_stmt (self , s : ForStmt ) -> None :
@@ -4724,20 +4726,20 @@ def visit_for_stmt(self, s: ForStmt) -> None:
47244726 self .store_declared_types (s .index , analyzed )
47254727 s .index_type = analyzed
47264728
4727- self .loop_depth += 1
4729+ self .loop_depth [ - 1 ] += 1
47284730 self .visit_block (s .body )
4729- self .loop_depth -= 1
4731+ self .loop_depth [ - 1 ] -= 1
47304732
47314733 self .visit_block_maybe (s .else_body )
47324734
47334735 def visit_break_stmt (self , s : BreakStmt ) -> None :
47344736 self .statement = s
4735- if self .loop_depth == 0 :
4737+ if self .loop_depth [ - 1 ] == 0 :
47364738 self .fail ('"break" outside loop' , s , serious = True , blocker = True )
47374739
47384740 def visit_continue_stmt (self , s : ContinueStmt ) -> None :
47394741 self .statement = s
4740- if self .loop_depth == 0 :
4742+ if self .loop_depth [ - 1 ] == 0 :
47414743 self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
47424744
47434745 def visit_if_stmt (self , s : IfStmt ) -> None :
@@ -6232,6 +6234,7 @@ def enter(
62326234 self .nonlocal_decls .append (set ())
62336235 # -1 since entering block will increment this to 0.
62346236 self .block_depth .append (- 1 )
6237+ self .loop_depth .append (0 )
62356238 self .missing_names .append (set ())
62366239 try :
62376240 yield
@@ -6241,6 +6244,7 @@ def enter(
62416244 self .global_decls .pop ()
62426245 self .nonlocal_decls .pop ()
62436246 self .block_depth .pop ()
6247+ self .loop_depth .pop ()
62446248 self .missing_names .pop ()
62456249
62466250 def is_func_scope (self ) -> bool :
0 commit comments