@@ -484,6 +484,12 @@ 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 .inside_except_star_block : bool = False
490+ # Used to track edge case when return is still inside except* if it enters a loop
491+ self .return_stmt_inside_except_star_block : bool = False
492+
487493 # mypyc doesn't properly handle implementing an abstractproperty
488494 # with a regular attribute so we make them properties
489495 @property
@@ -511,6 +517,25 @@ def allow_unbound_tvars_set(self) -> Iterator[None]:
511517 finally :
512518 self .allow_unbound_tvars = old
513519
520+ @contextmanager
521+ def inside_except_star_block_set (
522+ self , value : bool , entering_loop : bool = False
523+ ) -> Iterator [None ]:
524+ old = self .inside_except_star_block
525+ self .inside_except_star_block = value
526+
527+ # Return statement would still be in except* scope if entering loops
528+ if not entering_loop :
529+ old_return_stmt_flag = self .return_stmt_inside_except_star_block
530+ self .return_stmt_inside_except_star_block = value
531+
532+ try :
533+ yield
534+ finally :
535+ self .inside_except_star_block = old
536+ if not entering_loop :
537+ self .return_stmt_inside_except_star_block = old_return_stmt_flag
538+
514539 #
515540 # Preparing module (performed before semantic analysis)
516541 #
@@ -877,7 +902,8 @@ def visit_func_def(self, defn: FuncDef) -> None:
877902 return
878903
879904 with self .scope .function_scope (defn ):
880- self .analyze_func_def (defn )
905+ with self .inside_except_star_block_set (value = False ):
906+ self .analyze_func_def (defn )
881907
882908 def function_fullname (self , fullname : str ) -> str :
883909 if self .current_overload_item is None :
@@ -5264,6 +5290,8 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
52645290 self .statement = s
52655291 if not self .is_func_scope ():
52665292 self .fail ('"return" outside function' , s )
5293+ if self .return_stmt_inside_except_star_block :
5294+ self .fail ('"return" not allowed in except* block' , s , serious = True )
52675295 if s .expr :
52685296 s .expr .accept (self )
52695297
@@ -5297,7 +5325,8 @@ def visit_while_stmt(self, s: WhileStmt) -> None:
52975325 self .statement = s
52985326 s .expr .accept (self )
52995327 self .loop_depth [- 1 ] += 1
5300- s .body .accept (self )
5328+ with self .inside_except_star_block_set (value = False , entering_loop = True ):
5329+ s .body .accept (self )
53015330 self .loop_depth [- 1 ] -= 1
53025331 self .visit_block_maybe (s .else_body )
53035332
@@ -5321,20 +5350,24 @@ def visit_for_stmt(self, s: ForStmt) -> None:
53215350 s .index_type = analyzed
53225351
53235352 self .loop_depth [- 1 ] += 1
5324- self .visit_block (s .body )
5353+ with self .inside_except_star_block_set (value = False , entering_loop = True ):
5354+ self .visit_block (s .body )
53255355 self .loop_depth [- 1 ] -= 1
5326-
53275356 self .visit_block_maybe (s .else_body )
53285357
53295358 def visit_break_stmt (self , s : BreakStmt ) -> None :
53305359 self .statement = s
53315360 if self .loop_depth [- 1 ] == 0 :
53325361 self .fail ('"break" outside loop' , s , serious = True , blocker = True )
5362+ if self .inside_except_star_block :
5363+ self .fail ('"break" not allowed in except* block' , s , serious = True )
53335364
53345365 def visit_continue_stmt (self , s : ContinueStmt ) -> None :
53355366 self .statement = s
53365367 if self .loop_depth [- 1 ] == 0 :
53375368 self .fail ('"continue" outside loop' , s , serious = True , blocker = True )
5369+ if self .inside_except_star_block :
5370+ self .fail ('"continue" not allowed in except* block' , s , serious = True )
53385371
53395372 def visit_if_stmt (self , s : IfStmt ) -> None :
53405373 self .statement = s
@@ -5355,7 +5388,8 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
53555388 type .accept (visitor )
53565389 if var :
53575390 self .analyze_lvalue (var )
5358- handler .accept (visitor )
5391+ with self .inside_except_star_block_set (self .inside_except_star_block or s .is_star ):
5392+ handler .accept (visitor )
53595393 if s .else_body :
53605394 s .else_body .accept (visitor )
53615395 if s .finally_body :
0 commit comments