From 20f12d32e24de79f40279b4ed12a426def33cd8c Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 24 Dec 2025 23:36:14 +0900 Subject: [PATCH 1/2] clean up hash --- crates/vm/src/class.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/crates/vm/src/class.rs b/crates/vm/src/class.rs index 1addf00497..40f01d98b0 100644 --- a/crates/vm/src/class.rs +++ b/crates/vm/src/class.rs @@ -165,25 +165,15 @@ pub trait PyClassImpl: PyClassDef { "Initialize self. See help(type(self)) for accurate signature." ); add_slot_wrapper!(repr, __repr__, Repr, "Return repr(self)."); + add_slot_wrapper!(str, __str__, Str, "Return str(self)."); add_slot_wrapper!(iter, __iter__, Iter, "Implement iter(self)."); add_slot_wrapper!(iternext, __next__, IterNext, "Implement next(self)."); // __hash__ needs special handling: hash_not_implemented sets __hash__ = None - if let Some(hash_func) = class.slots.hash.load() { - if hash_func as usize == hash_not_implemented as usize { - class.set_attr(ctx.names.__hash__, ctx.none.clone().into()); - } else { - let hash_name = identifier!(ctx, __hash__); - if !class.attributes.read().contains_key(hash_name) { - let wrapper = PySlotWrapper { - typ: class, - name: ctx.intern_str("__hash__"), - wrapped: SlotFunc::Hash(hash_func), - doc: Some("Return hash(self)."), - }; - class.set_attr(hash_name, wrapper.into_ref(ctx).into()); - } - } + if class.slots.hash.load().map_or(0, |h| h as usize) == hash_not_implemented as usize { + class.set_attr(ctx.names.__hash__, ctx.none.clone().into()); + } else { + add_slot_wrapper!(hash, __hash__, Hash, "Return hash(self)."); } class.extend_methods(class.slots.methods, ctx); From ed736da99e6772ffc283411a6f0228996a48723d Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 24 Dec 2025 23:36:20 +0900 Subject: [PATCH 2/2] __str__ slot wrapper --- Lib/test/test_inspect/test_inspect.py | 1 - crates/vm/src/builtins/descriptor.rs | 13 +++++++++---- crates/vm/src/builtins/object.rs | 4 ++-- crates/vm/src/types/slot.rs | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index e403ab7b22..353d7c2e7b 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -409,7 +409,6 @@ class NotFuture: pass coro.close(); gen_coro.close() # silence warnings - @unittest.expectedFailure # TODO: RUSTPYTHON def test_isroutine(self): # method self.assertTrue(inspect.isroutine(git.argue)) diff --git a/crates/vm/src/builtins/descriptor.rs b/crates/vm/src/builtins/descriptor.rs index fcf40d0082..297199eee1 100644 --- a/crates/vm/src/builtins/descriptor.rs +++ b/crates/vm/src/builtins/descriptor.rs @@ -399,6 +399,7 @@ pub fn init(ctx: &Context) { pub enum SlotFunc { Init(InitFunc), Hash(HashFunc), + Str(StringifyFunc), Repr(StringifyFunc), Iter(IterFunc), IterNext(IterNextFunc), @@ -409,6 +410,7 @@ impl std::fmt::Debug for SlotFunc { match self { SlotFunc::Init(_) => write!(f, "SlotFunc::Init(...)"), SlotFunc::Hash(_) => write!(f, "SlotFunc::Hash(...)"), + SlotFunc::Str(_) => write!(f, "SlotFunc::Str(...)"), SlotFunc::Repr(_) => write!(f, "SlotFunc::Repr(...)"), SlotFunc::Iter(_) => write!(f, "SlotFunc::Iter(...)"), SlotFunc::IterNext(_) => write!(f, "SlotFunc::IterNext(...)"), @@ -433,11 +435,14 @@ impl SlotFunc { let hash = func(&obj, vm)?; Ok(vm.ctx.new_int(hash).into()) } - SlotFunc::Repr(func) => { + SlotFunc::Repr(func) | SlotFunc::Str(func) => { if !args.args.is_empty() || !args.kwargs.is_empty() { - return Err( - vm.new_type_error("__repr__() takes no arguments (1 given)".to_owned()) - ); + let name = match self { + SlotFunc::Repr(_) => "__repr__", + SlotFunc::Str(_) => "__str__", + _ => unreachable!(), + }; + return Err(vm.new_type_error(format!("{name}() takes no arguments (1 given)"))); } let s = func(&obj, vm)?; Ok(s.into()) diff --git a/crates/vm/src/builtins/object.rs b/crates/vm/src/builtins/object.rs index 854cb2701e..65a11d5531 100644 --- a/crates/vm/src/builtins/object.rs +++ b/crates/vm/src/builtins/object.rs @@ -425,8 +425,8 @@ impl PyBaseObject { } /// Return str(self). - #[pymethod] - fn __str__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { + #[pyslot] + fn slot_str(zelf: &PyObject, vm: &VirtualMachine) -> PyResult { // FIXME: try tp_repr first and fallback to object.__repr__ zelf.repr(vm) } diff --git a/crates/vm/src/types/slot.rs b/crates/vm/src/types/slot.rs index 26c059067e..57ac24f461 100644 --- a/crates/vm/src/types/slot.rs +++ b/crates/vm/src/types/slot.rs @@ -140,7 +140,7 @@ pub struct PyTypeSlots { // More standard operations (here for binary compatibility) pub hash: AtomicCell>, pub call: AtomicCell>, - // tp_str + pub str: AtomicCell>, pub repr: AtomicCell>, pub getattro: AtomicCell>, pub setattro: AtomicCell>,