Skip to content

Commit 17ab286

Browse files
committed
Fix object.__init__ excess-arg checks for heap types
1 parent 578bc62 commit 17ab286

File tree

3 files changed

+10
-7
lines changed

3 files changed

+10
-7
lines changed

Lib/test/test_class.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,6 @@ def __setattr__(self, name, value) -> None:
741741
with self.assertRaisesRegex(AttributeError, error_msg):
742742
del B().z
743743

744-
@unittest.expectedFailure # TODO: RUSTPYTHON
745744
def testConstructorErrorMessages(self):
746745
# bpo-31506: Improves the error message logic for object_new & object_init
747746

Lib/test/test_descr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,6 @@ class C(list):
18531853
__new__ = object.__new__
18541854
self.assertRaises(TypeError, C)
18551855

1856-
@unittest.expectedFailure # TODO: RUSTPYTHON
18571856
def test_object_new(self):
18581857
class A(object):
18591858
pass

crates/vm/src/builtins/object.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl Initializer for PyBaseObject {
125125
}
126126

127127
let typ = zelf.class();
128-
let object_type = &vm.ctx.types.object_type;
128+
let object_type = vm.ctx.types.object_type;
129129

130130
let typ_init = typ.slots.init.load().map(|f| f as usize);
131131
let object_init = object_type.slots.init.load().map(|f| f as usize);
@@ -138,11 +138,16 @@ impl Initializer for PyBaseObject {
138138
));
139139
}
140140

141-
let typ_new = typ.slots.new.load().map(|f| f as usize);
142-
let object_new = object_type.slots.new.load().map(|f| f as usize);
143-
144141
// if (type->tp_new == object_new) → second error
145-
if typ_new == object_new {
142+
// Can't compare slot pointers for __new__ because update_one_slot
143+
// unconditionally sets new_wrapper for all heap types. Use get_attr
144+
// identity check instead — this works for __new__ because add_operators
145+
// skips it, so no duplicate PyWrapper objects are created.
146+
if let (Some(typ_new), Some(object_new)) = (
147+
typ.get_attr(identifier!(vm, __new__)),
148+
object_type.get_attr(identifier!(vm, __new__)),
149+
) && typ_new.is(&object_new)
150+
{
146151
return Err(vm.new_type_error(format!(
147152
"{}.__init__() takes exactly one argument (the instance to initialize)",
148153
typ.name()

0 commit comments

Comments
 (0)