@@ -375,7 +375,7 @@ class SemanticAnalyzer(
375
375
missing_names : list [set [str ]]
376
376
# Callbacks that will be called after semantic analysis to tweak things.
377
377
patches : list [tuple [int , Callable [[], None ]]]
378
- loop_depth = 0 # Depth of breakable loops
378
+ loop_depth : list [ int ] # Depth of breakable loops
379
379
cur_mod_id = "" # Current module id (or None) (phase 2)
380
380
_is_stub_file = False # Are we analyzing a stub file?
381
381
_is_typeshed_stub_file = False # Are we analyzing a typeshed stub file?
@@ -428,7 +428,7 @@ def __init__(
428
428
self .tvar_scope = TypeVarLikeScope ()
429
429
self .function_stack = []
430
430
self .block_depth = [0 ]
431
- self .loop_depth = 0
431
+ self .loop_depth = [ 0 ]
432
432
self .errors = errors
433
433
self .modules = modules
434
434
self .msg = MessageBuilder (errors , modules )
@@ -1808,12 +1808,14 @@ def enter_class(self, info: TypeInfo) -> None:
1808
1808
self .locals .append (None ) # Add class scope
1809
1809
self .is_comprehension_stack .append (False )
1810
1810
self .block_depth .append (- 1 ) # The class body increments this to 0
1811
+ self .loop_depth .append (0 )
1811
1812
self ._type = info
1812
1813
self .missing_names .append (set ())
1813
1814
1814
1815
def leave_class (self ) -> None :
1815
1816
"""Restore analyzer state."""
1816
1817
self .block_depth .pop ()
1818
+ self .loop_depth .pop ()
1817
1819
self .locals .pop ()
1818
1820
self .is_comprehension_stack .pop ()
1819
1821
self ._type = self .type_stack .pop ()
@@ -3219,7 +3221,7 @@ def unwrap_final(self, s: AssignmentStmt) -> bool:
3219
3221
if lval .is_new_def :
3220
3222
lval .is_inferred_def = s .type is None
3221
3223
3222
- if self .loop_depth > 0 :
3224
+ if self .loop_depth [ - 1 ] > 0 :
3223
3225
self .fail ("Cannot use Final inside a loop" , s )
3224
3226
if self .type and self .type .is_protocol :
3225
3227
self .msg .protocol_members_cant_be_final (s )
@@ -4698,9 +4700,9 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
4698
4700
def visit_while_stmt (self , s : WhileStmt ) -> None :
4699
4701
self .statement = s
4700
4702
s .expr .accept (self )
4701
- self .loop_depth += 1
4703
+ self .loop_depth [ - 1 ] += 1
4702
4704
s .body .accept (self )
4703
- self .loop_depth -= 1
4705
+ self .loop_depth [ - 1 ] -= 1
4704
4706
self .visit_block_maybe (s .else_body )
4705
4707
4706
4708
def visit_for_stmt (self , s : ForStmt ) -> None :
@@ -4722,20 +4724,20 @@ def visit_for_stmt(self, s: ForStmt) -> None:
4722
4724
self .store_declared_types (s .index , analyzed )
4723
4725
s .index_type = analyzed
4724
4726
4725
- self .loop_depth += 1
4727
+ self .loop_depth [ - 1 ] += 1
4726
4728
self .visit_block (s .body )
4727
- self .loop_depth -= 1
4729
+ self .loop_depth [ - 1 ] -= 1
4728
4730
4729
4731
self .visit_block_maybe (s .else_body )
4730
4732
4731
4733
def visit_break_stmt (self , s : BreakStmt ) -> None :
4732
4734
self .statement = s
4733
- if self .loop_depth == 0 :
4735
+ if self .loop_depth [ - 1 ] == 0 :
4734
4736
self .fail ('"break" outside loop' , s , serious = True , blocker = True )
4735
4737
4736
4738
def visit_continue_stmt (self , s : ContinueStmt ) -> None :
4737
4739
self .statement = s
4738
- if self .loop_depth == 0 :
4740
+ if self .loop_depth [ - 1 ] == 0 :
4739
4741
self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
4740
4742
4741
4743
def visit_if_stmt (self , s : IfStmt ) -> None :
@@ -6230,6 +6232,7 @@ def enter(
6230
6232
self .nonlocal_decls .append (set ())
6231
6233
# -1 since entering block will increment this to 0.
6232
6234
self .block_depth .append (- 1 )
6235
+ self .loop_depth .append (0 )
6233
6236
self .missing_names .append (set ())
6234
6237
try :
6235
6238
yield
@@ -6239,6 +6242,7 @@ def enter(
6239
6242
self .global_decls .pop ()
6240
6243
self .nonlocal_decls .pop ()
6241
6244
self .block_depth .pop ()
6245
+ self .loop_depth .pop ()
6242
6246
self .missing_names .pop ()
6243
6247
6244
6248
def is_func_scope (self ) -> bool :
0 commit comments