Repository navigation
Conversation
FuncArgs::bind_for rejected surplus positional arguments only after FromArgs::from_args had converted every declared parameter. A conversion can run user code (__iter__ for PyIter, __index__ for ArgIndex), so filter(None, it, 0), hex(x, 1) and pairwise(it, 0) raised whatever that code raised instead of the TypeError CPython reports before it touches any argument. Check the count against FromArgs::arity() before from_args runs. For that bound to be safe: - The default arity() has no upper bound, since a manual impl may take positional arguments itself. KwArgs, (), DirFd, OpenDirFd and csv's FormatOptions declare the bound they actually have. - A derived struct adds the upper bound of each flattened field. - A tuple sums upper bounds with saturating_add. Assisted-by: Claude Code:claude-opus-5-5
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
| fn arity() -> ::std::ops::RangeInclusive<usize> { | ||
| #min_arity..=#max_arity | ||
| #min_arity..=#max_arity #( | ||
| .saturating_add(*<#flattened as ::rustpython_vm::function::FromArgs>::arity().end()) |
There was a problem hiding this comment.
could you tell me why saturating_add is required here? I am missing something.
Summary
FuncArgs::bind_forrejects leftover positional arguments only afterfrom_argshas converted every parameter. A conversion can run user code (__iter__forPyIter,__index__forArgIndex), so a call with too many arguments raises whatever that code raises. CPython checks the count first, infilter_vectorcalland incfunction_vectorcall_Oforhex()and friends. #8957 made the same change for keywords.AS-IS
TO-BE
(matching CPython's exception type; the
filtermessage is identical, thehexone keeps RustPython's shared wording)Changes
FromArgs::arity()inbind_forbeforefrom_argsruns.arity()unbounded, since a hand-written impl such asObjectArgsorReplaceChangesmay take any number of positional arguments itself. GiveKwArgs,(),DirFd,OpenDirFdand csv'sFormatOptionsthe bound they actually take, so their existing messages keep a finite count.arity(), and sum tuple bounds withsaturating_add.*argsnow saysexpected at least 1 argumentinstead ofexpected 1 argument(for examplestruct.pack()andint.__new__()). Both are stillTypeError.extra_tests/snippets/vm_argument_errors.py.Test plan
Built and run on macOS aarch64 against upstream/main 398dd70, using the CI feature set
--no-default-features --features stdlib,importlib,stdio,encodings,sqlite,ssl-rustls-aws-lc,host_env,doc,ucd_3_2_0, plusthreading, compared with CPython 3.14.4.itertools,operator,functools,mathand constructors with too many, too few and valid arguments: the patch changes exactly 10 results, all fromRuntimeErrortoTypeError(filtertwice,enumeratewith 3 arguments,hex,oct,bin,chr,itertools.compress,pairwiseandtakewhile). The other 59 are unchanged.rustpython -m test -j 6 --timeout 600on the unpatched and patched builds: 45,717 run on both, and the same 3 modules fail on both (test_cmd_line,test_dict,test_frame).pytest -k rustpythoninextra_tests: 246 pass on the patched build. On the unpatched build the only failure is the newvm_argument_errors.pycase, which also passes under CPython 3.14.4.cargo test -p rustpython-vm -p rustpython-derive-impl --lib: 128 pass.cargo fmt --checkclean,cargo clippy -p rustpython-vm -p rustpython-stdlib -p rustpython-derive-impl --all-targetsreports nothing, andpre-commit run --filespasses on the changed files.I used Claude Code (claude-opus-5-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
Compatibility