Skip to content

Commit 48826b6

Browse files
committed
SetExcInfo
1 parent e0cceaf commit 48826b6

File tree

6 files changed

+41
-57
lines changed

6 files changed

+41
-57
lines changed

Lib/_opcode_metadata.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@
216216
'BEFORE_WITH': 213,
217217
'BINARY_SUBSCR': 214,
218218
'BUILD_CONST_KEY_MAP': 215,
219-
'JUMP_IF_NOT_EXC_MATCH': 220,
220-
'SET_EXC_INFO': 223,
221219
'INSTRUMENTED_END_FOR': 234,
222220
'INSTRUMENTED_POP_ITER': 235,
223221
'INSTRUMENTED_END_SEND': 236,

crates/codegen/src/compile.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,12 +2925,19 @@ impl Compiler {
29252925
// If we gave a typ,
29262926
// check if this handler can handle the exception:
29272927
if let Some(exc_type) = type_ {
2928-
// Duplicate exception for test:
2929-
emit!(self, Instruction::Copy { index: 1_u32 });
2930-
29312928
// Check exception type:
2929+
// Stack: [prev_exc, exc]
29322930
self.compile_expression(exc_type)?;
2933-
emit!(self, Instruction::JumpIfNotExcMatch(next_handler));
2931+
// Stack: [prev_exc, exc, type]
2932+
emit!(self, Instruction::CheckExcMatch);
2933+
// Stack: [prev_exc, exc, bool]
2934+
emit!(
2935+
self,
2936+
Instruction::PopJumpIfFalse {
2937+
target: next_handler
2938+
}
2939+
);
2940+
// Stack: [prev_exc, exc]
29342941

29352942
// We have a match, store in name (except x as y)
29362943
if let Some(alias) = name {
@@ -3308,13 +3315,9 @@ impl Compiler {
33083315

33093316
// Handler matched
33103317
// Stack: [prev_exc, orig, list, new_rest, match]
3318+
// Note: CheckEgMatch already sets the matched exception as current exception
33113319
let handler_except_block = self.new_block();
33123320

3313-
// Set matched exception as current exception (for __context__ in handler body)
3314-
// This ensures that exceptions raised in the handler get the matched part
3315-
// as their __context__, not the original full exception group
3316-
emit!(self, Instruction::SetExcInfo);
3317-
33183321
// Store match to name or pop
33193322
if let Some(alias) = name {
33203323
self.store_name(alias.as_str())?;

crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/compiler-core/src/bytecode/instruction.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,6 @@ pub enum Instruction {
266266
BuildConstKeyMap {
267267
size: Arg<u32>,
268268
} = 215, // Placeholder
269-
JumpIfNotExcMatch(Arg<Label>) = 220,
270-
SetExcInfo = 223,
271269
// CPython 3.14 RESUME (128)
272270
Resume {
273271
arg: Arg<u32>,
@@ -418,8 +416,6 @@ impl TryFrom<u8> for Instruction {
418416
u8::from(Self::BuildConstKeyMap {
419417
size: Arg::marker(),
420418
}),
421-
u8::from(Self::JumpIfNotExcMatch(Arg::marker())),
422-
u8::from(Self::SetExcInfo),
423419
];
424420

425421
if (cpython_start..=cpython_end).contains(&value)
@@ -443,7 +439,6 @@ impl InstructionMetadata for Instruction {
443439
Self::JumpBackward { target: l }
444440
| Self::JumpBackwardNoInterrupt { target: l }
445441
| Self::JumpForward { target: l }
446-
| Self::JumpIfNotExcMatch(l)
447442
| Self::PopJumpIfTrue { target: l }
448443
| Self::PopJumpIfFalse { target: l }
449444
| Self::ForIter { target: l }
@@ -534,7 +529,6 @@ impl InstructionMetadata for Instruction {
534529
}
535530
Self::IsOp(_) => -1,
536531
Self::ContainsOp(_) => -1,
537-
Self::JumpIfNotExcMatch(_) => -2,
538532
Self::ReturnValue => -1,
539533
Self::Resume { .. } => 0,
540534
Self::YieldValue { .. } => 0,
@@ -544,7 +538,6 @@ impl InstructionMetadata for Instruction {
544538
Self::EndSend => -1,
545539
// CLEANUP_THROW: (sub_iter, last_sent_val, exc) -> (None, value) = 3 pop, 2 push = -1
546540
Self::CleanupThrow => -1,
547-
Self::SetExcInfo => 0,
548541
Self::PushExcInfo => 1, // [exc] -> [prev_exc, exc]
549542
Self::CheckExcMatch => 0, // [exc, type] -> [exc, bool] (pops type, pushes bool)
550543
Self::Reraise { .. } => 0, // Exception raised, stack effect doesn't matter
@@ -858,7 +851,6 @@ impl InstructionMetadata for Instruction {
858851
Self::JumpBackward { target } => w!(JUMP_BACKWARD, target),
859852
Self::JumpBackwardNoInterrupt { target } => w!(JUMP_BACKWARD_NO_INTERRUPT, target),
860853
Self::JumpForward { target } => w!(JUMP_FORWARD, target),
861-
Self::JumpIfNotExcMatch(target) => w!(JUMP_IF_NOT_EXC_MATCH, target),
862854
Self::ListAppend { i } => w!(LIST_APPEND, i),
863855
Self::ListExtend { i } => w!(LIST_EXTEND, i),
864856
Self::LoadAttr { idx } => {
@@ -912,7 +904,6 @@ impl InstructionMetadata for Instruction {
912904
Self::ReturnValue => w!(RETURN_VALUE),
913905
Self::Send { target } => w!(SEND, target),
914906
Self::SetAdd { i } => w!(SET_ADD, i),
915-
Self::SetExcInfo => w!(SET_EXC_INFO),
916907
Self::SetFunctionAttribute { attr } => w!(SET_FUNCTION_ATTRIBUTE, ?attr),
917908
Self::SetupAnnotations => w!(SETUP_ANNOTATIONS),
918909
Self::SetUpdate { i } => w!(SET_UPDATE, i),

crates/stdlib/src/opcode.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ mod opcode {
103103
Self::try_from(opcode).map(|op| op.inner()),
104104
Ok(AnyInstruction::Real(
105105
Instruction::ForIter { .. }
106-
| Instruction::JumpIfNotExcMatch(_)
107106
| Instruction::PopJumpIfFalse { .. }
108107
| Instruction::PopJumpIfTrue { .. }
109108
| Instruction::Send { .. }

crates/vm/src/frame.rs

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,15 @@ impl ExecutingFrame<'_> {
775775
let exc_value = self.pop_value();
776776
let (rest, matched) =
777777
crate::exceptions::exception_group_match(&exc_value, &match_type, vm)?;
778+
779+
// Set matched exception as current exception (if not None)
780+
// This mirrors CPython's PyErr_SetHandledException(match_o) in CHECK_EG_MATCH
781+
if !vm.is_none(&matched)
782+
&& let Some(exc) = matched.downcast_ref::<PyBaseException>()
783+
{
784+
vm.set_exception(Some(exc.to_owned()));
785+
}
786+
778787
self.push_value(rest);
779788
self.push_value(matched);
780789
Ok(None)
@@ -1119,29 +1128,6 @@ impl ExecutingFrame<'_> {
11191128
self.push_value(vm.ctx.new_bool(value).into());
11201129
Ok(None)
11211130
}
1122-
Instruction::JumpIfNotExcMatch(target) => {
1123-
let b = self.pop_value();
1124-
let a = self.pop_value();
1125-
if let Some(tuple_of_exceptions) = b.downcast_ref::<PyTuple>() {
1126-
for exception in tuple_of_exceptions {
1127-
if !exception
1128-
.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)?
1129-
{
1130-
return Err(vm.new_type_error(
1131-
"catching classes that do not inherit from BaseException is not allowed",
1132-
));
1133-
}
1134-
}
1135-
} else if !b.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)? {
1136-
return Err(vm.new_type_error(
1137-
"catching classes that do not inherit from BaseException is not allowed",
1138-
));
1139-
}
1140-
1141-
let value = a.is_instance(&b, vm)?;
1142-
self.push_value(vm.ctx.new_bool(value).into());
1143-
self.pop_jump_if(vm, target.get(arg), false)
1144-
}
11451131
Instruction::JumpForward { target } => {
11461132
self.jump(target.get(arg));
11471133
Ok(None)
@@ -1569,15 +1555,6 @@ impl ExecutingFrame<'_> {
15691555
}
15701556
Ok(None)
15711557
}
1572-
Instruction::SetExcInfo => {
1573-
// Set the current exception to TOS (for except* handlers)
1574-
// This updates sys.exc_info() so bare 'raise' will reraise the matched exception
1575-
let exc = self.top_value();
1576-
if let Some(exc) = exc.downcast_ref::<PyBaseException>() {
1577-
vm.set_exception(Some(exc.to_owned()));
1578-
}
1579-
Ok(None)
1580-
}
15811558
Instruction::PushExcInfo => {
15821559
// Stack: [exc] -> [prev_exc, exc]
15831560
let exc = self.pop_value();
@@ -1600,7 +1577,23 @@ impl ExecutingFrame<'_> {
16001577
let exc_type = self.pop_value();
16011578
let exc = self.top_value();
16021579

1603-
// Validate that exc_type is valid for exception matching
1580+
// Validate that exc_type inherits from BaseException
1581+
if let Some(tuple_of_exceptions) = exc_type.downcast_ref::<PyTuple>() {
1582+
for exception in tuple_of_exceptions {
1583+
if !exception
1584+
.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)?
1585+
{
1586+
return Err(vm.new_type_error(
1587+
"catching classes that do not inherit from BaseException is not allowed",
1588+
));
1589+
}
1590+
}
1591+
} else if !exc_type.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)? {
1592+
return Err(vm.new_type_error(
1593+
"catching classes that do not inherit from BaseException is not allowed",
1594+
));
1595+
}
1596+
16041597
let result = exc.is_instance(&exc_type, vm)?;
16051598
self.push_value(vm.ctx.new_bool(result).into());
16061599
Ok(None)

0 commit comments

Comments
 (0)