Reject payload receivers on #[pymethod] and #[pygetset] (#8898)

* Report errors from #[pyclass] trait items

The trait branch of impl_pyclass_impl built its own ImplContext, so the
errors collected while extracting trait items were never emitted: an
invalid #[pymethod] or #[pygetset] in a #[pyclass] trait was left out of
the class without a compile error. The trait branch now uses the shared
context whose errors are emitted.

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

* Pass the object to #[pymethod] and #[pygetset] receivers outside vm

Outside crates/vm, where impl Py<T> cannot be written, #[pymethod] and
#[pygetset] receivers that took &self become zelf: &Py<Self> inside the
existing impl T blocks. Where Rust code calls one of these methods on a
payload value, the logic stays in a payload method and the Python method
forwards to it.

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Grok:grok-4.7

* Reject payload receivers on #[pymethod] and #[pygetset]

A #[pymethod] or #[pygetset] item with a self receiver is now a compile
error when self is the payload: in an impl for T rather than Py<T> or
PyRef<T>, and in a #[pyclass] trait. The error points to taking
zelf: &Py<Self> or zelf: PyRef<Self>, or defining the item in impl Py<T>.

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

* Pass the object to the layout test getter

The subclass layout test's extra getter is a #[pygetset] on the
payload. Take zelf: &Py<Self> so the receiver is the object.

Assisted-by: Grok:4.7
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2026-09-30 22:12:16 +09:00
1 parent 536737f4a0
commit 100dac0bbe
37 files changed
+2150 -1808

No files matched your search

+4 -4
View File
@@ -1,6 +1,6 @@
use rustpython::InterpreterBuilderExt;
use rustpython::vm::{
PyObject, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine, pyclass, pymodule,
Py, PyObject, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine, pyclass, pymodule,
};
pub fn main() {
@@ -67,12 +67,12 @@ python_person.name: {}",
#[pyclass]
impl RustStruct {
#[pygetset]
fn numbers(&self) -> NumVec {
self.numbers.clone()
fn numbers(zelf: &Py<Self>) -> NumVec {
zelf.numbers.clone()
}
#[pymethod]
fn print_in_rust_from_python(&self) {
fn print_in_rust_from_python(_zelf: &Py<Self>) {
println!("Calling a rust method from python");
}
}