Visitar URL original
Infer native calling convention flags from argument metadata by youknowone · Pull Request #9005 · RustPython/RustPython · GitHub
Skip to content

Infer native calling convention flags from argument metadata - #9005

Merged
youknowone merged 1 commit into
RustPython:mainfrom
youknowone:native-call-convention
Oct 8, 2026
Merged

youknowone merged 1 commit into
RustPython:mainfrom
youknowone:native-call-convention

Conversation

@youknowone

@youknowone youknowone commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary

Native functions now get their calling convention flags (NOARGS, O, FASTCALL, FASTCALL | KEYWORDS) from the FromArgs::PARAMS metadata of each argument. The PyMethodDef constructors compute them. Before this change, the derive macros guessed the flags from Rust type names.

This is split out of #8957. That PR rejects unsupported keywords before argument binding, which only works if KEYWORDS is accurate on every PyMethodDef. On main it is not:

  • list.sort(&self, options: SortOptions) is flagged O.
  • sorted is flagged FASTCALL without KEYWORDS.
  • Definitions built without the macros (the __new__ wrapper, vm.new_function, AST.__replace__) have no calling convention at all.

Details

  • IntoPyNativeFn::ARGS exposes the binding metadata of each argument. A &self / &Py<Self> receiver appears as the $self marker.
  • PyMethodFlags::with_call_convention adds the inferred calling convention unless the flags already contain one. Flags that already have one, such as C-API ml_flags, are kept as they are. With METHOD or CLASS, the first argument is the bound receiver and is not counted.
  • PyMethodDef::new_const, PyMethodDef::new_raw_const and Context::new_method_def apply it. Raw functions get FASTCALL | KEYWORDS.
  • The derive macros pass only binding flags. The string-based infer_native_call_flags is removed.

Behavior

Nothing visible from Python changes. On main, these flags are read only to pick a CALL specialization in frame.rs, and specialized calls still bind arguments through vectorcall. What changes is which specialization gets picked:

  • Definitions built without the macros now carry flags, so they can be specialized.
  • derive(FromArgs) struct arguments get accurate flags instead of being counted as one positional argument.

API: PyMethodDef::new_const takes a generic F: IntoPyNativeFn<Kind> instead of impl IntoPyNativeFn<Kind>. IntoPyNativeFn gains an associated ARGS const with a default.

Testing

  • cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --exclude rustpython-capi
  • cargo test from crates/capi
  • Workspace and C-API clippy, cargo fmt --all --check
  • Snippets: syntax_function_args.py, builtin_type.py
  • Release -m test: test_extcall test_call test_builtin test_list test_ast test_descr test_int test_inspect test_datetime test_csv test_enum test_types test_functools test_dataclasses test_typing test_copy test_dict test_str test_os test_io (20 modules, all passed)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Native methods and module functions now use calling conventions based on their argument signatures, improving compatibility for functions with positional, keyword, optional, and variadic arguments.
    • Bound methods and class methods now account for their receiver when determining how calls are handled.

`PyMethodDef::new_const`, `PyMethodDef::new_raw_const` and
`Context::new_method_def` add the calling convention (`NOARGS`, `O`,
`FASTCALL`, or `FASTCALL | KEYWORDS`) inferred from the
`FromArgs::PARAMS` of each argument, exposed as `IntoPyNativeFn::ARGS`.
Flags that already contain a calling convention, such as C-API
`ml_flags`, are kept. For `METHOD` and `CLASS` the first argument is the
bound receiver. Raw functions get `FASTCALL | KEYWORDS`.

The derive macros pass only binding flags and no longer infer call flags
from Rust type names. Definitions built without the macros, such as the
`__new__` wrapper and `vm.new_function`, get calling convention flags the
same way.

Assisted-by: Claude Code:claude-opus-5-5
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: RustPython/RustPython/.coderabbit.yml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c234ff99-a74e-4dec-993e-03049fe827de
📥 Commits

Reviewing files that changed from the base of the PR and between ca9dbb4 and 823ca0c.

📒 Files selected for processing (7)
  • crates/derive-impl/src/pyclass.rs
  • crates/derive-impl/src/pymodule.rs
  • crates/derive-impl/src/util.rs
  • crates/vm/src/function/builtin.rs
  • crates/vm/src/function/method.rs
  • crates/vm/src/function/signature.rs
  • crates/vm/src/vm/context.rs
💤 Files with no reviewable changes (1)
  • crates/derive-impl/src/util.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Native function implementations now expose argument-signature metadata. Method definitions use that metadata to infer native call-convention flags. Derive macros no longer infer these flags from Rust function signatures.

Changes

Native call conventions

Layer / File(s) Summary
Expose native argument metadata
crates/vm/src/function/builtin.rs
IntoPyNativeFn exposes ARGS metadata. Generated implementations describe extracted arguments and mark receiver arguments with "$self".
Infer and apply call-convention flags
crates/vm/src/function/signature.rs, crates/vm/src/function/method.rs, crates/vm/src/vm/context.rs
native_call_flags selects flags from argument metadata, including defaults, keyword-capable parameters, variadics, flattened parameters, and receivers. Method-definition construction applies inferred flags unless a convention is already supplied.
Remove derive-time call-flag inference
crates/derive-impl/src/pyclass.rs, crates/derive-impl/src/pymodule.rs, crates/derive-impl/src/util.rs
Class and module derives stop inferring and storing call flags from Rust signatures. Generated definitions retain binding flags or use empty flags. The old inference utility is removed.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Suggested reviewers: leehanjeong

Merge Risk: ⚪ Minimal · up to 823ca

This change infers native call-convention flags from argument metadata instead of from Rust signatures in the derive macros. Python-visible behavior is reported to stay the same, and the author reports the test suites passing. No merge-blocking risk was found.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: deriving native calling-convention flags from argument metadata.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@youknowone

Copy link
Copy Markdown
Member Author

cc @widehyo1

@youknowone
youknowone merged commit bb9ef5d into RustPython:main Oct 8, 2026
21 checks passed
@youknowone
youknowone deleted the native-call-convention branch October 8, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant