mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Remove JUMP_IF_NOT_EXC_MATCH, SET_EXC_INFO (#6820)
This commit is contained in:
2
Lib/_opcode_metadata.py
vendored
2
Lib/_opcode_metadata.py
vendored
@@ -216,8 +216,6 @@ opmap = {
|
||||
'BEFORE_WITH': 213,
|
||||
'BINARY_SUBSCR': 214,
|
||||
'BUILD_CONST_KEY_MAP': 215,
|
||||
'JUMP_IF_NOT_EXC_MATCH': 220,
|
||||
'SET_EXC_INFO': 223,
|
||||
'INSTRUMENTED_END_FOR': 234,
|
||||
'INSTRUMENTED_POP_ITER': 235,
|
||||
'INSTRUMENTED_END_SEND': 236,
|
||||
|
||||
@@ -2925,12 +2925,19 @@ impl Compiler {
|
||||
// If we gave a typ,
|
||||
// check if this handler can handle the exception:
|
||||
if let Some(exc_type) = type_ {
|
||||
// Duplicate exception for test:
|
||||
emit!(self, Instruction::Copy { index: 1_u32 });
|
||||
|
||||
// Check exception type:
|
||||
// Stack: [prev_exc, exc]
|
||||
self.compile_expression(exc_type)?;
|
||||
emit!(self, Instruction::JumpIfNotExcMatch(next_handler));
|
||||
// Stack: [prev_exc, exc, type]
|
||||
emit!(self, Instruction::CheckExcMatch);
|
||||
// Stack: [prev_exc, exc, bool]
|
||||
emit!(
|
||||
self,
|
||||
Instruction::PopJumpIfFalse {
|
||||
target: next_handler
|
||||
}
|
||||
);
|
||||
// Stack: [prev_exc, exc]
|
||||
|
||||
// We have a match, store in name (except x as y)
|
||||
if let Some(alias) = name {
|
||||
@@ -3308,13 +3315,9 @@ impl Compiler {
|
||||
|
||||
// Handler matched
|
||||
// Stack: [prev_exc, orig, list, new_rest, match]
|
||||
// Note: CheckEgMatch already sets the matched exception as current exception
|
||||
let handler_except_block = self.new_block();
|
||||
|
||||
// Set matched exception as current exception (for __context__ in handler body)
|
||||
// This ensures that exceptions raised in the handler get the matched part
|
||||
// as their __context__, not the original full exception group
|
||||
emit!(self, Instruction::SetExcInfo);
|
||||
|
||||
// Store match to name or pop
|
||||
if let Some(alias) = name {
|
||||
self.store_name(alias.as_str())?;
|
||||
|
||||
@@ -83,10 +83,10 @@ expression: "compile_exec(\"\\\nasync def test():\n for stop_exc in (StopIter
|
||||
73 RERAISE (1)
|
||||
>> 74 JUMP_FORWARD (100)
|
||||
75 PUSH_EXC_INFO
|
||||
76 COPY (1)
|
||||
|
||||
7 77 LOAD_GLOBAL (6, Exception)
|
||||
78 JUMP_IF_NOT_EXC_MATCH(96)
|
||||
7 76 LOAD_GLOBAL (6, Exception)
|
||||
77 CHECK_EXC_MATCH
|
||||
78 POP_JUMP_IF_FALSE (96)
|
||||
79 STORE_FAST (1, ex)
|
||||
|
||||
8 80 LOAD_GLOBAL (2, self)
|
||||
|
||||
@@ -266,8 +266,6 @@ pub enum Instruction {
|
||||
BuildConstKeyMap {
|
||||
size: Arg<u32>,
|
||||
} = 215, // Placeholder
|
||||
JumpIfNotExcMatch(Arg<Label>) = 220,
|
||||
SetExcInfo = 223,
|
||||
// CPython 3.14 RESUME (128)
|
||||
Resume {
|
||||
arg: Arg<u32>,
|
||||
@@ -418,8 +416,6 @@ impl TryFrom<u8> for Instruction {
|
||||
u8::from(Self::BuildConstKeyMap {
|
||||
size: Arg::marker(),
|
||||
}),
|
||||
u8::from(Self::JumpIfNotExcMatch(Arg::marker())),
|
||||
u8::from(Self::SetExcInfo),
|
||||
];
|
||||
|
||||
if (cpython_start..=cpython_end).contains(&value)
|
||||
@@ -443,7 +439,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::JumpBackward { target: l }
|
||||
| Self::JumpBackwardNoInterrupt { target: l }
|
||||
| Self::JumpForward { target: l }
|
||||
| Self::JumpIfNotExcMatch(l)
|
||||
| Self::PopJumpIfTrue { target: l }
|
||||
| Self::PopJumpIfFalse { target: l }
|
||||
| Self::ForIter { target: l }
|
||||
@@ -534,7 +529,6 @@ impl InstructionMetadata for Instruction {
|
||||
}
|
||||
Self::IsOp(_) => -1,
|
||||
Self::ContainsOp(_) => -1,
|
||||
Self::JumpIfNotExcMatch(_) => -2,
|
||||
Self::ReturnValue => -1,
|
||||
Self::Resume { .. } => 0,
|
||||
Self::YieldValue { .. } => 0,
|
||||
@@ -544,7 +538,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::EndSend => -1,
|
||||
// CLEANUP_THROW: (sub_iter, last_sent_val, exc) -> (None, value) = 3 pop, 2 push = -1
|
||||
Self::CleanupThrow => -1,
|
||||
Self::SetExcInfo => 0,
|
||||
Self::PushExcInfo => 1, // [exc] -> [prev_exc, exc]
|
||||
Self::CheckExcMatch => 0, // [exc, type] -> [exc, bool] (pops type, pushes bool)
|
||||
Self::Reraise { .. } => 0, // Exception raised, stack effect doesn't matter
|
||||
@@ -858,7 +851,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::JumpBackward { target } => w!(JUMP_BACKWARD, target),
|
||||
Self::JumpBackwardNoInterrupt { target } => w!(JUMP_BACKWARD_NO_INTERRUPT, target),
|
||||
Self::JumpForward { target } => w!(JUMP_FORWARD, target),
|
||||
Self::JumpIfNotExcMatch(target) => w!(JUMP_IF_NOT_EXC_MATCH, target),
|
||||
Self::ListAppend { i } => w!(LIST_APPEND, i),
|
||||
Self::ListExtend { i } => w!(LIST_EXTEND, i),
|
||||
Self::LoadAttr { idx } => {
|
||||
@@ -912,7 +904,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::ReturnValue => w!(RETURN_VALUE),
|
||||
Self::Send { target } => w!(SEND, target),
|
||||
Self::SetAdd { i } => w!(SET_ADD, i),
|
||||
Self::SetExcInfo => w!(SET_EXC_INFO),
|
||||
Self::SetFunctionAttribute { attr } => w!(SET_FUNCTION_ATTRIBUTE, ?attr),
|
||||
Self::SetupAnnotations => w!(SETUP_ANNOTATIONS),
|
||||
Self::SetUpdate { i } => w!(SET_UPDATE, i),
|
||||
|
||||
@@ -103,7 +103,6 @@ mod opcode {
|
||||
Self::try_from(opcode).map(|op| op.inner()),
|
||||
Ok(AnyInstruction::Real(
|
||||
Instruction::ForIter { .. }
|
||||
| Instruction::JumpIfNotExcMatch(_)
|
||||
| Instruction::PopJumpIfFalse { .. }
|
||||
| Instruction::PopJumpIfTrue { .. }
|
||||
| Instruction::Send { .. }
|
||||
|
||||
@@ -775,6 +775,15 @@ impl ExecutingFrame<'_> {
|
||||
let exc_value = self.pop_value();
|
||||
let (rest, matched) =
|
||||
crate::exceptions::exception_group_match(&exc_value, &match_type, vm)?;
|
||||
|
||||
// Set matched exception as current exception (if not None)
|
||||
// This mirrors CPython's PyErr_SetHandledException(match_o) in CHECK_EG_MATCH
|
||||
if !vm.is_none(&matched)
|
||||
&& let Some(exc) = matched.downcast_ref::<PyBaseException>()
|
||||
{
|
||||
vm.set_exception(Some(exc.to_owned()));
|
||||
}
|
||||
|
||||
self.push_value(rest);
|
||||
self.push_value(matched);
|
||||
Ok(None)
|
||||
@@ -1119,29 +1128,6 @@ impl ExecutingFrame<'_> {
|
||||
self.push_value(vm.ctx.new_bool(value).into());
|
||||
Ok(None)
|
||||
}
|
||||
Instruction::JumpIfNotExcMatch(target) => {
|
||||
let b = self.pop_value();
|
||||
let a = self.pop_value();
|
||||
if let Some(tuple_of_exceptions) = b.downcast_ref::<PyTuple>() {
|
||||
for exception in tuple_of_exceptions {
|
||||
if !exception
|
||||
.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)?
|
||||
{
|
||||
return Err(vm.new_type_error(
|
||||
"catching classes that do not inherit from BaseException is not allowed",
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if !b.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)? {
|
||||
return Err(vm.new_type_error(
|
||||
"catching classes that do not inherit from BaseException is not allowed",
|
||||
));
|
||||
}
|
||||
|
||||
let value = a.is_instance(&b, vm)?;
|
||||
self.push_value(vm.ctx.new_bool(value).into());
|
||||
self.pop_jump_if(vm, target.get(arg), false)
|
||||
}
|
||||
Instruction::JumpForward { target } => {
|
||||
self.jump(target.get(arg));
|
||||
Ok(None)
|
||||
@@ -1569,15 +1555,6 @@ impl ExecutingFrame<'_> {
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
Instruction::SetExcInfo => {
|
||||
// Set the current exception to TOS (for except* handlers)
|
||||
// This updates sys.exc_info() so bare 'raise' will reraise the matched exception
|
||||
let exc = self.top_value();
|
||||
if let Some(exc) = exc.downcast_ref::<PyBaseException>() {
|
||||
vm.set_exception(Some(exc.to_owned()));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
Instruction::PushExcInfo => {
|
||||
// Stack: [exc] -> [prev_exc, exc]
|
||||
let exc = self.pop_value();
|
||||
@@ -1600,7 +1577,23 @@ impl ExecutingFrame<'_> {
|
||||
let exc_type = self.pop_value();
|
||||
let exc = self.top_value();
|
||||
|
||||
// Validate that exc_type is valid for exception matching
|
||||
// Validate that exc_type inherits from BaseException
|
||||
if let Some(tuple_of_exceptions) = exc_type.downcast_ref::<PyTuple>() {
|
||||
for exception in tuple_of_exceptions {
|
||||
if !exception
|
||||
.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)?
|
||||
{
|
||||
return Err(vm.new_type_error(
|
||||
"catching classes that do not inherit from BaseException is not allowed",
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if !exc_type.is_subclass(vm.ctx.exceptions.base_exception_type.into(), vm)? {
|
||||
return Err(vm.new_type_error(
|
||||
"catching classes that do not inherit from BaseException is not allowed",
|
||||
));
|
||||
}
|
||||
|
||||
let result = exc.is_instance(&exc_type, vm)?;
|
||||
self.push_value(vm.ctx.new_bool(result).into());
|
||||
Ok(None)
|
||||
|
||||
Reference in New Issue
Block a user