Skip to content

Commit d9b1ae2

Browse files
committed
tp_del
1 parent 9e71cb3 commit d9b1ae2

5 files changed

Lines changed: 43 additions & 6 deletions

File tree

vm/src/macros.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ macro_rules! py_class {
4747
py_class
4848
}
4949
};
50-
(@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {
51-
$slots.$slot_name = Some(
50+
(@extract_slots($ctx:expr, $slots:expr, (slot new), $value:expr)) => {
51+
$slots.new = Some(
5252
$crate::function::IntoPyNativeFunc::into_func($value)
5353
);
5454
};
55+
(@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {
56+
$slots.$slot_name.store(Some($value));
57+
};
5558
(@extract_slots($ctx:expr, $class:expr, $name:expr, $value:expr)) => {};
5659
(@extract_attrs($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {};
5760
(@extract_attrs($ctx:expr, $class:expr, $name:expr, $value:expr)) => {

vm/src/obj/objtype.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ impl PyClassRef {
150150
} as _;
151151
self.slots.hash.store(Some(func));
152152
}
153+
"__del__" => {
154+
let func: slots::DelFunc = |zelf, vm| {
155+
let magic = get_class_magic(&zelf, "__del__");
156+
vm.invoke(&magic, vec![zelf.clone()]).map(|_| ())
157+
} as _;
158+
self.slots.del.store(Some(func));
159+
}
153160
_ => (),
154161
}
155162
}

vm/src/pyobjectrc.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ where
146146

147147
// CPython-compatible drop implementation
148148
let zelf = Self::into_ref(self.clone());
149-
if let Some(del_method) = zelf.inner.get_class_attr("__del__") {
149+
if let Some(del_slot) = zelf.class().first_in_mro(|cls| cls.slots.del.load()) {
150150
crate::vm::thread::with_vm(&zelf, |vm| {
151-
if let Err(e) = vm.invoke(&del_method, vec![zelf.clone()]) {
151+
if let Err(e) = del_slot(&zelf, vm) {
152152
// exception in del will be ignored but printed
153153
print!("Exception ignored in: ",);
154+
let del_method = zelf.get_class_attr("__del__").unwrap();
154155
let repr = vm.to_repr(&del_method);
155156
match repr {
156157
Ok(v) => println!("{}", v.to_string()),

vm/src/slots.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl Default for PyTpFlags {
4141
}
4242

4343
pub(crate) type GenericMethod = fn(PyObjectRef, PyFuncArgs, &VirtualMachine) -> PyResult;
44+
pub(crate) type DelFunc = fn(&PyObjectRef, &VirtualMachine) -> PyResult<()>;
4445
pub(crate) type DescrGetFunc =
4546
fn(PyObjectRef, Option<PyObjectRef>, Option<PyObjectRef>, &VirtualMachine) -> PyResult;
4647
pub(crate) type HashFunc = fn(&PyObjectRef, &VirtualMachine) -> PyResult<PyHash>;
@@ -50,6 +51,7 @@ pub struct PyClassSlots {
5051
pub flags: PyTpFlags,
5152
pub name: PyRwLock<Option<String>>, // tp_name, not class name
5253
pub new: Option<PyNativeFunc>,
54+
pub del: AtomicCell<Option<DelFunc>>,
5355
pub call: AtomicCell<Option<GenericMethod>>,
5456
pub descr_get: AtomicCell<Option<DescrGetFunc>>,
5557
pub hash: AtomicCell<Option<HashFunc>>,
@@ -82,6 +84,25 @@ impl std::fmt::Debug for PyClassSlots {
8284
}
8385
}
8486

87+
#[pyimpl]
88+
pub trait SlotDesctuctor: PyValue {
89+
#[pyslot]
90+
fn tp_del(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
91+
if let Some(zelf) = zelf.downcast_ref() {
92+
Self::del(zelf, vm)
93+
} else {
94+
Err(vm.new_type_error("unexpected payload for __del__".to_owned()))
95+
}
96+
}
97+
98+
#[pymethod(magic)]
99+
fn __del__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
100+
Self::del(&zelf, vm)
101+
}
102+
103+
fn del(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<()>;
104+
}
105+
85106
#[pyimpl]
86107
pub trait SlotCall: PyValue {
87108
#[pymethod(magic)]

vm/src/stdlib/io.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,15 @@ fn io_base_cm_enter(instance: PyObjectRef) -> PyObjectRef {
416416
instance
417417
}
418418

419-
fn io_base_cm_del(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
420-
vm.call_method(&instance, "close", vec![])?;
419+
fn io_base_cm_del_slot(instance: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
420+
vm.call_method(instance, "close", vec![])?;
421421
Ok(())
422422
}
423423

424+
fn io_base_cm_del(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
425+
io_base_cm_del_slot(&instance, vm)
426+
}
427+
424428
fn io_base_cm_exit(instance: PyObjectRef, _args: PyFuncArgs, vm: &VirtualMachine) -> PyResult<()> {
425429
vm.call_method(&instance, "close", vec![])?;
426430
Ok(())
@@ -1271,6 +1275,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
12711275
let io_base = py_class!(ctx, "_IOBase", &ctx.types.object_type, {
12721276
"__enter__" => ctx.new_method(io_base_cm_enter),
12731277
"__del__" => ctx.new_method(io_base_cm_del),
1278+
(slot del) => io_base_cm_del_slot,
12741279
"__exit__" => ctx.new_method(io_base_cm_exit),
12751280
"seekable" => ctx.new_method(io_base_seekable),
12761281
"readable" => ctx.new_method(io_base_readable),

0 commit comments

Comments
 (0)