diff --git a/newsfragments/5831.added.md b/newsfragments/5831.added.md new file mode 100644 index 00000000000..c4dfef50883 --- /dev/null +++ b/newsfragments/5831.added.md @@ -0,0 +1 @@ +Add `Borrowed::as_unbound` diff --git a/newsfragments/5831.changed.md b/newsfragments/5831.changed.md new file mode 100644 index 00000000000..bcb0391d27f --- /dev/null +++ b/newsfragments/5831.changed.md @@ -0,0 +1 @@ +Make `IntoPyObject` for `Bound` & `Borrowed` more generic diff --git a/src/conversion.rs b/src/conversion.rs index ef349ea97b6..c000cf2e664 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -127,7 +127,7 @@ pub(crate) mod private { } } -impl<'py, T: PyTypeCheck> IntoPyObject<'py> for Bound<'py, T> { +impl<'py, T: PyTypeCheck> IntoPyObject<'py> for Bound<'_, T> { type Target = T; type Output = Bound<'py, Self::Target>; type Error = Infallible; @@ -135,12 +135,12 @@ impl<'py, T: PyTypeCheck> IntoPyObject<'py> for Bound<'py, T> { #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT; - fn into_pyobject(self, _py: Python<'py>) -> Result { - Ok(self) + fn into_pyobject(self, py: Python<'py>) -> Result { + Ok(self.unbind().into_bound(py)) } } -impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &'a Bound<'py, T> { +impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &'a Bound<'_, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; @@ -148,12 +148,12 @@ impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &'a Bound<'py, T> { #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT; - fn into_pyobject(self, _py: Python<'py>) -> Result { - Ok(self.as_borrowed()) + fn into_pyobject(self, py: Python<'py>) -> Result { + Ok(self.as_unbound().bind_borrowed(py)) } } -impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for Borrowed<'a, 'py, T> { +impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for Borrowed<'a, '_, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; @@ -161,12 +161,12 @@ impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for Borrowed<'a, 'py, T> { #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT; - fn into_pyobject(self, _py: Python<'py>) -> Result { - Ok(self) + fn into_pyobject(self, py: Python<'py>) -> Result { + Ok(self.as_unbound().bind_borrowed(py)) } } -impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &Borrowed<'a, 'py, T> { +impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &Borrowed<'a, '_, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; @@ -174,8 +174,8 @@ impl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &Borrowed<'a, 'py, T> { #[cfg(feature = "experimental-inspect")] const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT; - fn into_pyobject(self, _py: Python<'py>) -> Result { - Ok(*self) + fn into_pyobject(self, py: Python<'py>) -> Result { + Ok(self.as_unbound().bind_borrowed(py)) } } diff --git a/src/instance.rs b/src/instance.rs index ce96b4aa4ce..3bd49394739 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1075,6 +1075,14 @@ impl<'a, 'py, T> Borrowed<'a, 'py, T> { pub unsafe fn cast_unchecked(self) -> Borrowed<'a, 'py, U> { Borrowed(self.0, PhantomData, self.2) } + + /// Removes the connection for this `Borrowed` from the [`Python<'py>`] token, + /// allowing it to cross thread boundaries, without transferring ownership. + #[inline] + pub fn as_unbound(&self) -> &'a Py { + // Safety: NonNull is layout-compatible with Py + unsafe { NonNull::from(&self.0).cast().as_ref() } + } } impl<'a, T: PyClass> Borrowed<'a, '_, T> {