diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index 02024011366..616e6b9b750 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -1287,8 +1287,17 @@ fn impl_pytypeinfo( <#cls as _pyo3::impl_::pyclass::PyClassImpl>::lazy_type_object() .get_or_init(py) + .as_gil_ref() .as_type_ptr() } + + #[inline] + fn try_type_object_bound(py: _pyo3::Python<'_>) -> _pyo3::PyResult<_pyo3::Bound<'_, _pyo3::types::PyType>> { + #deprecations + + <#cls as _pyo3::impl_::pyclass::PyClassImpl>::lazy_type_object() + .get_or_try_init(py) + } } } } diff --git a/src/impl_/pyclass/lazy_type_object.rs b/src/impl_/pyclass/lazy_type_object.rs index af52033a702..dcbc127ed06 100644 --- a/src/impl_/pyclass/lazy_type_object.rs +++ b/src/impl_/pyclass/lazy_type_object.rs @@ -12,7 +12,7 @@ use crate::{ pyclass::{create_type_object, PyClassTypeObject}, sync::{GILOnceCell, GILProtected}, types::PyType, - PyClass, PyErr, PyMethodDefType, PyObject, PyResult, Python, + Bound, PyClass, PyErr, PyMethodDefType, PyObject, PyResult, Python, }; use super::PyClassItemsIter; @@ -46,7 +46,7 @@ impl LazyTypeObject { impl LazyTypeObject { /// Gets the type object contained by this `LazyTypeObject`, initializing it if needed. - pub fn get_or_init<'py>(&'py self, py: Python<'py>) -> &'py PyType { + pub fn get_or_init<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.get_or_try_init(py).unwrap_or_else(|err| { err.print(py); panic!("failed to create type object for {}", T::NAME) @@ -54,7 +54,7 @@ impl LazyTypeObject { } /// Fallible version of the above. - pub(crate) fn get_or_try_init<'py>(&'py self, py: Python<'py>) -> PyResult<&'py PyType> { + pub fn get_or_try_init<'py>(&self, py: Python<'py>) -> PyResult> { self.0 .get_or_try_init(py, create_type_object::, T::NAME, T::items_iter()) } @@ -65,19 +65,20 @@ impl LazyTypeObjectInner { // so that this code is only instantiated once, instead of for every T // like the generic LazyTypeObject methods above. fn get_or_try_init<'py>( - &'py self, + &self, py: Python<'py>, init: fn(Python<'py>) -> PyResult, name: &str, items_iter: PyClassItemsIter, - ) -> PyResult<&'py PyType> { + ) -> PyResult> { (|| -> PyResult<_> { let type_object = self .value .get_or_try_init(py, || init(py))? .type_object - .as_ref(py); - self.ensure_init(type_object, name, items_iter)?; + .clone() + .into_bound(py); + self.ensure_init(&type_object, name, items_iter)?; Ok(type_object) })() .map_err(|err| { @@ -91,7 +92,7 @@ impl LazyTypeObjectInner { fn ensure_init( &self, - type_object: &PyType, + type_object: &Bound<'_, PyType>, name: &str, items_iter: PyClassItemsIter, ) -> PyResult<()> { diff --git a/src/impl_/pymodule.rs b/src/impl_/pymodule.rs index 7b9df8d0fb3..c7fb0d09866 100644 --- a/src/impl_/pymodule.rs +++ b/src/impl_/pymodule.rs @@ -143,7 +143,7 @@ pub trait PyAddToModule { impl PyAddToModule for T { fn add_to_module(module: &Bound<'_, PyModule>) -> PyResult<()> { - module.add(Self::NAME, Self::type_object_bound(module.py())) + module.add(Self::NAME, Self::try_type_object_bound(module.py())?) } } diff --git a/src/type_object.rs b/src/type_object.rs index 994781b3fc0..ddefbd01178 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -3,7 +3,7 @@ use crate::ffi_ptr_ext::FfiPtrExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyType}; -use crate::{ffi, Bound, PyNativeType, Python}; +use crate::{ffi, Bound, PyNativeType, PyResult, Python}; /// `T: PyLayout` represents that `T` is a concrete representation of `U` in the Python heap. /// E.g., `PyCell` is a concrete representation of all `pyclass`es, and `ffi::PyObject` @@ -96,6 +96,12 @@ pub unsafe trait PyTypeInfo: Sized + HasPyGilRef { } } + /// Returns the safe abstraction over the type object or an error if initialization fails + #[inline] + fn try_type_object_bound(py: Python<'_>) -> PyResult> { + Ok(Self::type_object_bound(py)) + } + /// Checks if `object` is an instance of this type or a subclass of this type. #[inline] #[cfg_attr( diff --git a/src/types/module.rs b/src/types/module.rs index 8824dfcf030..dc80fb0027b 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -633,7 +633,7 @@ impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> { T: PyClass, { let py = self.py(); - self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?) + self.add(T::NAME, T::try_type_object_bound(py)?) } fn add_wrapped(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>