From b31b8125c7df2ea38b34989d4fc9126a6adf35ad Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Sun, 15 Mar 2026 23:49:39 +0900 Subject: [PATCH 1/5] Define only wrapper_descriptor --- crates/vm/src/types/slot.rs | 105 +------------------------------ crates/vm/src/types/structseq.rs | 5 -- 2 files changed, 2 insertions(+), 108 deletions(-) diff --git a/crates/vm/src/types/slot.rs b/crates/vm/src/types/slot.rs index 222d827c7f5..8ffcfd0f3b6 100644 --- a/crates/vm/src/types/slot.rs +++ b/crates/vm/src/types/slot.rs @@ -3,13 +3,11 @@ use crate::common::lock::{ }; use crate::{ AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, - builtins::{PyInt, PyStr, PyStrInterned, PyStrRef, PyType, PyTypeRef}, + builtins::{PyInt, PyStr, PyStrInterned, PyType, PyTypeRef}, bytecode::ComparisonOperator, common::hash::{PyHash, fix_sentinel, hash_bigint}, convert::ToPyObject, - function::{ - Either, FromArgs, FuncArgs, OptionalArg, PyComparisonValue, PyMethodDef, PySetterValue, - }, + function::{Either, FromArgs, FuncArgs, PyComparisonValue, PyMethodDef, PySetterValue}, protocol::{ PyBuffer, PyIterReturn, PyMapping, PyMappingMethods, PyMappingSlots, PyNumber, PyNumberMethods, PyNumberSlots, PySequence, PySequenceMethods, PySequenceSlots, @@ -1681,11 +1679,6 @@ pub trait Destructor: PyPayload { Self::del(zelf, vm) } - #[pymethod] - fn __del__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - Self::slot_del(&zelf, vm) - } - fn del(zelf: &Py, vm: &VirtualMachine) -> PyResult<()>; } @@ -1711,11 +1704,6 @@ pub trait Callable: PyPayload { Self::call(zelf, args, vm) } - #[inline] - #[pymethod] - fn __call__(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { - Self::slot_call(&zelf, args.bind(vm)?, vm) - } fn call(zelf: &Py, args: Self::Args, vm: &VirtualMachine) -> PyResult; } @@ -1729,17 +1717,6 @@ pub trait GetDescriptor: PyPayload { vm: &VirtualMachine, ) -> PyResult; - #[inline] - #[pymethod] - fn __get__( - zelf: PyObjectRef, - obj: PyObjectRef, - cls: OptionalArg, - vm: &VirtualMachine, - ) -> PyResult { - Self::descr_get(zelf, Some(obj), cls.into_option(), vm) - } - #[inline] fn _as_pyref<'a>(zelf: &'a PyObject, vm: &VirtualMachine) -> PyResult<&'a Py> { zelf.try_to_value(vm) @@ -1847,61 +1824,6 @@ pub trait Comparable: PyPayload { op: PyComparisonOp, vm: &VirtualMachine, ) -> PyResult; - - #[inline] - #[pymethod] - fn __eq__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Eq, vm) - } - #[inline] - #[pymethod] - fn __ne__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Ne, vm) - } - #[inline] - #[pymethod] - fn __lt__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Lt, vm) - } - #[inline] - #[pymethod] - fn __le__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Le, vm) - } - #[inline] - #[pymethod] - fn __ge__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Ge, vm) - } - #[inline] - #[pymethod] - fn __gt__( - zelf: &Py, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { - Self::cmp(zelf, &other, PyComparisonOp::Gt, vm) - } } #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -2013,12 +1935,6 @@ pub trait GetAttr: PyPayload { } fn getattro(zelf: &Py, name: &Py, vm: &VirtualMachine) -> PyResult; - - #[inline] - #[pymethod] - fn __getattribute__(zelf: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult { - Self::slot_getattro(&zelf, &name, vm) - } } #[pyclass] @@ -2043,23 +1959,6 @@ pub trait SetAttr: PyPayload { value: PySetterValue, vm: &VirtualMachine, ) -> PyResult<()>; - - #[inline] - #[pymethod] - fn __setattr__( - zelf: PyObjectRef, - name: PyStrRef, - value: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult<()> { - Self::slot_setattro(&zelf, &name, PySetterValue::Assign(value), vm) - } - - #[inline] - #[pymethod] - fn __delattr__(zelf: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> { - Self::slot_setattro(&zelf, &name, PySetterValue::Delete, vm) - } } #[pyclass] diff --git a/crates/vm/src/types/structseq.rs b/crates/vm/src/types/structseq.rs index 0744d7a4a00..02d1a4d6349 100644 --- a/crates/vm/src/types/structseq.rs +++ b/crates/vm/src/types/structseq.rs @@ -243,11 +243,6 @@ pub trait PyStructSequence: StaticType + PyClassImpl + Sized + 'static { Ok(vm.ctx.new_str(repr_str)) } - #[pymethod] - fn __repr__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { - Self::slot_repr(&zelf, vm) - } - #[pymethod] fn __replace__(zelf: PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { if !args.args.is_empty() { From 6d863fbd49eaa472bb47b300d51183112cc34661 Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Sun, 15 Mar 2026 23:53:22 +0900 Subject: [PATCH 2/5] Implement missing slots for NoneType --- crates/vm/src/builtins/singletons.rs | 29 +++++++++++++++++++++++++--- extra_tests/snippets/builtin_none.py | 12 ++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/crates/vm/src/builtins/singletons.rs b/crates/vm/src/builtins/singletons.rs index c70ed08e3df..0ad9d88c3d3 100644 --- a/crates/vm/src/builtins/singletons.rs +++ b/crates/vm/src/builtins/singletons.rs @@ -2,12 +2,15 @@ use super::{PyStrRef, PyType, PyTypeRef}; use crate::{ Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, class::PyClassImpl, + common::hash::PyHash, convert::ToPyObject, - function::FuncArgs, + function::{FuncArgs, PyComparisonValue}, protocol::PyNumberMethods, - types::{AsNumber, Constructor, Representable}, + types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable}, }; +const NONE_HASH: PyHash = 0xFCA8_6420; + #[pyclass(module = false, name = "NoneType")] #[derive(Debug)] pub struct PyNone; @@ -49,7 +52,7 @@ impl Constructor for PyNone { } } -#[pyclass(with(Constructor, AsNumber, Representable))] +#[pyclass(with(Constructor, AsNumber, Comparable, Hashable, Representable))] impl PyNone {} impl Representable for PyNone { @@ -74,6 +77,26 @@ impl AsNumber for PyNone { } } +impl Comparable for PyNone { + fn cmp( + zelf: &Py, + other: &crate::PyObject, + op: PyComparisonOp, + _vm: &VirtualMachine, + ) -> PyResult { + Ok(op + .identical_optimization(zelf, other) + .map(PyComparisonValue::Implemented) + .unwrap_or(PyComparisonValue::NotImplemented)) + } +} + +impl Hashable for PyNone { + fn hash(_zelf: &Py, _vm: &VirtualMachine) -> PyResult { + Ok(NONE_HASH) + } +} + #[pyclass(module = false, name = "NotImplementedType")] #[derive(Debug)] pub struct PyNotImplemented; diff --git a/extra_tests/snippets/builtin_none.py b/extra_tests/snippets/builtin_none.py index 230a7229e02..061739153ff 100644 --- a/extra_tests/snippets/builtin_none.py +++ b/extra_tests/snippets/builtin_none.py @@ -26,3 +26,15 @@ def none2(): assert None.__ne__(3) is NotImplemented assert None.__eq__(None) is True assert None.__ne__(None) is False +assert None.__lt__(3) is NotImplemented +assert None.__le__(3) is NotImplemented +assert None.__gt__(3) is NotImplemented +assert None.__ge__(3) is NotImplemented + +none_type_dict = type(None).__dict__ +for name in ("__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__hash__"): + assert name in none_type_dict + assert none_type_dict[name] is not object.__dict__[name] + assert type(none_type_dict[name]).__name__ == "wrapper_descriptor" + +assert hash(None) & 0xFFFFFFFF == 0xFCA86420 From 6a08fdaf5a7953b9b5e6af94899bbbd961d6ed42 Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Mon, 16 Mar 2026 00:08:16 +0900 Subject: [PATCH 3/5] Unmark fixed tests --- Lib/test/test_types.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 5042b3c17b0..ced9e27fed5 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -630,7 +630,6 @@ def test_internal_sizes(self): self.assertGreater(object.__basicsize__, 0) self.assertGreater(tuple.__itemsize__, 0) - @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: is not an instance of def test_slot_wrapper_types(self): self.assertIsInstance(object.__init__, types.WrapperDescriptorType) self.assertIsInstance(object.__str__, types.WrapperDescriptorType) @@ -646,7 +645,6 @@ def test_dunder_get_signature(self): # gh-93021: Second parameter is optional self.assertIs(sig.parameters["owner"].default, None) - @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: is not an instance of def test_method_wrapper_types(self): self.assertIsInstance(object().__init__, types.MethodWrapperType) self.assertIsInstance(object().__str__, types.MethodWrapperType) From 4ababea40e6946d08a8d7c58390839af1d10b43d Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Mon, 16 Mar 2026 01:11:23 +0900 Subject: [PATCH 4/5] Inline PyNone hash value --- crates/vm/src/builtins/singletons.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/vm/src/builtins/singletons.rs b/crates/vm/src/builtins/singletons.rs index 0ad9d88c3d3..0fb84c4c49d 100644 --- a/crates/vm/src/builtins/singletons.rs +++ b/crates/vm/src/builtins/singletons.rs @@ -9,8 +9,6 @@ use crate::{ types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable}, }; -const NONE_HASH: PyHash = 0xFCA8_6420; - #[pyclass(module = false, name = "NoneType")] #[derive(Debug)] pub struct PyNone; @@ -93,7 +91,7 @@ impl Comparable for PyNone { impl Hashable for PyNone { fn hash(_zelf: &Py, _vm: &VirtualMachine) -> PyResult { - Ok(NONE_HASH) + Ok(0xFCA8_6420) } } From 07b792b13600387ce7205623c2b4adbd7eff0110 Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Mon, 16 Mar 2026 11:53:51 +0900 Subject: [PATCH 5/5] Improve searchability for NoneType hash value Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com> --- crates/vm/src/builtins/singletons.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/vm/src/builtins/singletons.rs b/crates/vm/src/builtins/singletons.rs index 0fb84c4c49d..00d84dfabb6 100644 --- a/crates/vm/src/builtins/singletons.rs +++ b/crates/vm/src/builtins/singletons.rs @@ -91,7 +91,7 @@ impl Comparable for PyNone { impl Hashable for PyNone { fn hash(_zelf: &Py, _vm: &VirtualMachine) -> PyResult { - Ok(0xFCA8_6420) + Ok(0xFCA86420) } }