diff --git a/pyo3-macros-backend/src/method.rs b/pyo3-macros-backend/src/method.rs index f8501c58..ddf2244f 100644 --- a/pyo3-macros-backend/src/method.rs +++ b/pyo3-macros-backend/src/method.rs @@ -157,14 +157,14 @@ impl SelfType { quote! { let _cell = #cell; let _ref = _cell.try_borrow()?; - let _slf = &_ref; + let _slf: &#cls = &*_ref; } } SelfType::Receiver { mutable: true } => { quote! { let _cell = #cell; let mut _ref = _cell.try_borrow_mut()?; - let _slf = &mut _ref; + let _slf: &mut #cls = &mut *_ref; } } SelfType::TryFromPyCell(span) => { @@ -235,8 +235,15 @@ pub fn get_return_info(output: &syn::ReturnType) -> syn::Type { pub fn parse_method_receiver(arg: &syn::FnArg) -> Result { match arg { - syn::FnArg::Receiver(recv) => Ok(SelfType::Receiver { - mutable: recv.mutability.is_some(), + syn::FnArg::Receiver( + recv @ syn::Receiver { + reference: None, .. + }, + ) => { + bail_spanned!(recv.span() => RECEIVER_BY_VALUE_ERR); + } + syn::FnArg::Receiver(syn::Receiver { mutability, .. }) => Ok(SelfType::Receiver { + mutable: mutability.is_some(), }), syn::FnArg::Typed(syn::PatType { ty, .. }) => { if let syn::Type::ImplTrait(_) = &**ty { @@ -729,3 +736,6 @@ fn parse_method_attributes( } const IMPL_TRAIT_ERR: &str = "Python functions cannot have `impl Trait` arguments"; +const RECEIVER_BY_VALUE_ERR: &str = + "Python objects are shared, so 'self' cannot be moved out of the Python interpreter. +Try `&self`, `&mut self, `slf: PyRef<'_, Self>` or `slf: PyRefMut<'_, Self>`."; diff --git a/tests/ui/invalid_pymethods.rs b/tests/ui/invalid_pymethods.rs index 4fc63dc7..cad832b1 100644 --- a/tests/ui/invalid_pymethods.rs +++ b/tests/ui/invalid_pymethods.rs @@ -119,6 +119,11 @@ impl MyClass { fn default_arg_before_required(&self, has_default: isize, required: isize) {} } +#[pymethods] +impl MyClass { + fn method_self_by_value(self){} +} + struct TwoNew { } #[pymethods] diff --git a/tests/ui/invalid_pymethods.stderr b/tests/ui/invalid_pymethods.stderr index 2a851154..06306bca 100644 --- a/tests/ui/invalid_pymethods.stderr +++ b/tests/ui/invalid_pymethods.stderr @@ -102,10 +102,17 @@ error: `pass_module` cannot be used on Python methods 112 | #[pyo3(pass_module)] | ^^^^^^^^^^^ -error[E0592]: duplicate definitions with name `__pymethod__new__` - --> tests/ui/invalid_pymethods.rs:124:1 +error: Python objects are shared, so 'self' cannot be moved out of the Python interpreter. + Try `&self`, `&mut self, `slf: PyRef<'_, Self>` or `slf: PyRefMut<'_, Self>`. + --> tests/ui/invalid_pymethods.rs:124:29 | -124 | #[pymethods] +124 | fn method_self_by_value(self){} + | ^^^^ + +error[E0592]: duplicate definitions with name `__pymethod__new__` + --> tests/ui/invalid_pymethods.rs:129:1 + | +129 | #[pymethods] | ^^^^^^^^^^^^ | | | duplicate definitions for `__pymethod__new__`