Skip to content

Commit 0d4e960

Browse files
committed
Name the type whose constructor or initializer bound the arguments
`Constructor::slot_new` and `Initializer::slot_init` bound their arguments without a name, and so did the slots that override them, so a constructor that was called wrongly said only `expected 1 argument, got 0`. Both defaults and every override now name the type the slot was written for, not the subclass being constructed and not the module `tp_name` carries: `float expected at most 1 argument, got 2`, and `deque expected at most 2 arguments, got 3` for a `deque` subclass. `slice()` and `range()` counted their own arguments and raised messages of their own; they now raise the one `_PyArg_CheckPositional` raises, which makes `test_range_constructor_error_messages` pass. Assisted-by: Claude
1 parent 5ce3f6c commit 0d4e960

26 files changed

Lines changed: 173 additions & 55 deletions

‎Lib/test/test_range.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ def test_range(self):
9191
r = range(-sys.maxsize, sys.maxsize, 2)
9292
self.assertEqual(len(r), sys.maxsize)
9393

94-
@unittest.expectedFailure # TODO: RUSTPYTHON
9594
def test_range_constructor_error_messages(self):
9695
with self.assertRaisesRegex(
9796
TypeError,

‎crates/stdlib/src/contextvars.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod _contextvars {
2020
lock::{LazyLock, PyMutex},
2121
wtf8::Wtf8Buf,
2222
},
23-
function::{ArgCallable, FuncArgs, OptionalArg},
23+
function::{ArgCallable, Callee, FuncArgs, OptionalArg},
2424
protocol::{PyMappingMethods, PySequenceMethods},
2525
types::{AsMapping, AsSequence, Constructor, Hashable, Iterable, Representable},
2626
};
@@ -484,7 +484,7 @@ mod _contextvars {
484484
type Args = ContextVarOptions;
485485

486486
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
487-
let args: Self::Args = args.bind(vm)?;
487+
let args: Self::Args = args.bind_for(vm, Callee::of::<Self>(vm))?;
488488
let var = Self {
489489
name: args.name.to_string(),
490490
default: args.default.into_option(),

‎crates/vm/src/builtins/bool.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
AsObject, Context, Py, PyObject, PyObjectRef, PyResult, TryFromBorrowedObject, VirtualMachine,
55
class::PyClassImpl,
66
convert::{IntoPyException, ToPyObject, ToPyResult},
7-
function::{FuncArgs, OptionalArg},
7+
function::{Callee, FuncArgs, OptionalArg},
88
protocol::PyNumberMethods,
99
types::{AsNumber, Constructor, Representable},
1010
};
@@ -87,7 +87,7 @@ impl Constructor for PyBool {
8787
type Args = OptionalArg<PyObjectRef>;
8888

8989
fn slot_new(zelf: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
90-
let x: Self::Args = args.bind(vm)?;
90+
let x: Self::Args = args.bind_for(vm, Callee::of::<Self>(vm))?;
9191
if !zelf.fast_isinstance(vm.ctx.types.type_type) {
9292
return Err(vm.new_type_error(format!(
9393
"requires a 'type' object but received a '{}'",

‎crates/vm/src/builtins/bytes.rs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use crate::{
1717
class::PyClassImpl,
1818
common::{hash::PyHash, lock::PyMutex},
1919
convert::{ToPyObject, ToPyResult},
20-
function::{ArgBytesLike, ArgIndex, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue},
20+
function::{
21+
ArgBytesLike, ArgIndex, Callee, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue,
22+
},
2123
protocol::{
2224
BufferDescriptor, BufferFlags, BufferMethods, PyBuffer, PyIterReturn, PyMappingMethods,
2325
PyNumberMethods, PySequenceMethods,
@@ -95,7 +97,7 @@ impl Constructor for PyBytes {
9597
type Args = Vec<u8>;
9698

9799
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
98-
let options: ByteInnerNewOptions = args.bind(vm)?;
100+
let options: ByteInnerNewOptions = args.bind_for(vm, Callee::of::<Self>(vm))?;
99101

100102
// Optimizations for exact bytes type
101103
if cls.is(vm.ctx.types.bytes_type) {

‎crates/vm/src/builtins/classmethod.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
44
class::PyClassImpl,
55
common::lock::PyMutex,
6-
function::{FuncArgs, PySetterValue},
6+
function::{Callee, FuncArgs, PySetterValue},
77
types::{Constructor, GetDescriptor, Initializer, Representable},
88
};
99

@@ -70,7 +70,7 @@ impl Constructor for PyClassMethod {
7070
// copying its attributes to `__init__` so that subclasses overriding
7171
// `__init__` without calling `super().__init__()` see `__func__` as
7272
// `None`, matching CPython.
73-
let _: Self::Args = args.bind(vm)?;
73+
let _: Self::Args = args.bind_for(vm, Callee::of::<Self>(vm))?;
7474
let classmethod = Self {
7575
callable: PyMutex::new(vm.ctx.none()),
7676
};

‎crates/vm/src/builtins/complex.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
class::PyClassImpl,
66
common::{format::FormatSpec, wtf8::Wtf8Buf},
77
convert::{IntoPyException, ToPyObject, ToPyResult},
8-
function::{FuncArgs, OptionalArg, PyComparisonValue},
8+
function::{Callee, FuncArgs, OptionalArg, PyComparisonValue},
99
protocol::PyNumberMethods,
1010
stdlib::_warnings,
1111
types::{AsNumber, Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
@@ -395,7 +395,7 @@ impl Constructor for PyComplex {
395395
return Ok(func_args.args[0].clone());
396396
}
397397

398-
let args: Self::Args = func_args.bind(vm)?;
398+
let args: Self::Args = func_args.bind_for(vm, Callee::of::<Self>(vm))?;
399399
let payload = Self::py_new(&cls, args, vm)?;
400400
payload.into_ref_with_type(vm, cls).map(Into::into)
401401
}

‎crates/vm/src/builtins/float.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use crate::{
99
common::{float_ops, format::FormatSpec, hash, wtf8::Wtf8Buf},
1010
convert::{IntoPyException, ToPyObject, ToPyResult},
1111
function::{
12-
ArgBytesLike, FuncArgs, OptionalArg, OptionalOption, PyArithmeticValue, PyComparisonValue,
12+
ArgBytesLike, Callee, FuncArgs, OptionalArg, OptionalOption, PyArithmeticValue,
13+
PyComparisonValue,
1314
},
1415
protocol::PyNumberMethods,
1516
types::{AsNumber, Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
@@ -178,7 +179,7 @@ impl Constructor for PyFloat {
178179
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
179180
// Bind before the fast path so FromArgs::arity decides how many arguments
180181
// are acceptable, rather than a count repeated here.
181-
let arg: Self::Args = args.bind(vm)?;
182+
let arg: Self::Args = args.bind_for(vm, Callee::of::<Self>(vm))?;
182183

183184
// Optimization: return exact float as-is
184185
if cls.is(vm.ctx.types.float_type)

‎crates/vm/src/builtins/int.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use crate::{
1313
},
1414
convert::{IntoPyException, ToPyObject, ToPyResult},
1515
function::{
16-
ArgByteOrder, ArgIntoBool, FuncArgs, OptionalArg, OptionalOption, PyArithmeticValue,
17-
PyComparisonValue,
16+
ArgByteOrder, ArgIntoBool, Callee, FuncArgs, OptionalArg, OptionalOption,
17+
PyArithmeticValue, PyComparisonValue,
1818
},
1919
protocol::{PyNumberMethods, handle_bytes_to_int_err, numeric_literal_from_str},
2020
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
@@ -259,7 +259,7 @@ impl Constructor for PyInt {
259259
return Ok(args.args[0].clone());
260260
}
261261

262-
let options: IntOptions = args.bind(vm)?;
262+
let options: IntOptions = args.bind_for(vm, Callee::of::<Self>(vm))?;
263263
let value = if let OptionalArg::Present(val) = options.val_options {
264264
if let OptionalArg::Present(base) = options.base {
265265
let base = base

‎crates/vm/src/builtins/range.rs‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
VirtualMachine, atomic_func,
99
class::PyClassImpl,
1010
common::hash::PyHash,
11-
function::{ArgIndex, FuncArgs, OptionalArg, PyComparisonValue},
11+
function::{ArgIndex, Callee, FuncArgs, OptionalArg, PyComparisonValue},
1212
protocol::{PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
1313
types::{
1414
AsMapping, AsNumber, AsSequence, Comparable, Hashable, IterNext, Iterable, PyComparisonOp,
@@ -351,11 +351,13 @@ impl PyRange {
351351

352352
#[pyslot]
353353
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
354-
let range = if args.args.len() <= 1 {
355-
let stop = args.bind(vm)?;
354+
let range = if args.args.is_empty() {
355+
return Err(Callee::of::<Self>(vm).arity_error(1..=3, 0, vm));
356+
} else if args.args.len() == 1 {
357+
let stop = args.bind_for(vm, Callee::of::<Self>(vm))?;
356358
Self::new(cls, stop, vm)
357359
} else {
358-
let (start, stop, step) = args.bind(vm)?;
360+
let (start, stop, step) = args.bind_for(vm, Callee::of::<Self>(vm))?;
359361
Self::new_from(cls, start, stop, step, vm)
360362
}?;
361363

‎crates/vm/src/builtins/set.rs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ use crate::{
1818
},
1919
convert::ToPyResult,
2020
dict_inner::{self, DictSize},
21-
function::{ArgIterable, FuncArgs, OptionalArg, PosArgs, PyArithmeticValue, PyComparisonValue},
21+
function::{
22+
ArgIterable, Callee, FuncArgs, OptionalArg, PosArgs, PyArithmeticValue, PyComparisonValue,
23+
},
2224
protocol::{PyIterReturn, PyNumberMethods, PySequenceMethods},
2325
recursion::ReprGuard,
2426
types::AsNumber,
@@ -1077,7 +1079,7 @@ impl Constructor for PyFrozenSet {
10771079

10781080
// Optimizations for exact frozenset type
10791081
let iterable_opt = if is_exact_frozenset || is_frozenset_init {
1080-
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;
1082+
let iterable: OptionalArg<PyObjectRef> = args.bind_for(vm, Callee::of::<Self>(vm))?;
10811083

10821084
// Return exact frozenset as-is
10831085
if is_exact_frozenset

0 commit comments

Comments
 (0)