Skip to content

Commit 64cf654

Browse files
committed
Fix try-except and except* no-location and block layout
- Add set_no_location() after jump instructions in try-except and except* handlers for proper line number tracking - Use no-location (lineno_override=-1) for cold block jumps instead of copying predecessor location - Simplify continuation_block to always use end_block - Rename except_with_error_block to next_handler_block - Fix exit_block vs end_block selection for finalbody
1 parent e98e9f2 commit 64cf654

2 files changed

Lines changed: 370 additions & 49 deletions

File tree

crates/codegen/src/compile.rs

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,6 +3201,7 @@ impl Compiler {
32013201
emit!(self, PseudoInstruction::PopBlock);
32023202
self.pop_fblock(FBlockType::TryExcept);
32033203
emit!(self, PseudoInstruction::Jump { delta: else_block });
3204+
self.set_no_location();
32043205

32053206
// except handlers:
32063207
self.switch_to_block(handler_block);
@@ -3471,8 +3472,12 @@ impl Compiler {
34713472
) -> CompileResult<()> {
34723473
let handler_block = self.new_block();
34733474
let cleanup_block = self.new_block();
3474-
let orelse_block = self.new_block();
34753475
let end_block = self.new_block();
3476+
let orelse_block = if orelse.is_empty() {
3477+
end_block
3478+
} else {
3479+
self.new_block()
3480+
};
34763481

34773482
emit!(self, Instruction::Nop);
34783483
emit!(
@@ -3619,14 +3624,16 @@ impl Compiler {
36193624
emit!(self, Instruction::Reraise { depth: 1 });
36203625
self.set_no_location();
36213626

3622-
self.switch_to_block(orelse_block);
3623-
self.set_no_location();
3624-
self.compile_statements(orelse)?;
3625-
emit!(
3626-
self,
3627-
PseudoInstruction::JumpNoInterrupt { delta: end_block }
3628-
);
3629-
self.set_no_location();
3627+
if !orelse.is_empty() {
3628+
self.switch_to_block(orelse_block);
3629+
self.set_no_location();
3630+
self.compile_statements(orelse)?;
3631+
emit!(
3632+
self,
3633+
PseudoInstruction::JumpNoInterrupt { delta: end_block }
3634+
);
3635+
self.set_no_location();
3636+
}
36303637

36313638
self.switch_to_block(end_block);
36323639
Ok(())
@@ -3644,7 +3651,6 @@ impl Compiler {
36443651
let handler_block = self.new_block();
36453652
let finally_block = self.new_block();
36463653
let cleanup_block = self.new_block();
3647-
let else_block = self.new_block();
36483654
let end_block = self.new_block();
36493655
let reraise_star_block = self.new_block();
36503656
let reraise_block = self.new_block();
@@ -3654,10 +3660,11 @@ impl Compiler {
36543660
None
36553661
};
36563662
let exit_block = self.new_block();
3657-
let continuation_block = if finalbody.is_empty() {
3658-
exit_block
3663+
let continuation_block = end_block;
3664+
let else_block = if orelse.is_empty() && finalbody.is_empty() {
3665+
continuation_block
36593666
} else {
3660-
end_block
3667+
self.new_block()
36613668
};
36623669

36633670
// Emit NOP at the try: line so LINE events fire for it
@@ -3733,22 +3740,23 @@ impl Compiler {
37333740
delta: reraise_star_block
37343741
}
37353742
);
3743+
self.set_no_location();
37363744
}
37373745
for (i, handler) in handlers.iter().enumerate() {
37383746
let ast::ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
37393747
type_,
37403748
name,
37413749
body,
3750+
range: handler_range,
37423751
..
37433752
}) = handler;
37443753
let is_last_handler = i == n - 1;
37453754

37463755
let no_match_block = self.new_block();
3747-
let except_with_error_block = self.new_block();
3748-
let handler_done_block = if is_last_handler {
3756+
let next_handler_block = if is_last_handler {
37493757
reraise_star_block
37503758
} else {
3751-
except_with_error_block
3759+
self.new_block()
37523760
};
37533761

37543762
// Compile exception type
@@ -3806,7 +3814,7 @@ impl Compiler {
38063814
);
38073815
self.push_fblock_full(
38083816
FBlockType::HandlerCleanup,
3809-
handler_done_block,
3817+
next_handler_block,
38103818
end_block,
38113819
if let Some(alias) = name {
38123820
FBlockDatum::ExceptionName(alias.as_str().to_owned())
@@ -3819,6 +3827,7 @@ impl Compiler {
38193827
self.compile_statements(body)?;
38203828

38213829
// Handler body completed normally
3830+
self.set_no_location();
38223831
emit!(self, PseudoInstruction::PopBlock);
38233832
self.pop_fblock(FBlockType::HandlerCleanup);
38243833

@@ -3831,12 +3840,11 @@ impl Compiler {
38313840

38323841
if is_last_handler {
38333842
emit!(self, Instruction::ListAppend { i: 1 });
3834-
} else {
38353843
}
38363844
emit!(
38373845
self,
38383846
PseudoInstruction::Jump {
3839-
delta: handler_done_block
3847+
delta: next_handler_block
38403848
}
38413849
);
38423850

@@ -3846,6 +3854,7 @@ impl Compiler {
38463854
// (lasti is pushed because push_lasti=true in HANDLER_CLEANUP fblock)
38473855

38483856
// Cleanup name binding
3857+
self.set_no_location();
38493858
if let Some(alias) = name {
38503859
self.emit_load_const(ConstantData::None);
38513860
self.store_name(alias.as_str())?;
@@ -3876,16 +3885,18 @@ impl Compiler {
38763885
emit!(
38773886
self,
38783887
PseudoInstruction::Jump {
3879-
delta: except_with_error_block
3888+
delta: next_handler_block
38803889
}
38813890
);
38823891
}
38833892

38843893
if is_last_handler {
38853894
self.switch_to_block(no_match_block);
3895+
self.set_source_range(*handler_range);
38863896
emit!(self, Instruction::PopTop); // pop match (None)
38873897
// Stack: [prev_exc, orig, list, new_rest]
38883898

3899+
self.set_no_location();
38893900
emit!(self, Instruction::ListAppend { i: 1 });
38903901
emit!(
38913902
self,
@@ -3895,10 +3906,10 @@ impl Compiler {
38953906
);
38963907
} else {
38973908
self.switch_to_block(no_match_block);
3909+
self.set_source_range(*handler_range);
38983910
emit!(self, Instruction::PopTop); // pop match (None)
38993911
// Stack: [prev_exc, orig, list, new_rest]
3900-
3901-
self.switch_to_block(except_with_error_block);
3912+
self.switch_to_block(next_handler_block);
39023913
}
39033914
}
39043915

@@ -3908,6 +3919,7 @@ impl Compiler {
39083919
// Reraise star block
39093920
self.switch_to_block(reraise_star_block);
39103921
// Stack: [prev_exc, orig, list]
3922+
self.set_no_location();
39113923

39123924
// CALL_INTRINSIC_2 PREP_RERAISE_STAR
39133925
// Takes 2 args (orig, list) and produces result
@@ -3957,6 +3969,7 @@ impl Compiler {
39573969
// Reraise the result
39583970
self.switch_to_block(reraise_block);
39593971
// Stack: [prev_exc, result]
3972+
self.set_no_location();
39603973

39613974
emit!(self, PseudoInstruction::PopBlock);
39623975
emit!(self, Instruction::Swap { i: 2 });
@@ -3970,6 +3983,7 @@ impl Compiler {
39703983
emit!(self, Instruction::Reraise { depth: 0 });
39713984

39723985
self.switch_to_block(cleanup_block);
3986+
self.set_no_location();
39733987
emit!(self, Instruction::Copy { i: 3 });
39743988
emit!(self, Instruction::PopExcept);
39753989
emit!(self, Instruction::Reraise { depth: 1 });
@@ -3993,21 +4007,23 @@ impl Compiler {
39934007
FBlockDatum::FinallyBody(finalbody.to_vec()),
39944008
)?;
39954009
}
3996-
self.switch_to_block(else_block);
3997-
self.compile_statements(orelse)?;
3998-
3999-
if !finalbody.is_empty() {
4000-
// Pop the FinallyTry fblock we just pushed for the else path
4001-
emit!(self, PseudoInstruction::PopBlock);
4002-
self.pop_fblock(FBlockType::FinallyTry);
4003-
}
4010+
if else_block != continuation_block {
4011+
self.switch_to_block(else_block);
4012+
self.compile_statements(orelse)?;
40044013

4005-
emit!(
4006-
self,
4007-
PseudoInstruction::Jump {
4008-
delta: continuation_block
4014+
if !finalbody.is_empty() {
4015+
// Pop the FinallyTry fblock we just pushed for the else path
4016+
emit!(self, PseudoInstruction::PopBlock);
4017+
self.pop_fblock(FBlockType::FinallyTry);
40094018
}
4010-
);
4019+
4020+
emit!(
4021+
self,
4022+
PseudoInstruction::Jump {
4023+
delta: continuation_block
4024+
}
4025+
);
4026+
}
40114027

40124028
if !finalbody.is_empty() {
40134029
self.switch_to_block(end_block);
@@ -4051,7 +4067,11 @@ impl Compiler {
40514067
}
40524068
}
40534069

4054-
self.switch_to_block(exit_block);
4070+
self.switch_to_block(if finalbody.is_empty() {
4071+
end_block
4072+
} else {
4073+
exit_block
4074+
});
40554075

40564076
Ok(())
40574077
}

0 commit comments

Comments
 (0)