Skip to content

Commit 2344c90

Browse files
committed
limit 'py: 'a on Borrowed
1 parent 0ae71bf commit 2344c90

File tree

6 files changed

+31
-16
lines changed

6 files changed

+31
-16
lines changed

pyo3-macros-backend/src/method.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,9 @@ impl FnType {
125125
FnType::FnClass(span) | FnType::FnNewClass(span) => {
126126
let py = syn::Ident::new("py", Span::call_site());
127127
let slf: Ident = syn::Ident::new("_slf", Span::call_site());
128-
let allow_deprecated = if cfg!(feature = "gil-refs") {
129-
quote!()
130-
} else {
131-
quote!(#[allow(deprecated)])
132-
};
133128
quote_spanned! { *span =>
134129
#[allow(clippy::useless_conversion)]
135-
#allow_deprecated
136-
::std::convert::Into::into(_pyo3::types::PyType::from_type_ptr(#py, #slf.cast())),
130+
::std::convert::Into::into(_pyo3::types::PyType::from_type_ptr_borrowed(#py, #slf.cast())),
137131
}
138132
}
139133
FnType::FnModule(span) => {

src/instance.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ unsafe impl<T> AsPyPointer for Bound<'_, T> {
256256
///
257257
/// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`).
258258
#[repr(transparent)]
259-
pub struct Borrowed<'a, 'py, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py<T>>, Python<'py>);
259+
pub struct Borrowed<'a, 'py, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py<T>>, Python<'py>)
260+
where
261+
'py: 'a;
260262

261263
impl<'py, T> Borrowed<'_, 'py, T> {
262264
/// Creates a new owned `Bound` from this borrowed reference by increasing the reference count.
@@ -1318,6 +1320,21 @@ where
13181320
}
13191321
}
13201322

1323+
impl<'py, T> std::convert::From<Borrowed<'py, 'py, T>> for &'py T::AsRefTarget
1324+
where
1325+
T: HasPyGilRef,
1326+
{
1327+
fn from(borrowed: Borrowed<'py, 'py, T>) -> Self {
1328+
borrowed.into_gil_ref()
1329+
}
1330+
}
1331+
1332+
impl<'py, T> std::convert::From<Borrowed<'py, 'py, T>> for Py<T> {
1333+
fn from(borrowed: Borrowed<'py, 'py, T>) -> Self {
1334+
borrowed.to_owned().unbind()
1335+
}
1336+
}
1337+
13211338
impl<T> std::convert::From<Py<T>> for PyObject
13221339
where
13231340
T: AsRef<PyAny>,

src/types/bytes.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ impl Py<PyBytes> {
129129
/// immutable, the result may be used for as long as the reference to
130130
/// `self` is held, including when the GIL is released.
131131
pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {
132-
self.bind_borrowed(py).as_bytes()
132+
// Safety: lifetime of the borrow can extend beyond py.
133+
unsafe { std::mem::transmute(self.bind_borrowed(py).as_bytes()) }
133134
}
134135
}
135136

src/types/string.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ impl Py<PyString> {
407407
/// the GIL lifetime.
408408
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
409409
pub fn to_str<'a>(&'a self, py: Python<'_>) -> PyResult<&'a str> {
410-
self.bind_borrowed(py).to_str()
410+
// Safety: lifetime of the borrow can extend beyond py.
411+
unsafe { std::mem::transmute(self.bind_borrowed(py).to_str()) }
411412
}
412413

413414
/// Converts the `PyString` into a Rust string, avoiding copying when possible.
@@ -418,7 +419,8 @@ impl Py<PyString> {
418419
/// Because `str` objects are immutable, the returned slice is independent of
419420
/// the GIL lifetime.
420421
pub fn to_cow<'a>(&'a self, py: Python<'_>) -> PyResult<Cow<'a, str>> {
421-
self.bind_borrowed(py).to_cow()
422+
// Safety: lifetime of the borrow can extend beyond py.
423+
unsafe { std::mem::transmute(self.bind_borrowed(py).to_cow()) }
422424
}
423425

424426
/// Converts the `PyString` into a Rust string.
@@ -429,7 +431,8 @@ impl Py<PyString> {
429431
/// Because `str` objects are immutable, the returned slice is independent of
430432
/// the GIL lifetime.
431433
pub fn to_string_lossy<'a>(&'a self, py: Python<'_>) -> Cow<'a, str> {
432-
self.bind_borrowed(py).to_string_lossy()
434+
// Safety: lifetime of the borrow can extend beyond py.
435+
unsafe { std::mem::transmute(self.bind_borrowed(py).to_string_lossy()) }
433436
}
434437
}
435438

tests/ui/invalid_pymethods.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ error: macros cannot be used as items in `#[pymethods]` impl blocks
179179
197 | macro_invocation!();
180180
| ^^^^^^^^^^^^^^^^
181181

182-
error[E0277]: the trait bound `i32: From<&PyType>` is not satisfied
182+
error[E0277]: the trait bound `i32: From<pyo3::Borrowed<'_, '_, PyType>>` is not satisfied
183183
--> tests/ui/invalid_pymethods.rs:46:45
184184
|
185185
46 | fn classmethod_wrong_first_argument(_x: i32) -> Self {
186-
| ^^^ the trait `From<&PyType>` is not implemented for `i32`
186+
| ^^^ the trait `From<pyo3::Borrowed<'_, '_, PyType>>` is not implemented for `i32`
187187
|
188188
= help: the following other types implement trait `From<T>`:
189189
<i32 as From<bool>>
@@ -192,4 +192,4 @@ error[E0277]: the trait bound `i32: From<&PyType>` is not satisfied
192192
<i32 as From<u8>>
193193
<i32 as From<u16>>
194194
<i32 as From<NonZeroI32>>
195-
= note: required for `&PyType` to implement `Into<i32>`
195+
= note: required for `pyo3::Borrowed<'_, '_, PyType>` to implement `Into<i32>`

tests/ui/invalid_result_conversion.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ error[E0277]: the trait bound `PyErr: From<MyError>` is not satisfied
55
| ^^^^^^^^^^^^^ the trait `From<MyError>` is not implemented for `PyErr`
66
|
77
= help: the following other types implement trait `From<T>`:
8-
<PyErr as From<PyBorrowError>>
98
<PyErr as From<std::io::Error>>
9+
<PyErr as From<PyBorrowError>>
1010
<PyErr as From<PyBorrowMutError>>
1111
<PyErr as From<PyDowncastError<'a>>>
1212
<PyErr as From<DowncastError<'_, '_>>>

0 commit comments

Comments
 (0)