allow `Bound<'_, T>` in #[pymethods] `self` position (#3896)
* allow `Bound<'_, T>` in #[pymethods] `self` position * rename `TryFromPyCell` -> `TryFromBoundRef` * remove unneccessary unsafe
This commit is contained in:
parent
8f1b99e1e9
commit
7c10ff4327
|
@ -151,7 +151,7 @@ impl FnType {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SelfType {
|
pub enum SelfType {
|
||||||
Receiver { mutable: bool, span: Span },
|
Receiver { mutable: bool, span: Span },
|
||||||
TryFromPyCell(Span),
|
TryFromBoundRef(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -204,15 +204,14 @@ impl SelfType {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
SelfType::TryFromPyCell(span) => {
|
SelfType::TryFromBoundRef(span) => {
|
||||||
error_mode.handle_error(
|
error_mode.handle_error(
|
||||||
quote_spanned! { *span =>
|
quote_spanned! { *span =>
|
||||||
#py.from_borrowed_ptr::<_pyo3::PyAny>(#slf).downcast::<_pyo3::PyCell<#cls>>()
|
_pyo3::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).downcast::<#cls>()
|
||||||
.map_err(::std::convert::Into::<_pyo3::PyErr>::into)
|
.map_err(::std::convert::Into::<_pyo3::PyErr>::into)
|
||||||
.and_then(
|
.and_then(
|
||||||
#[allow(clippy::useless_conversion)] // In case slf is PyCell<Self>
|
|
||||||
#[allow(unknown_lints, clippy::unnecessary_fallible_conversions)] // In case slf is Py<Self> (unknown_lints can be removed when MSRV is 1.75+)
|
#[allow(unknown_lints, clippy::unnecessary_fallible_conversions)] // In case slf is Py<Self> (unknown_lints can be removed when MSRV is 1.75+)
|
||||||
|cell| ::std::convert::TryFrom::try_from(cell).map_err(::std::convert::Into::into)
|
|bound| ::std::convert::TryFrom::try_from(bound).map_err(::std::convert::Into::into)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -291,7 +290,7 @@ pub fn parse_method_receiver(arg: &syn::FnArg) -> Result<SelfType> {
|
||||||
if let syn::Type::ImplTrait(_) = &**ty {
|
if let syn::Type::ImplTrait(_) = &**ty {
|
||||||
bail_spanned!(ty.span() => IMPL_TRAIT_ERR);
|
bail_spanned!(ty.span() => IMPL_TRAIT_ERR);
|
||||||
}
|
}
|
||||||
Ok(SelfType::TryFromPyCell(ty.span()))
|
Ok(SelfType::TryFromBoundRef(ty.span()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1188,7 +1188,7 @@ fn complex_enum_variant_field_getter<'a>(
|
||||||
) -> Result<MethodAndMethodDef> {
|
) -> Result<MethodAndMethodDef> {
|
||||||
let signature = crate::pyfunction::FunctionSignature::from_arguments(vec![])?;
|
let signature = crate::pyfunction::FunctionSignature::from_arguments(vec![])?;
|
||||||
|
|
||||||
let self_type = crate::method::SelfType::TryFromPyCell(field_span);
|
let self_type = crate::method::SelfType::TryFromBoundRef(field_span);
|
||||||
|
|
||||||
let spec = FnSpec {
|
let spec = FnSpec {
|
||||||
tp: crate::method::FnType::Getter(self_type.clone()),
|
tp: crate::method::FnType::Getter(self_type.clone()),
|
||||||
|
|
|
@ -3,10 +3,12 @@ use crate::exceptions::PyStopAsyncIteration;
|
||||||
use crate::gil::LockGIL;
|
use crate::gil::LockGIL;
|
||||||
use crate::impl_::panic::PanicTrap;
|
use crate::impl_::panic::PanicTrap;
|
||||||
use crate::internal_tricks::extract_c_string;
|
use crate::internal_tricks::extract_c_string;
|
||||||
|
use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
||||||
|
use crate::pyclass::boolean_struct::False;
|
||||||
use crate::types::{any::PyAnyMethods, PyModule, PyType};
|
use crate::types::{any::PyAnyMethods, PyModule, PyType};
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi, Bound, Py, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult, PyTraverseError, PyVisit,
|
ffi, Bound, DowncastError, Py, PyAny, PyCell, PyClass, PyErr, PyObject, PyRef, PyRefMut,
|
||||||
Python,
|
PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -490,6 +492,10 @@ impl<'a, 'py> BoundRef<'a, 'py, PyAny> {
|
||||||
Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef)
|
Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn downcast<T: PyTypeCheck>(self) -> Result<BoundRef<'a, 'py, T>, DowncastError<'a, 'py>> {
|
||||||
|
self.0.downcast::<T>().map(BoundRef)
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn downcast_unchecked<T>(self) -> BoundRef<'a, 'py, T> {
|
pub unsafe fn downcast_unchecked<T>(self) -> BoundRef<'a, 'py, T> {
|
||||||
BoundRef(self.0.downcast_unchecked::<T>())
|
BoundRef(self.0.downcast_unchecked::<T>())
|
||||||
}
|
}
|
||||||
|
@ -511,6 +517,36 @@ impl<'a> From<BoundRef<'a, 'a, PyModule>> for &'a PyModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'py, T: PyClass> From<BoundRef<'a, 'py, T>> for &'a PyCell<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
|
||||||
|
bound.0.as_gil_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'py, T: PyClass> TryFrom<BoundRef<'a, 'py, T>> for PyRef<'py, T> {
|
||||||
|
type Error = PyBorrowError;
|
||||||
|
#[inline]
|
||||||
|
fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {
|
||||||
|
value.0.clone().into_gil_ref().try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<BoundRef<'a, 'py, T>> for PyRefMut<'py, T> {
|
||||||
|
type Error = PyBorrowMutError;
|
||||||
|
#[inline]
|
||||||
|
fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {
|
||||||
|
value.0.clone().into_gil_ref().try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'py, T> From<BoundRef<'a, 'py, T>> for Bound<'py, T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
|
||||||
|
bound.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'py, T> From<BoundRef<'a, 'py, T>> for &'a Bound<'py, T> {
|
impl<'a, 'py, T> From<BoundRef<'a, 'py, T>> for &'a Bound<'py, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
|
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
|
||||||
|
|
|
@ -654,7 +654,7 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
|
||||||
/// }
|
/// }
|
||||||
/// # Python::with_gil(|py| {
|
/// # Python::with_gil(|py| {
|
||||||
/// # let sub = Py::new(py, Child::new()).unwrap();
|
/// # let sub = Py::new(py, Child::new()).unwrap();
|
||||||
/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 3)'");
|
/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 4)'");
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0277]: the trait bound `i32: From<&PyCell<MyClass>>` is not satisfied
|
error[E0277]: the trait bound `i32: From<BoundRef<'_, '_, MyClass>>` is not satisfied
|
||||||
--> tests/ui/invalid_pymethod_receiver.rs:8:43
|
--> tests/ui/invalid_pymethod_receiver.rs:8:43
|
||||||
|
|
|
|
||||||
8 | fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
|
8 | fn method_with_invalid_self_type(slf: i32, py: Python<'_>, index: u32) {}
|
||||||
| ^^^ the trait `From<&PyCell<MyClass>>` is not implemented for `i32`
|
| ^^^ the trait `From<BoundRef<'_, '_, MyClass>>` is not implemented for `i32`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `From<T>`:
|
= help: the following other types implement trait `From<T>`:
|
||||||
<i32 as From<bool>>
|
<i32 as From<bool>>
|
||||||
|
@ -11,5 +11,5 @@ error[E0277]: the trait bound `i32: From<&PyCell<MyClass>>` is not satisfied
|
||||||
<i32 as From<u8>>
|
<i32 as From<u8>>
|
||||||
<i32 as From<u16>>
|
<i32 as From<u16>>
|
||||||
<i32 as From<NonZeroI32>>
|
<i32 as From<NonZeroI32>>
|
||||||
= note: required for `&PyCell<MyClass>` to implement `Into<i32>`
|
= note: required for `BoundRef<'_, '_, MyClass>` to implement `Into<i32>`
|
||||||
= note: required for `i32` to implement `TryFrom<&PyCell<MyClass>>`
|
= note: required for `i32` to implement `TryFrom<BoundRef<'_, '_, MyClass>>`
|
||||||
|
|
Loading…
Reference in New Issue