Reject extra positional arguments to float() - #8509
Conversation
PyFloat::slot_new's exact-float fast path tested args.args.first(), which
succeeds for any number of positional arguments, so float(1.5, True)
returned the first one and never reached args.bind(vm). CPython's clinic
generated float_new runs _PyArg_CheckPositional("float", nargs, 0, 1)
before it fetches the first argument.
Add args.args.len() == 1 to the condition, as PyInt::slot_new,
PyStr::slot_new and PyComplex::slot_new already do; the extra argument
then falls through to args.bind(vm) and raises TypeError.
Assisted-by: Claude Code:claude-opus-5
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe float constructor binds arguments before its exact-float reuse path. Extra positional arguments now raise ChangesFloat constructor validation
Estimated code review effort: 2 (Simple) | ~10 minutes Mergeability Score: ⚪ Minimal · up to The change makes float() reject extra positional arguments while preserving existing valid forms, with regression tests covering the affected behavior; no actionable merge-blocking risk remains. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The exact-float fast path repeated float()'s argument count inline, which duplicates what FromArgs::arity already knows. Bind first and match on the resulting OptionalArg instead, so the positional and keyword rules stay in one place and the bound value is reused by py_new. Assisted-by: Claude Code:claude-opus-5
float(1.5, True)returns the first argument instead of raisingTypeError#8461Summary
PyFloat::slot_new's exact-float fast path testedargs.args.first(), which succeeds for any number of positional arguments, sofloat(1.5, True)returned the first one and never reachedargs.bind(vm). CPython's clinic-generatedfloat_newruns_PyArg_CheckPositional("float", nargs, 0, 1)before it fetches the first argument.AS-IS
TO-BE
(matching CPython, which raises
TypeError: float expected at most 1 argument, got 2; the wording comes fromFuncArgs::bindand is a separate repo-wide difference)Changes
args.args.len() == 1to the fast path condition inPyFloat::slot_new, so an extra positional argument falls through toargs.bind(vm).PyInt::slot_new,PyStr::slot_newandPyComplex::slot_newalready guard the same optimization this way;floatwas the one that did not.extra_tests/snippets/builtin_float.pyfor two and three positional arguments, plus the unchangedfloat(1.5)andfloat()forms.Test plan
Built and run on macOS aarch64 against upstream/main
525ba8cf0, using the CI feature set--no-default-features --features stdlib,importlib,stdio,encodings,sqlite,ssl-rustls-aws-lc,host_env.float(1.5, True)returned1.5; with the patch it raisesTypeError.float(1.5),float(),float("1.5")andfloatsubclass construction are unchanged.cargo run --release -- -m test test_float test_builtin test_complex: 229 run, 18 skipped, all pass.cargo test --workspace --exclude rustpython-capi --exclude rustpython_wasm --exclude rustpython-compiler-source --exclude rustpython-venvlauncher --features threading: 1107 pass, 0 fail.cargo testincrates/capi: 102 pass.extra_testsbuiltin snippets under RustPython: 66 of 67 pass, the newbuiltin_float.pycases among them. The one failure,builtin_thread.py, asserts_thread.TIMEOUT_MAX in [9223372036.0, 4294967.0]and my build reports2147483648, which is an unrelated platform constant.cargo fmt --checkclean,cargo clippy -p rustpython-vm --all-targetsreports nothing on the changed file, andpre-commit run --filespasses on both changed files.I used Claude Code (claude-opus-5) to draft the analysis, the patch and this description; I reviewed the change and ran every command above myself.
Summary by CodeRabbit
Bug Fixes
float()so it rejects calls with multiple positional arguments.Tests