fix compile failure for getter with return lifetime of self

This commit is contained in:
David Hewitt 2023-07-28 15:59:01 +01:00
parent eb885969fd
commit c1126740c5
2 changed files with 36 additions and 20 deletions

View File

@ -625,7 +625,7 @@ pub fn impl_py_getter_def(
let python_name = property_type.null_terminated_python_name()?; let python_name = property_type.null_terminated_python_name()?;
let doc = property_type.doc(); let doc = property_type.doc();
let getter_impl = match property_type { let body = match property_type {
PropertyType::Descriptor { PropertyType::Descriptor {
field_index, field, .. field_index, field, ..
} => { } => {
@ -634,31 +634,28 @@ pub fn impl_py_getter_def(
span: Span::call_site(), span: Span::call_site(),
} }
.receiver(cls, ExtractErrorMode::Raise); .receiver(cls, ExtractErrorMode::Raise);
if let Some(ident) = &field.ident { let field_token = if let Some(ident) = &field.ident {
// named struct field // named struct field
quote!(::std::clone::Clone::clone(&(#slf.#ident))) ident.to_token_stream()
} else { } else {
// tuple struct field // tuple struct field
let index = syn::Index::from(field_index); syn::Index::from(field_index).to_token_stream()
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 { .. } => {
quote! { quote! {
let item: _pyo3::Py<_pyo3::PyAny> = _pyo3::IntoPy::into_py(item, _py); ::std::result::Result::Ok(
::std::result::Result::Ok(_pyo3::conversion::IntoPyPointer::into_ptr(item)) _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. // 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! { quote! {
_pyo3::callback::convert(_py, item) _pyo3::callback::convert(_py, #call)
} }
} }
}; };
@ -697,8 +694,7 @@ pub fn impl_py_getter_def(
_py: _pyo3::Python<'_>, _py: _pyo3::Python<'_>,
_slf: *mut _pyo3::ffi::PyObject _slf: *mut _pyo3::ffi::PyObject
) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> { ) -> _pyo3::PyResult<*mut _pyo3::ffi::PyObject> {
let item = #getter_impl; #body
#conversion
} }
}; };

View File

@ -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'");
});
}