3055: Fix compile error when trying to use static slot methods, fixes: #3039 r=davidhewitt a=willstott101

Whilst having static slot methods is of dubious value in the first place, there's little reason not to support it by bringing the different function call macros more in-line with each other.

I had no idea which test file to use so I just made a new one... `test_methods.rs` has no slots in and the test files that do use slots seem to be specific to their protocol. Let me know if you'd like the test somewhere else.

Thanks!

Co-authored-by: Will Stott <willstott101@gmail.com>
This commit is contained in:
bors[bot] 2023-03-23 07:23:38 +00:00 committed by GitHub
commit 28814f2978
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 1 deletions

View File

@ -0,0 +1 @@
compile error in generated code for a `#[staticmethod]` occupying a slot

View File

@ -1195,9 +1195,10 @@ fn generate_method_body(
return_mode: Option<&ReturnMode>, return_mode: Option<&ReturnMode>,
) -> Result<TokenStream> { ) -> Result<TokenStream> {
let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode); let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode);
let self_arg = spec.tp.self_arg();
let rust_name = spec.name; let rust_name = spec.name;
let args = extract_proto_arguments(py, spec, arguments, extract_error_mode)?; let args = extract_proto_arguments(py, spec, arguments, extract_error_mode)?;
let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(_slf, #(#args),*)) }; let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(#self_arg #(#args),*)) };
let body = if let Some(return_mode) = return_mode { let body = if let Some(return_mode) = return_mode {
return_mode.return_call_output(py, call) return_mode.return_call_output(py, call)
} else { } else {

View File

@ -0,0 +1,71 @@
#![cfg(feature = "macros")]
use pyo3::exceptions::PyIndexError;
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use pyo3::py_run;
mod common;
#[pyclass]
struct Count5();
#[pymethods]
impl Count5 {
#[new]
fn new() -> Self {
Self()
}
#[staticmethod]
fn __len__() -> usize {
5
}
#[staticmethod]
fn __getitem__(idx: isize) -> PyResult<f64> {
if idx < 0 {
Err(PyIndexError::new_err("Count5 cannot count backwards"))
} else if idx > 4 {
Err(PyIndexError::new_err("Count5 cannot count higher than 5"))
} else {
Ok(idx as f64 + 1.0)
}
}
}
/// Return a dict with `s = Count5()`.
fn test_dict(py: Python<'_>) -> &pyo3::types::PyDict {
let d = [("Count5", py.get_type::<Count5>())].into_py_dict(py);
// Though we can construct `s` in Rust, let's test `__new__` works.
py_run!(py, *d, "s = Count5()");
d
}
#[test]
fn test_len() {
Python::with_gil(|py| {
let d = test_dict(py);
py_assert!(py, *d, "len(s) == 5");
});
}
#[test]
fn test_getitem() {
Python::with_gil(|py| {
let d = test_dict(py);
py_assert!(py, *d, "s[4] == 5.0");
});
}
#[test]
fn test_list() {
Python::with_gil(|py| {
let d = test_dict(py);
py_assert!(py, *d, "list(s) == [1.0, 2.0, 3.0, 4.0, 5.0]");
});
}