Skip to content

Commit 3538304

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

File tree

3 files changed

+22
-21
lines changed

3 files changed

+22
-21
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: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -127,26 +127,29 @@ impl Initializer for PyBaseObject {
127127
let typ = zelf.class();
128128
let object_type = &vm.ctx.types.object_type;
129129

130-
let typ_init = typ.slots.init.load().map(|f| f as usize);
131-
let object_init = object_type.slots.init.load().map(|f| f as usize);
132-
133-
// if (type->tp_init != object_init) → first error
134-
if typ_init != object_init {
135-
return Err(vm.new_type_error(
136-
"object.__init__() takes exactly one argument (the instance to initialize)"
137-
.to_owned(),
138-
));
139-
}
140-
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);
130+
if let (Some(typ_init), Some(object_init)) = (
131+
typ.get_attr(identifier!(vm, __init__)),
132+
object_type.get_attr(identifier!(vm, __init__)),
133+
) {
134+
// if (type->tp_init != object_init) → first error
135+
if !typ_init.is(&object_init) {
136+
return Err(vm.new_type_error(
137+
"object.__init__() takes exactly one argument (the instance to initialize)"
138+
.to_owned(),
139+
));
140+
}
143141

144-
// if (type->tp_new == object_new) → second error
145-
if typ_new == object_new {
146-
return Err(vm.new_type_error(format!(
147-
"{}.__init__() takes exactly one argument (the instance to initialize)",
148-
typ.name()
149-
)));
142+
// if (type->tp_new == object_new) → second error
143+
if let (Some(typ_new), Some(object_new)) = (
144+
typ.get_attr(identifier!(vm, __new__)),
145+
object_type.get_attr(identifier!(vm, __new__)),
146+
) && typ_new.is(&object_new)
147+
{
148+
return Err(vm.new_type_error(format!(
149+
"{}.__init__() takes exactly one argument (the instance to initialize)",
150+
typ.name()
151+
)));
152+
}
150153
}
151154

152155
// Both conditions false → OK (e.g., tuple, dict with custom __new__)

0 commit comments

Comments
 (0)