@@ -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 )
@@ -1810,12 +1810,14 @@ def enter_class(self, info: TypeInfo) -> None:
1810
1810
self .locals .append (None ) # Add class scope
1811
1811
self .is_comprehension_stack .append (False )
1812
1812
self .block_depth .append (- 1 ) # The class body increments this to 0
1813
+ self .loop_depth .append (0 )
1813
1814
self ._type = info
1814
1815
self .missing_names .append (set ())
1815
1816
1816
1817
def leave_class (self ) -> None :
1817
1818
"""Restore analyzer state."""
1818
1819
self .block_depth .pop ()
1820
+ self .loop_depth .pop ()
1819
1821
self .locals .pop ()
1820
1822
self .is_comprehension_stack .pop ()
1821
1823
self ._type = self .type_stack .pop ()
@@ -3221,7 +3223,7 @@ def unwrap_final(self, s: AssignmentStmt) -> bool:
3221
3223
if lval .is_new_def :
3222
3224
lval .is_inferred_def = s .type is None
3223
3225
3224
- if self .loop_depth > 0 :
3226
+ if self .loop_depth [ - 1 ] > 0 :
3225
3227
self .fail ("Cannot use Final inside a loop" , s )
3226
3228
if self .type and self .type .is_protocol :
3227
3229
self .msg .protocol_members_cant_be_final (s )
@@ -4700,9 +4702,9 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
4700
4702
def visit_while_stmt (self , s : WhileStmt ) -> None :
4701
4703
self .statement = s
4702
4704
s .expr .accept (self )
4703
- self .loop_depth += 1
4705
+ self .loop_depth [ - 1 ] += 1
4704
4706
s .body .accept (self )
4705
- self .loop_depth -= 1
4707
+ self .loop_depth [ - 1 ] -= 1
4706
4708
self .visit_block_maybe (s .else_body )
4707
4709
4708
4710
def visit_for_stmt (self , s : ForStmt ) -> None :
@@ -4724,20 +4726,20 @@ def visit_for_stmt(self, s: ForStmt) -> None:
4724
4726
self .store_declared_types (s .index , analyzed )
4725
4727
s .index_type = analyzed
4726
4728
4727
- self .loop_depth += 1
4729
+ self .loop_depth [ - 1 ] += 1
4728
4730
self .visit_block (s .body )
4729
- self .loop_depth -= 1
4731
+ self .loop_depth [ - 1 ] -= 1
4730
4732
4731
4733
self .visit_block_maybe (s .else_body )
4732
4734
4733
4735
def visit_break_stmt (self , s : BreakStmt ) -> None :
4734
4736
self .statement = s
4735
- if self .loop_depth == 0 :
4737
+ if self .loop_depth [ - 1 ] == 0 :
4736
4738
self .fail ('"break" outside loop' , s , serious = True , blocker = True )
4737
4739
4738
4740
def visit_continue_stmt (self , s : ContinueStmt ) -> None :
4739
4741
self .statement = s
4740
- if self .loop_depth == 0 :
4742
+ if self .loop_depth [ - 1 ] == 0 :
4741
4743
self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
4742
4744
4743
4745
def visit_if_stmt (self , s : IfStmt ) -> None :
@@ -6232,6 +6234,7 @@ def enter(
6232
6234
self .nonlocal_decls .append (set ())
6233
6235
# -1 since entering block will increment this to 0.
6234
6236
self .block_depth .append (- 1 )
6237
+ self .loop_depth .append (0 )
6235
6238
self .missing_names .append (set ())
6236
6239
try :
6237
6240
yield
@@ -6241,6 +6244,7 @@ def enter(
6241
6244
self .global_decls .pop ()
6242
6245
self .nonlocal_decls .pop ()
6243
6246
self .block_depth .pop ()
6247
+ self .loop_depth .pop ()
6244
6248
self .missing_names .pop ()
6245
6249
6246
6250
def is_func_scope (self ) -> bool :
0 commit comments