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)]
|
||||
pub enum SelfType {
|
||||
Receiver { mutable: bool, span: Span },
|
||||
TryFromPyCell(Span),
|
||||
TryFromBoundRef(Span),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -204,15 +204,14 @@ impl SelfType {
|
|||
)
|
||||
})
|
||||
}
|
||||
SelfType::TryFromPyCell(span) => {
|
||||
SelfType::TryFromBoundRef(span) => {
|
||||
error_mode.handle_error(
|
||||
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)
|
||||
.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+)
|
||||
|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 {
|
||||
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> {
|
||||
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 {
|
||||
tp: crate::method::FnType::Getter(self_type.clone()),
|
||||
|
|
|
@ -3,10 +3,12 @@ use crate::exceptions::PyStopAsyncIteration;
|
|||
use crate::gil::LockGIL;
|
||||
use crate::impl_::panic::PanicTrap;
|
||||
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::{
|
||||
ffi, Bound, Py, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult, PyTraverseError, PyVisit,
|
||||
Python,
|
||||
ffi, Bound, DowncastError, Py, PyAny, PyCell, PyClass, PyErr, PyObject, PyRef, PyRefMut,
|
||||
PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
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)
|
||||
}
|
||||
|
||||
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> {
|
||||
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> {
|
||||
#[inline]
|
||||
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| {
|
||||
/// # 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
|
||||
|
|
||||
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>`:
|
||||
<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<u16>>
|
||||
<i32 as From<NonZeroI32>>
|
||||
= note: required for `&PyCell<MyClass>` to implement `Into<i32>`
|
||||
= note: required for `i32` to implement `TryFrom<&PyCell<MyClass>>`
|
||||
= note: required for `BoundRef<'_, '_, MyClass>` to implement `Into<i32>`
|
||||
= note: required for `i32` to implement `TryFrom<BoundRef<'_, '_, MyClass>>`
|
||||
|
|
Loading…
Reference in New Issue