@@ -1288,6 +1288,19 @@ impl Compiler {
12881288 }
12891289 }
12901290
1291+ // Clear the exception handlers of all FinallyTry fblocks that we're going to unwind.
1292+ // This prevents exceptions raised during inline finally compilation from being
1293+ // caught by other FinallyTry handlers in the stack, which would cause those
1294+ // finally blocks to re-execute.
1295+ {
1296+ let code = self . current_code_info ( ) ;
1297+ for info in & unwind_infos {
1298+ if let UnwindInfo :: FinallyTry { fblock_idx, .. } = info {
1299+ code. fblock [ * fblock_idx] . fb_handler = None ;
1300+ }
1301+ }
1302+ }
1303+
12911304 // Process each fblock
12921305 for info in unwind_infos {
12931306 match info {
@@ -1301,40 +1314,19 @@ impl Compiler {
13011314 let saved_fblock = code. fblock . remove ( fblock_idx) ;
13021315
13031316 // Push PopValue fblock if preserving tos
1304- // IMPORTANT: When preserving TOS (return value), we need to update the
1305- // exception handler's stack_depth to account for the return value on stack.
1306- // Otherwise, if an exception occurs during the finally body, the stack
1307- // will be unwound to the wrong depth and the return value will be lost.
1317+ // IMPORTANT: Do NOT set an exception handler here!
1318+ // When the finally body is compiled inline (for return/break/continue),
1319+ // if an exception occurs during execution, it should propagate naturally
1320+ // up the call stack, NOT go to the try-finally's exception handler.
1321+ // Setting a handler here would cause the finally body to run twice.
13081322 if preserve_tos {
1309- // Get the handler info from the saved fblock (or current handler)
1310- // and create a new handler with stack_depth + 1
1311- let ( handler, stack_depth, preserve_lasti) =
1312- if let Some ( handler) = saved_fblock. fb_handler {
1313- (
1314- Some ( handler) ,
1315- saved_fblock. fb_stack_depth + 1 , // +1 for return value
1316- saved_fblock. fb_preserve_lasti ,
1317- )
1318- } else {
1319- // No handler in saved_fblock, check current handler
1320- if let Some ( current_handler) = self . current_except_handler ( ) {
1321- (
1322- Some ( current_handler. handler_block ) ,
1323- current_handler. stack_depth + 1 , // +1 for return value
1324- current_handler. preserve_lasti ,
1325- )
1326- } else {
1327- ( None , 1 , false ) // No handler, but still track the return value
1328- }
1329- } ;
1330-
13311323 self . push_fblock_with_handler (
13321324 FBlockType :: PopValue ,
13331325 saved_fblock. fb_block ,
13341326 saved_fblock. fb_block ,
1335- handler ,
1336- stack_depth ,
1337- preserve_lasti ,
1327+ None , // No handler - let exceptions propagate naturally
1328+ 1 , // Stack depth for the return value
1329+ false ,
13381330 ) ?;
13391331 }
13401332
@@ -1344,7 +1336,7 @@ impl Compiler {
13441336 self . pop_fblock ( FBlockType :: PopValue ) ;
13451337 }
13461338
1347- // Restore the fblock
1339+ // Restore the fblock (with its handler already cleared)
13481340 let code = self . current_code_info ( ) ;
13491341 code. fblock . insert ( fblock_idx, saved_fblock) ;
13501342 }
0 commit comments