@@ -484,6 +484,10 @@ def __init__(
484484 # Used to pass information about current overload index to visit_func_def().
485485 self .current_overload_item : int | None = None
486486
487+ # Used to track whether currently inside an except* block. This helps
488+ # to invoke errors when continue/break/return is used inside except * block.
489+ self .is_in_except_block : bool = False
490+
487491 # mypyc doesn't properly handle implementing an abstractproperty
488492 # with a regular attribute so we make them properties
489493 @property
@@ -854,6 +858,9 @@ def file_context(
854858 def visit_func_def (self , defn : FuncDef ) -> None :
855859 self .statement = defn
856860
861+ was_in_except_block : bool = self .is_in_except_block
862+ self .is_in_except_block = False
863+
857864 # Visit default values because they may contain assignment expressions.
858865 for arg in defn .arguments :
859866 if arg .initializer :
@@ -874,11 +881,14 @@ def visit_func_def(self, defn: FuncDef) -> None:
874881 self .add_function_to_symbol_table (defn )
875882
876883 if not self .recurse_into_functions :
884+ self .is_in_except_block = was_in_except_block
877885 return
878886
879887 with self .scope .function_scope (defn ):
880888 self .analyze_func_def (defn )
881889
890+ self .is_in_except_block = was_in_except_block
891+
882892 def function_fullname (self , fullname : str ) -> str :
883893 if self .current_overload_item is None :
884894 return fullname
@@ -5263,6 +5273,8 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
52635273 self .statement = s
52645274 if not self .is_func_scope ():
52655275 self .fail ('"return" outside function' , s )
5276+ if self .is_in_except_block :
5277+ self .fail ('"return" not allowed in except* block' , s , serious = True , blocker = True )
52665278 if s .expr :
52675279 s .expr .accept (self )
52685280
@@ -5295,9 +5307,12 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
52955307 def visit_while_stmt (self , s : WhileStmt ) -> None :
52965308 self .statement = s
52975309 s .expr .accept (self )
5310+ was_in_except_block : bool = self .is_in_except_block
5311+ self .is_in_except_block = False
52985312 self .loop_depth [- 1 ] += 1
52995313 s .body .accept (self )
53005314 self .loop_depth [- 1 ] -= 1
5315+ self .is_in_except_block = was_in_except_block
53015316 self .visit_block_maybe (s .else_body )
53025317
53035318 def visit_for_stmt (self , s : ForStmt ) -> None :
@@ -5319,21 +5334,28 @@ def visit_for_stmt(self, s: ForStmt) -> None:
53195334 self .store_declared_types (s .index , analyzed )
53205335 s .index_type = analyzed
53215336
5337+ was_in_except_block : bool = self .is_in_except_block
5338+ self .is_in_except_block = False
53225339 self .loop_depth [- 1 ] += 1
53235340 self .visit_block (s .body )
53245341 self .loop_depth [- 1 ] -= 1
5342+ self .is_in_except_block = was_in_except_block
53255343
53265344 self .visit_block_maybe (s .else_body )
53275345
53285346 def visit_break_stmt (self , s : BreakStmt ) -> None :
53295347 self .statement = s
53305348 if self .loop_depth [- 1 ] == 0 :
53315349 self .fail ('"break" outside loop' , s , serious = True , blocker = True )
5350+ if self .is_in_except_block :
5351+ self .fail ('"break" not allowed in except* block' , s , serious = True , blocker = True )
53325352
53335353 def visit_continue_stmt (self , s : ContinueStmt ) -> None :
53345354 self .statement = s
53355355 if self .loop_depth [- 1 ] == 0 :
53365356 self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
5357+ if self .is_in_except_block :
5358+ self .fail ('"continue" not allowed in except* block' , s , serious = True , blocker = True )
53375359
53385360 def visit_if_stmt (self , s : IfStmt ) -> None :
53395361 self .statement = s
@@ -5354,7 +5376,13 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
53545376 type .accept (visitor )
53555377 if var :
53565378 self .analyze_lvalue (var )
5357- handler .accept (visitor )
5379+ if s .is_star :
5380+ was_in_except_block : bool = self .is_in_except_block
5381+ self .is_in_except_block = True
5382+ handler .accept (visitor )
5383+ self .is_in_except_block = was_in_except_block
5384+ else :
5385+ handler .accept (visitor )
53585386 if s .else_body :
53595387 s .else_body .accept (visitor )
53605388 if s .finally_body :
0 commit comments