From ee1272ed7646b33afb54d92c10249b633d1738ed Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Wed, 20 Dec 2023 15:42:43 +0000 Subject: [PATCH] implement `Copy` for `Py2Borrowed` --- src/instance.rs | 10 ++++++++++ src/types/dict.rs | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/instance.rs b/src/instance.rs index 8b749016..e8ff4a2f 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -221,6 +221,8 @@ unsafe impl AsPyPointer for Py2<'_, T> { /// /// The advantage of this over `&Py2` is that it avoids the need to have a pointer-to-pointer, as Py2 /// is already a pointer to an `ffi::PyObject``. +/// +/// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`). #[repr(transparent)] pub(crate) struct Py2Borrowed<'a, 'py, T>( NonNull, @@ -326,6 +328,14 @@ impl<'py, T> Deref for Py2Borrowed<'_, 'py, T> { } } +impl Clone for Py2Borrowed<'_, '_, T> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for Py2Borrowed<'_, '_, T> {} + /// A GIL-independent reference to an object allocated on the Python heap. /// /// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it. diff --git a/src/types/dict.rs b/src/types/dict.rs index c03a03ec..858fb187 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -2,7 +2,7 @@ use super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; use crate::ffi_ptr_ext::FfiPtrExt; -use crate::instance::Py2; +use crate::instance::{Py2, Py2Borrowed}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyList}; @@ -406,7 +406,7 @@ impl<'py> PyDictMethods<'py> for Py2<'py, PyDict> { match unsafe { ffi::PyDict_GetItemWithError(dict.as_ptr(), key.as_ptr()) .assume_borrowed_or_opt(py) - .map(|borrowed_any| borrowed_any.clone()) + .map(Py2Borrowed::to_owned) } { some @ Some(_) => Ok(some), None => PyErr::take(py).map(Err).transpose(), @@ -595,8 +595,8 @@ impl<'py> Iterator for PyDictIterator2<'py> { // - PyDict_Next returns borrowed values // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null Some(( - unsafe { key.assume_borrowed_unchecked(py) }.clone(), - unsafe { value.assume_borrowed_unchecked(py) }.clone(), + unsafe { key.assume_borrowed_unchecked(py) }.to_owned(), + unsafe { value.assume_borrowed_unchecked(py) }.to_owned(), )) } else { None