Create a better error message for moving self (#2238)

This commit is contained in:
Bruno Kolenbrander 2022-03-24 10:27:37 +01:00 committed by GitHub
parent 16ee22c7cc
commit 43944aef76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 7 deletions

View file

@ -157,14 +157,14 @@ impl SelfType {
quote! { quote! {
let _cell = #cell; let _cell = #cell;
let _ref = _cell.try_borrow()?; let _ref = _cell.try_borrow()?;
let _slf = &_ref; let _slf: &#cls = &*_ref;
} }
} }
SelfType::Receiver { mutable: true } => { SelfType::Receiver { mutable: true } => {
quote! { quote! {
let _cell = #cell; let _cell = #cell;
let mut _ref = _cell.try_borrow_mut()?; let mut _ref = _cell.try_borrow_mut()?;
let _slf = &mut _ref; let _slf: &mut #cls = &mut *_ref;
} }
} }
SelfType::TryFromPyCell(span) => { 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<SelfType> { pub fn parse_method_receiver(arg: &syn::FnArg) -> Result<SelfType> {
match arg { match arg {
syn::FnArg::Receiver(recv) => Ok(SelfType::Receiver { syn::FnArg::Receiver(
mutable: recv.mutability.is_some(), 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, .. }) => { syn::FnArg::Typed(syn::PatType { ty, .. }) => {
if let syn::Type::ImplTrait(_) = &**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 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>`.";

View file

@ -119,6 +119,11 @@ impl MyClass {
fn default_arg_before_required(&self, has_default: isize, required: isize) {} fn default_arg_before_required(&self, has_default: isize, required: isize) {}
} }
#[pymethods]
impl MyClass {
fn method_self_by_value(self){}
}
struct TwoNew { } struct TwoNew { }
#[pymethods] #[pymethods]

View file

@ -102,10 +102,17 @@ error: `pass_module` cannot be used on Python methods
112 | #[pyo3(pass_module)] 112 | #[pyo3(pass_module)]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error[E0592]: duplicate definitions with name `__pymethod__new__` error: Python objects are shared, so 'self' cannot be moved out of the Python interpreter.
--> tests/ui/invalid_pymethods.rs:124:1 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__` | duplicate definitions for `__pymethod__new__`