From 6181bf4a7a0c6c41f6774fb07d64e042b7cff63e Mon Sep 17 00:00:00 2001 From: Zion Date: Fri, 1 Nov 2024 20:47:13 -0400 Subject: [PATCH 1/2] Add delete for object_set_dict --- vm/src/builtins/object.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index f783ee017c..02036a3cd5 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -495,9 +495,17 @@ pub fn object_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult PyResult<()> { - obj.set_dict(dict) - .map_err(|_| vm.new_attribute_error("This object has no __dict__".to_owned())) +pub fn object_set_dict(obj: PyObjectRef, dict: PySetterValue, vm: &VirtualMachine) -> PyResult<()> { + match dict { + PySetterValue::Some(dict) => { + obj.set_dict(dict) + .map_err(|_| vm.new_attribute_error("This object has no __dict__".to_owned())) + } + PySetterValue::None => { + obj.delete_dict() + .map_err(|_| vm.new_attribute_error("This object has no deletable __dict__".to_owned())) + } + } } pub fn init(ctx: &Context) { -- 2.49.1 From 20c053a3c05b8a4917b3df620e7efc7eea529b35 Mon Sep 17 00:00:00 2001 From: Myeongseon Choi Date: Sun, 9 Feb 2025 23:26:36 +0900 Subject: [PATCH 2/2] Refactor PySetterValue handling in object and type modules - Update object_set_dict to use new PySetterValue variants - Modify getset.rs to handle PySetterValue::Delete - Add delete_dict method to PyObject - Adjust type.rs to use new PySetterValue semantics --- vm/src/builtins/object.rs | 5 +++-- vm/src/builtins/type.rs | 2 +- vm/src/function/getset.rs | 6 ++++-- vm/src/object/core.rs | 13 +++++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index 02036a3cd5..679fbf52d4 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -495,13 +495,14 @@ pub fn object_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult, vm: &VirtualMachine) -> PyResult<()> { match dict { - PySetterValue::Some(dict) => { + PySetterValue::Assign(dict) => { obj.set_dict(dict) .map_err(|_| vm.new_attribute_error("This object has no __dict__".to_owned())) } - PySetterValue::None => { + PySetterValue::Delete => { obj.delete_dict() .map_err(|_| vm.new_attribute_error("This object has no deletable __dict__".to_owned())) } diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index 15df5ff3c5..e1d46bf494 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1288,7 +1288,7 @@ fn subtype_set_dict(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) - descr_set(&descr, obj, PySetterValue::Assign(value), vm) } None => { - object::object_set_dict(obj, value.try_into_value(vm)?, vm)?; + object::object_set_dict(obj, PySetterValue::Delete, vm)?; Ok(()) } } diff --git a/vm/src/function/getset.rs b/vm/src/function/getset.rs index 827158e834..4d66b6dd26 100644 --- a/vm/src/function/getset.rs +++ b/vm/src/function/getset.rs @@ -36,8 +36,10 @@ where { #[inline] fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult { - let obj = obj.ok_or_else(|| vm.new_type_error("can't delete attribute".to_owned()))?; - T::try_from_object(vm, obj) + match obj { + PySetterValue::Assign(obj) => T::try_from_object(vm, obj), + PySetterValue::Delete => T::try_from_object(vm, vm.ctx.none()), + } } } diff --git a/vm/src/object/core.rs b/vm/src/object/core.rs index b326935464..fc0d1e56ff 100644 --- a/vm/src/object/core.rs +++ b/vm/src/object/core.rs @@ -717,6 +717,19 @@ impl PyObject { } } + pub fn delete_dict(&self) -> Result<(), ()> { + match self.instance_dict() { + Some(_) => { + unsafe { + let ptr = self as *const _ as *mut PyObject; + (*ptr).0.dict = None; + } + Ok(()) + } + None => Err(()), + } + } + #[inline(always)] pub fn payload_if_subclass(&self, vm: &VirtualMachine) -> Option<&T> { if self.class().fast_issubclass(T::class(&vm.ctx)) { -- 2.49.1