diff --git a/pyo3-macros-backend/src/pymethod.rs b/pyo3-macros-backend/src/pymethod.rs index c077073c..b745cb4b 100644 --- a/pyo3-macros-backend/src/pymethod.rs +++ b/pyo3-macros-backend/src/pymethod.rs @@ -625,7 +625,7 @@ pub fn impl_py_getter_def( let python_name = property_type.null_terminated_python_name()?; let doc = property_type.doc(); - let getter_impl = match property_type { + let body = match property_type { PropertyType::Descriptor { field_index, field, .. } => { @@ -634,31 +634,28 @@ pub fn impl_py_getter_def( span: Span::call_site(), } .receiver(cls, ExtractErrorMode::Raise); - if let Some(ident) = &field.ident { + let field_token = if let Some(ident) = &field.ident { // named struct field - quote!(::std::clone::Clone::clone(&(#slf.#ident))) + ident.to_token_stream() } else { // tuple struct field - let index = syn::Index::from(field_index); - quote!(::std::clone::Clone::clone(&(#slf.#index))) - } - } - PropertyType::Function { - spec, self_type, .. - } => impl_call_getter(cls, spec, self_type)?, - }; - - let conversion = match property_type { - PropertyType::Descriptor { .. } => { + syn::Index::from(field_index).to_token_stream() + }; quote! { - let item: _pyo3::Py<_pyo3::PyAny> = _pyo3::IntoPy::into_py(item, _py); - ::std::result::Result::Ok(_pyo3::conversion::IntoPyPointer::into_ptr(item)) + ::std::result::Result::Ok( + _pyo3::conversion::IntoPyPointer::into_ptr( + _pyo3::IntoPy::<_pyo3::Py<_pyo3::PyAny>>::into_py(::std::clone::Clone::clone(&(#slf.#field_token)), _py) + ) + ) } } // Forward to `IntoPyCallbackOutput`, to handle `#[getter]`s returning results. - PropertyType::Function { .. } => { + PropertyType::Function { + spec, self_type, .. + } => { + let call = impl_call_getter(cls, spec, self_type)?; quote! { - _pyo3::callback::convert(_py, item) + _pyo3::callback::convert(_py, #call) } } }; @@ -697,8 +694,7 @@ pub fn impl_py_getter_def( _py: _pyo3::Python<'_>, _slf: *mut _pyo3::ffi::PyObject ) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> { - let item = #getter_impl; - #conversion + #body } }; diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index c542aa0c..e0be6977 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -216,3 +216,23 @@ fn cell_getter_setter() { ); }); } + +#[test] +fn borrowed_value_with_lifetime_of_self() { + #[pyclass] + struct BorrowedValue {} + + #[pymethods] + impl BorrowedValue { + #[getter] + fn value(&self) -> &str { + "value" + } + } + + Python::with_gil(|py| { + let inst = Py::new(py, BorrowedValue {}).unwrap().to_object(py); + + py_run!(py, inst, "assert inst.value == 'value'"); + }); +}