Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix EG subclass
  • Loading branch information
youknowone committed Dec 27, 2025
commit 3aa9310d01f079b7b69f64aec847d9f2a4b142f7
12 changes: 7 additions & 5 deletions crates/codegen/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2233,13 +2233,14 @@ impl Compiler {
emit!(self, Instruction::CheckEgMatch);
// Stack: [orig, list, new_rest, match]

// Check if match is not None
// Check if match is not None (use identity check, not truthiness)
// CopyItem is 1-indexed: CopyItem(1) = TOS, CopyItem(2) = second from top
emit!(self, Instruction::CopyItem { index: 1 });
emit!(self, Instruction::ToBool);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::IsOp(bytecode::Invert::No)); // is None?
emit!(
self,
Instruction::PopJumpIfFalse {
Instruction::PopJumpIfTrue {
target: no_match_block
}
);
Expand Down Expand Up @@ -2369,9 +2370,10 @@ impl Compiler {
);
// Stack: [result] (exception to reraise or None)

// CopyItem(1) copies TOS
// Check if result is not None (use identity check, not truthiness)
emit!(self, Instruction::CopyItem { index: 1 });
emit!(self, Instruction::ToBool);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::IsOp(bytecode::Invert::Yes)); // is not None?
emit!(
self,
Instruction::PopJumpIfTrue {
Expand Down
25 changes: 16 additions & 9 deletions crates/vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2459,7 +2459,7 @@ fn check_except_star_type_valid(match_type: &PyObjectRef, vm: &VirtualMachine) -
// If it's a tuple, check each element
if let Ok(tuple) = match_type.clone().downcast::<PyTuple>() {
for item in tuple.iter() {
check_one(&item)?;
check_one(item)?;
}
} else {
check_one(match_type)?;
Expand Down Expand Up @@ -2510,6 +2510,13 @@ pub fn exception_group_match(
// Check for partial match if it's an exception group
if exc_value.fast_isinstance(vm.ctx.exceptions.base_exception_group) {
let pair = vm.call_method(exc_value, "split", (match_type.clone(),))?;
if !pair.class().is(vm.ctx.types.tuple_type) {
return Err(vm.new_type_error(format!(
"{}.split must return a tuple, not {}",
exc_value.class().name(),
pair.class().name()
)));
}
let pair_tuple: PyTupleRef = pair.try_into_value(vm)?;
if pair_tuple.len() < 2 {
return Err(vm.new_type_error(format!(
Expand All @@ -2528,7 +2535,7 @@ pub fn exception_group_match(
}

/// Prepare exception for reraise in except* block.
/// Implements _PyExc_PrepReraiseStar from Objects/exceptions.c
/// Implements _PyExc_PrepReraiseStar
pub fn prep_reraise_star(orig: PyObjectRef, excs: PyObjectRef, vm: &VirtualMachine) -> PyResult {
use crate::builtins::PyList;

Expand Down Expand Up @@ -2633,11 +2640,11 @@ fn collect_exception_group_leaf_ids(
}

// Recurse into exception group's exceptions
if let Ok(excs_attr) = exc.get_attr("exceptions", vm) {
if let Ok(tuple) = excs_attr.downcast::<PyTuple>() {
for e in tuple.iter() {
collect_exception_group_leaf_ids(&e, leaf_ids, vm);
}
if let Ok(excs_attr) = exc.get_attr("exceptions", vm)
&& let Ok(tuple) = excs_attr.downcast::<PyTuple>()
{
for e in tuple.iter() {
collect_exception_group_leaf_ids(e, leaf_ids, vm);
}
}
}
Expand Down Expand Up @@ -2689,7 +2696,7 @@ fn split_by_leaf_ids(

let mut matched = Vec::new();
for e in tuple.iter() {
let m = split_by_leaf_ids(&e, leaf_ids, vm)?;
let m = split_by_leaf_ids(e, leaf_ids, vm)?;
if !vm.is_none(&m) {
matched.push(m);
}
Expand All @@ -2699,7 +2706,7 @@ fn split_by_leaf_ids(
return Ok(vm.ctx.none());
}

// Reconstruct using derive() to preserve the exception group type
// Reconstruct using derive() to preserve the structure (not necessarily the subclass type)
let matched_tuple = vm.ctx.new_tuple(matched);
vm.call_method(exc, "derive", (matched_tuple,))
}
4 changes: 2 additions & 2 deletions crates/vm/src/frame.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
builtins::{
PyBaseExceptionRef, PyBaseException, PyCode, PyCoroutine, PyDict, PyDictRef, PyGenerator, PyList, PySet,
PySlice, PyStr, PyStrInterned, PyStrRef, PyTraceback, PyType,
PyBaseException, PyBaseExceptionRef, PyCode, PyCoroutine, PyDict, PyDictRef, PyGenerator,
PyList, PySet, PySlice, PyStr, PyStrInterned, PyStrRef, PyTraceback, PyType,
asyncgenerator::PyAsyncGenWrappedValue,
function::{PyCell, PyCellRef, PyFunction},
tuple::{PyTuple, PyTupleRef},
Expand Down