From 69dba08b01ac5cb52b98b3c0799baadffbde10f5 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Sat, 9 May 2020 16:36:02 +0900 Subject: [PATCH] Use PyMethodsImpl instead of *ProtocolImpl::methods --- CHANGELOG.md | 2 + guide/src/class.md | 143 +++++++-------- pyo3-derive-backend/src/pyclass.rs | 20 +- pyo3-derive-backend/src/pyproto.rs | 59 +++--- src/class/basic.rs | 58 ------ src/class/context.rs | 59 ------ src/class/descr.rs | 7 - src/class/mapping.rs | 30 --- src/class/methods.rs | 10 +- src/class/number.rs | 283 ----------------------------- src/class/pyasync.rs | 46 ----- src/pyclass.rs | 28 +-- tests/test_arithmetics.rs | 2 - tests/test_dunder.rs | 2 - tests/test_mapping.rs | 1 - 15 files changed, 118 insertions(+), 632 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea7bfb37..cc00ad44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,11 +24,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The `GILGuard` returned from `Python::acquire_gil` will now only assume responsiblity for freeing owned references on drop if no other `GILPool` or `GILGuard` exists. This ensures that multiple calls to the safe api `Python::acquire_gil` cannot lead to dangling references. [#893](https://github.com/PyO3/pyo3/pull/893) - The trait `ObjectProtocol` has been removed, and all the methods from the trait have been moved to `PyAny`. [#911](https://github.com/PyO3/pyo3/pull/911) - The exception to this is `ObjectProtocol::None`, which has simply been removed. Use `Python::None` instead. +- No `#![feature(specialization)]` in user code. [#917](https://github.com/PyO3/pyo3/pull/917) ### Removed - `PyMethodsProtocol` is now renamed to `PyMethodsImpl` and hidden. [#889](https://github.com/PyO3/pyo3/pull/889) - `num-traits` is no longer a dependency. [#895](https://github.com/PyO3/pyo3/pull/895) - `ObjectProtocol`. [#911](https://github.com/PyO3/pyo3/pull/911) +- All `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917) ### Fixed - `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839) diff --git a/guide/src/class.md b/guide/src/class.md index 9e4ed3eb..460e799b 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -17,76 +17,7 @@ struct MyClass { The above example generates implementations for [`PyTypeInfo`], [`PyTypeObject`], and [`PyClass`] for `MyClass`. -Specifically, the following implementation is generated: - -```rust -use pyo3::prelude::*; - -/// Class for demonstration -struct MyClass { - num: i32, - debug: bool, -} - -impl pyo3::pyclass::PyClassAlloc for MyClass {} - -unsafe impl pyo3::PyTypeInfo for MyClass { - type Type = MyClass; - type BaseType = PyAny; - type BaseLayout = pyo3::pycell::PyCellBase; - type Layout = PyCell; - type Initializer = PyClassInitializer; - type AsRefTarget = PyCell; - - const NAME: &'static str = "MyClass"; - const MODULE: Option<&'static str> = None; - const DESCRIPTION: &'static str = "Class for demonstration"; - const FLAGS: usize = 0; - - #[inline] - fn type_object() -> &'static pyo3::ffi::PyTypeObject { - use pyo3::type_object::LazyStaticType; - static TYPE_OBJECT: LazyStaticType = LazyStaticType::new(); - TYPE_OBJECT.get_or_init::() - } -} - -impl pyo3::pyclass::PyClass for MyClass { - type Dict = pyo3::pyclass_slots::PyClassDummySlot; - type WeakRef = pyo3::pyclass_slots::PyClassDummySlot; - type BaseNativeType = PyAny; -} - -impl pyo3::IntoPy for MyClass { - fn into_py(self, py: pyo3::Python) -> pyo3::PyObject { - pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py) - } -} - -pub struct Pyo3MethodsInventoryForMyClass { - methods: &'static [pyo3::class::PyMethodDefType], -} - -impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass { - fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self { - Self { methods } - } - - fn get_methods(&self) -> &'static [pyo3::class::PyMethodDefType] { - self.methods - } -} - -impl pyo3::class::methods::PyMethodsImpl for MyClass { - type Methods = Pyo3MethodsInventoryForMyClass; -} - -pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass); -# let gil = Python::acquire_gil(); -# let py = gil.python(); -# let cls = py.get_type::(); -# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") -``` +If you curious what `#[pyclass]` generates, see [How methods are implemented](#how-methods-are-implemented) section. ## Adding the class to a module @@ -944,7 +875,77 @@ pyclass dependent on whether there is an impl block, we'd need to implement the `#[pyclass]` and override the implementation in `#[pymethods]`, which is to the best of my knowledge only possible with the specialization feature, which can't be used on stable. -To escape this we use [inventory](https://github.com/dtolnay/inventory), which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class::impl_inventory` for more details. +To escape this we use [inventory](https://github.com/dtolnay/inventory), +which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick. +See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class` for more details. + +Specifically, the following implementation is generated: + +```rust +use pyo3::prelude::*; + +/// Class for demonstration +struct MyClass { + num: i32, + debug: bool, +} + +impl pyo3::pyclass::PyClassAlloc for MyClass {} + +unsafe impl pyo3::PyTypeInfo for MyClass { + type Type = MyClass; + type BaseType = PyAny; + type BaseLayout = pyo3::pycell::PyCellBase; + type Layout = PyCell; + type Initializer = PyClassInitializer; + type AsRefTarget = PyCell; + + const NAME: &'static str = "MyClass"; + const MODULE: Option<&'static str> = None; + const DESCRIPTION: &'static str = "Class for demonstration"; + const FLAGS: usize = 0; + + #[inline] + fn type_object() -> &'static pyo3::ffi::PyTypeObject { + use pyo3::type_object::LazyStaticType; + static TYPE_OBJECT: LazyStaticType = LazyStaticType::new(); + TYPE_OBJECT.get_or_init::() + } +} + +impl pyo3::pyclass::PyClass for MyClass { + type Dict = pyo3::pyclass_slots::PyClassDummySlot; + type WeakRef = pyo3::pyclass_slots::PyClassDummySlot; + type BaseNativeType = PyAny; +} + +impl pyo3::IntoPy for MyClass { + fn into_py(self, py: pyo3::Python) -> pyo3::PyObject { + pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py) + } +} + +pub struct Pyo3MethodsInventoryForMyClass { + methods: &'static [pyo3::class::PyMethodDefType], +} +impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass { + fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self { + Self { methods } + } + fn get(&self) -> &'static [pyo3::class::PyMethodDefType] { + self.methods + } +} +impl pyo3::class::methods::PyMethodsImpl for MyClass { + type Methods = Pyo3MethodsInventoryForMyClass; +} +pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass); +# let gil = Python::acquire_gil(); +# let py = gil.python(); +# let cls = py.get_type::(); +# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") +``` + [`GILGuard`]: https://docs.rs/pyo3/latest/pyo3/struct.GILGuard.html [`PyGCProtocol`]: https://docs.rs/pyo3/latest/pyo3/class/gc/trait.PyGCProtocol.html diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 32d5381a..d5aad18a 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -208,11 +208,9 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result> { Ok(descs) } -/// The orphan rule disallows using a generic inventory struct, so we create the whole boilerplate -/// once per class -fn impl_inventory(cls: &syn::Ident) -> TokenStream { - // Try to build a unique type that gives a hint about it's function when - // it comes up in error messages +/// To allow multiple #[pymethods]/#[pyproto] block, we define inventory types. +fn impl_methods_inventory(cls: &syn::Ident) -> TokenStream { + // Try to build a unique type for better error messages let name = format!("Pyo3MethodsInventoryFor{}", cls); let inventory_cls = syn::Ident::new(&name, Span::call_site()); @@ -221,15 +219,11 @@ fn impl_inventory(cls: &syn::Ident) -> TokenStream { pub struct #inventory_cls { methods: &'static [pyo3::class::PyMethodDefType], } - impl pyo3::class::methods::PyMethodsInventory for #inventory_cls { fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self { - Self { - methods - } + Self { methods } } - - fn get_methods(&self) -> &'static [pyo3::class::PyMethodDefType] { + fn get(&self) -> &'static [pyo3::class::PyMethodDefType] { self.methods } } @@ -345,7 +339,7 @@ fn impl_class( quote! {} }; - let inventory_impl = impl_inventory(&cls); + let impl_inventory = impl_methods_inventory(&cls); let base = &attr.base; let flags = &attr.flags; @@ -418,7 +412,7 @@ fn impl_class( #into_pyobject - #inventory_impl + #impl_inventory #extra diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs index 8f0d9330..78d5d6e7 100644 --- a/pyo3-derive-backend/src/pyproto.rs +++ b/pyo3-derive-backend/src/pyproto.rs @@ -36,7 +36,7 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result { )); }; - let tokens = impl_proto_impl(&ast.self_ty, &mut ast.items, proto); + let tokens = impl_proto_impl(&ast.self_ty, &mut ast.items, proto)?; // attach lifetime let mut seg = path.segments.pop().unwrap().into_value(); @@ -57,53 +57,54 @@ fn impl_proto_impl( ty: &syn::Type, impls: &mut Vec, proto: &defs::Proto, -) -> TokenStream { - let mut tokens = TokenStream::new(); +) -> syn::Result { + let mut trait_impls = TokenStream::new(); let mut py_methods = Vec::new(); for iimpl in impls.iter_mut() { if let syn::ImplItem::Method(ref mut met) = iimpl { if let Some(m) = proto.get_proto(&met.sig.ident) { - impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens); + impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut trait_impls); } if let Some(m) = proto.get_method(&met.sig.ident) { let name = &met.sig.ident; - let proto: syn::Path = syn::parse_str(m.proto).unwrap(); - - let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) { - Ok(fn_spec) => fn_spec, - Err(err) => return err.to_compile_error(), - }; - let meth = pymethod::impl_proto_wrap(ty, &fn_spec); + let fn_spec = FnSpec::parse(&met.sig, &mut met.attrs, false)?; + let method = pymethod::impl_proto_wrap(ty, &fn_spec); let coexist = if m.can_coexist { + // We need METH_COEXIST here to prevent __add__ from overriding __radd__ quote!(pyo3::ffi::METH_COEXIST) } else { quote!(0) }; + // TODO(kngwyu): doc py_methods.push(quote! { - impl #proto for #ty - { - #[inline] - fn #name() -> Option { - #meth - - Some(pyo3::class::PyMethodDef { - ml_name: stringify!(#name), - ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap), - // We need METH_COEXIST here to prevent __add__ from overriding __radd__ - ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist, - ml_doc: "" - }) + pyo3::class::PyMethodDefType::Method({ + #method + pyo3::class::PyMethodDef { + ml_name: stringify!(#name), + ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap), + ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist, + ml_doc: "" } - } + }) }); } } } - quote! { - #tokens - - #(#py_methods)* + if py_methods.is_empty() { + return Ok(quote! { #trait_impls }); } + let inventory_submission = quote! { + pyo3::inventory::submit! { + #![crate = pyo3] { + type ProtoInventory = <#ty as pyo3::class::methods::PyMethodsImpl>::Methods; + ::new(&[#(#py_methods),*]) + } + } + }; + Ok(quote! { + #trait_impls + #inventory_submission + }) } diff --git a/src/class/basic.rs b/src/class/basic.rs index 8d13ab49..30183cb8 100644 --- a/src/class/basic.rs +++ b/src/class/basic.rs @@ -9,7 +9,6 @@ //! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html) use crate::callback::HashCallbackOutput; -use crate::class::methods::PyMethodDef; use crate::{ exceptions, ffi, FromPyObject, IntoPy, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult, }; @@ -145,15 +144,11 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> { #[doc(hidden)] pub trait PyObjectProtocolImpl { - fn methods() -> Vec; fn tp_as_object(_type_object: &mut ffi::PyTypeObject); fn nb_bool_fn() -> Option; } impl PyObjectProtocolImpl for T { - default fn methods() -> Vec { - Vec::new() - } default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {} default fn nb_bool_fn() -> Option { None @@ -164,20 +159,6 @@ impl<'p, T> PyObjectProtocolImpl for T where T: PyObjectProtocol<'p>, { - fn methods() -> Vec { - let mut methods = Vec::new(); - - if let Some(def) = ::__format__() { - methods.push(def) - } - if let Some(def) = ::__bytes__() { - methods.push(def) - } - if let Some(def) = ::__unicode__() { - methods.push(def) - } - methods - } fn tp_as_object(type_object: &mut ffi::PyTypeObject) { type_object.tp_str = Self::tp_str(); type_object.tp_repr = Self::tp_repr(); @@ -373,45 +354,6 @@ where } } -#[doc(hidden)] -pub trait FormatProtocolImpl { - fn __format__() -> Option; -} -impl<'p, T> FormatProtocolImpl for T -where - T: PyObjectProtocol<'p>, -{ - default fn __format__() -> Option { - None - } -} - -#[doc(hidden)] -pub trait BytesProtocolImpl { - fn __bytes__() -> Option; -} -impl<'p, T> BytesProtocolImpl for T -where - T: PyObjectProtocol<'p>, -{ - default fn __bytes__() -> Option { - None - } -} - -#[doc(hidden)] -pub trait UnicodeProtocolImpl { - fn __unicode__() -> Option; -} -impl<'p, T> UnicodeProtocolImpl for T -where - T: PyObjectProtocol<'p>, -{ - default fn __unicode__() -> Option { - None - } -} - trait HashProtocolImpl { fn tp_hash() -> Option; } diff --git a/src/class/context.rs b/src/class/context.rs index 9a9e0e98..44ed2743 100644 --- a/src/class/context.rs +++ b/src/class/context.rs @@ -4,7 +4,6 @@ //! Trait and support implementation for context manager api //! -use crate::class::methods::PyMethodDef; use crate::err::PyResult; use crate::{PyClass, PyObject}; @@ -43,61 +42,3 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> { type Success: crate::IntoPy; type Result: Into>; } - -#[doc(hidden)] -pub trait PyContextProtocolImpl { - fn methods() -> Vec; -} - -impl PyContextProtocolImpl for T { - default fn methods() -> Vec { - Vec::new() - } -} - -impl<'p, T> PyContextProtocolImpl for T -where - T: PyContextProtocol<'p>, -{ - #[inline] - fn methods() -> Vec { - let mut methods = Vec::new(); - - if let Some(def) = ::__enter__() { - methods.push(def) - } - if let Some(def) = ::__exit__() { - methods.push(def) - } - - methods - } -} - -#[doc(hidden)] -pub trait PyContextEnterProtocolImpl { - fn __enter__() -> Option; -} - -impl<'p, T> PyContextEnterProtocolImpl for T -where - T: PyContextProtocol<'p>, -{ - default fn __enter__() -> Option { - None - } -} - -#[doc(hidden)] -pub trait PyContextExitProtocolImpl { - fn __exit__() -> Option; -} - -impl<'p, T> PyContextExitProtocolImpl for T -where - T: PyContextProtocol<'p>, -{ - default fn __exit__() -> Option { - None - } -} diff --git a/src/class/descr.rs b/src/class/descr.rs index fb36b72a..1349f7a7 100644 --- a/src/class/descr.rs +++ b/src/class/descr.rs @@ -123,14 +123,10 @@ impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {} #[doc(hidden)] pub trait PyDescrProtocolImpl { - fn methods() -> Vec; fn tp_as_descr(_type_object: &mut ffi::PyTypeObject); } impl PyDescrProtocolImpl for T { - default fn methods() -> Vec { - Vec::new() - } default fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {} } @@ -138,9 +134,6 @@ impl<'p, T> PyDescrProtocolImpl for T where T: PyDescrProtocol<'p>, { - fn methods() -> Vec { - Vec::new() - } fn tp_as_descr(type_object: &mut ffi::PyTypeObject) { type_object.tp_descr_get = Self::tp_descr_get(); type_object.tp_descr_set = Self::tp_descr_set(); diff --git a/src/class/mapping.rs b/src/class/mapping.rs index 4d82a9dd..2f5fa8e5 100644 --- a/src/class/mapping.rs +++ b/src/class/mapping.rs @@ -3,7 +3,6 @@ //! Python Mapping Interface //! Trait and support implementation for implementing mapping support -use crate::class::methods::PyMethodDef; use crate::err::{PyErr, PyResult}; use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject}; @@ -78,16 +77,12 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> { #[doc(hidden)] pub trait PyMappingProtocolImpl { fn tp_as_mapping() -> Option; - fn methods() -> Vec; } impl PyMappingProtocolImpl for T { default fn tp_as_mapping() -> Option { None } - default fn methods() -> Vec { - Vec::new() - } } impl<'p, T> PyMappingProtocolImpl for T @@ -108,17 +103,6 @@ where mp_ass_subscript: f, }) } - - #[inline] - fn methods() -> Vec { - let mut methods = Vec::new(); - - if let Some(def) = ::__reversed__() { - methods.push(def) - } - - methods - } } trait PyMappingLenProtocolImpl { @@ -242,17 +226,3 @@ where ::det_set_dispatch() } } - -#[doc(hidden)] -pub trait PyMappingReversedProtocolImpl { - fn __reversed__() -> Option; -} - -impl<'p, T> PyMappingReversedProtocolImpl for T -where - T: PyMappingProtocol<'p>, -{ - default fn __reversed__() -> Option { - None - } -} diff --git a/src/class/methods.rs b/src/class/methods.rs index dcf30ff9..28ea68a7 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -135,16 +135,16 @@ impl PySetterDef { } /// Implementation detail. Only to be used through the proc macros. -/// Allows arbitrary pymethod blocks to submit their methods, which are eventually -/// collected by pyclass. +/// Allows arbitrary `#[pymethod]/#[pyproto]` blocks to submit their methods, +/// which are eventually collected by `#[pyclass]`. #[doc(hidden)] #[cfg(feature = "macros")] pub trait PyMethodsInventory: inventory::Collect { /// Create a new instance fn new(methods: &'static [PyMethodDefType]) -> Self; - /// Returns the methods for a single impl block - fn get_methods(&self) -> &'static [PyMethodDefType]; + /// Returns the methods for a single `#[pymethods] impl` block + fn get(&self) -> &'static [PyMethodDefType]; } /// Implementation detail. Only to be used through the proc macros. @@ -159,7 +159,7 @@ pub trait PyMethodsImpl { fn py_methods() -> Vec<&'static PyMethodDefType> { inventory::iter:: .into_iter() - .flat_map(PyMethodsInventory::get_methods) + .flat_map(PyMethodsInventory::get) .collect() } } diff --git a/src/class/number.rs b/src/class/number.rs index 207a5b3a..ab5270b4 100644 --- a/src/class/number.rs +++ b/src/class/number.rs @@ -4,7 +4,6 @@ //! Trait and support implementation for implementing number protocol use crate::class::basic::PyObjectProtocolImpl; -use crate::class::methods::PyMethodDef; use crate::err::PyResult; use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject}; @@ -619,14 +618,10 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> { #[doc(hidden)] pub trait PyNumberProtocolImpl: PyObjectProtocolImpl { - fn methods() -> Vec; fn tp_as_number() -> Option; } impl<'p, T> PyNumberProtocolImpl for T { - default fn methods() -> Vec { - Vec::new() - } default fn tp_as_number() -> Option { if let Some(nb_bool) = ::nb_bool_fn() { let meth = ffi::PyNumberMethods { @@ -684,62 +679,6 @@ where nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(), }) } - - #[inline] - fn methods() -> Vec { - let mut methods = Vec::new(); - - if let Some(def) = ::__radd__() { - methods.push(def) - } - if let Some(def) = ::__rsub__() { - methods.push(def) - } - if let Some(def) = ::__rmul__() { - methods.push(def) - } - if let Some(def) = ::__rmatmul__() { - methods.push(def) - } - if let Some(def) = ::__rtruediv__() { - methods.push(def) - } - if let Some(def) = ::__rfloordiv__() { - methods.push(def) - } - if let Some(def) = ::__rmod__() { - methods.push(def) - } - if let Some(def) = ::__rdivmod__() { - methods.push(def) - } - if let Some(def) = ::__rpow__() { - methods.push(def) - } - if let Some(def) = ::__rlshift__() { - methods.push(def) - } - if let Some(def) = ::__rrshift__() { - methods.push(def) - } - if let Some(def) = ::__rand__() { - methods.push(def) - } - if let Some(def) = ::__rxor__() { - methods.push(def) - } - if let Some(def) = ::__ror__() { - methods.push(def) - } - if let Some(def) = ::__complex__() { - methods.push(def) - } - if let Some(def) = ::__round__() { - methods.push(def) - } - - methods - } } trait PyNumberAddProtocolImpl { @@ -1336,20 +1275,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRAddProtocolImpl { - fn __radd__() -> Option; -} - -impl<'p, T> PyNumberRAddProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __radd__() -> Option { - None - } -} - // Fallback trait for nb_add trait PyNumberAddFallback { fn nb_add_fallback() -> Option; @@ -1373,20 +1298,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRSubProtocolImpl { - fn __rsub__() -> Option; -} - -impl<'p, T> PyNumberRSubProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rsub__() -> Option { - None - } -} - trait PyNumberSubFallback { fn nb_sub_fallback() -> Option; } @@ -1409,20 +1320,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRMulProtocolImpl { - fn __rmul__() -> Option; -} - -impl<'p, T> PyNumberRMulProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rmul__() -> Option { - None - } -} - trait PyNumberMulFallback { fn nb_mul_fallback() -> Option; } @@ -1445,20 +1342,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRMatmulProtocolImpl { - fn __rmatmul__() -> Option; -} - -impl<'p, T> PyNumberRMatmulProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rmatmul__() -> Option { - None - } -} - trait PyNumberMatmulFallback { fn nb_matmul_fallback() -> Option; } @@ -1481,20 +1364,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRTruedivProtocolImpl { - fn __rtruediv__() -> Option; -} - -impl<'p, T> PyNumberRTruedivProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rtruediv__() -> Option { - None - } -} - trait PyNumberTruedivFallback { fn nb_truediv_fallback() -> Option; } @@ -1517,20 +1386,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRFloordivProtocolImpl { - fn __rfloordiv__() -> Option; -} - -impl<'p, T> PyNumberRFloordivProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rfloordiv__() -> Option { - None - } -} - trait PyNumberFloordivFallback { fn nb_floordiv_fallback() -> Option; } @@ -1553,20 +1408,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRModProtocolImpl { - fn __rmod__() -> Option; -} - -impl<'p, T> PyNumberRModProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rmod__() -> Option { - None - } -} - trait PyNumberModFallback { fn nb_mod_fallback() -> Option; } @@ -1589,20 +1430,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRDivmodProtocolImpl { - fn __rdivmod__() -> Option; -} - -impl<'p, T> PyNumberRDivmodProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rdivmod__() -> Option { - None - } -} - trait PyNumberDivmodFallback { fn nb_divmod_fallback() -> Option; } @@ -1625,20 +1452,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRPowProtocolImpl { - fn __rpow__() -> Option; -} - -impl<'p, T> PyNumberRPowProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rpow__() -> Option { - None - } -} - trait PyNumberPowFallback { fn nb_pow_fallback() -> Option; } @@ -1661,20 +1474,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRLShiftProtocolImpl { - fn __rlshift__() -> Option; -} - -impl<'p, T> PyNumberRLShiftProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rlshift__() -> Option { - None - } -} - trait PyNumberLShiftFallback { fn nb_lshift_fallback() -> Option; } @@ -1697,20 +1496,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRRShiftProtocolImpl { - fn __rrshift__() -> Option; -} - -impl<'p, T> PyNumberRRShiftProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rrshift__() -> Option { - None - } -} - trait PyNumberRRshiftFallback { fn nb_rshift_fallback() -> Option; } @@ -1733,20 +1518,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRAndProtocolImpl { - fn __rand__() -> Option; -} - -impl<'p, T> PyNumberRAndProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rand__() -> Option { - None - } -} - trait PyNumberAndFallback { fn nb_and_fallback() -> Option; } @@ -1769,20 +1540,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberRXorProtocolImpl { - fn __rxor__() -> Option; -} - -impl<'p, T> PyNumberRXorProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __rxor__() -> Option { - None - } -} - trait PyNumberXorFallback { fn nb_xor_fallback() -> Option; } @@ -1805,20 +1562,6 @@ where } } -#[doc(hidden)] -pub trait PyNumberROrProtocolImpl { - fn __ror__() -> Option; -} - -impl<'p, T> PyNumberROrProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __ror__() -> Option { - None - } -} - trait PyNumberOrFallback { fn nb_or_fallback() -> Option; } @@ -1995,29 +1738,3 @@ where py_unary_func!(PyNumberIndexProtocol, T::__index__) } } - -pub trait PyNumberComplexProtocolImpl { - fn __complex__() -> Option; -} - -impl<'p, T> PyNumberComplexProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __complex__() -> Option { - None - } -} - -pub trait PyNumberRoundProtocolImpl { - fn __round__() -> Option; -} - -impl<'p, T> PyNumberRoundProtocolImpl for T -where - T: PyNumberProtocol<'p>, -{ - default fn __round__() -> Option { - None - } -} diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs index a43dc57c..a65a91d6 100644 --- a/src/class/pyasync.rs +++ b/src/class/pyasync.rs @@ -8,7 +8,6 @@ //! [PEP-0492](https://www.python.org/dev/peps/pep-0492/) //! -use crate::class::methods::PyMethodDef; use crate::err::PyResult; use crate::{ffi, PyClass, PyObject}; @@ -89,17 +88,12 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> { #[doc(hidden)] pub trait PyAsyncProtocolImpl { fn tp_as_async() -> Option; - fn methods() -> Vec; } impl PyAsyncProtocolImpl for T { default fn tp_as_async() -> Option { None } - - default fn methods() -> Vec { - Vec::new() - } } impl<'p, T> PyAsyncProtocolImpl for T @@ -114,20 +108,6 @@ where am_anext: Self::am_anext(), }) } - - #[inline] - fn methods() -> Vec { - let mut methods = Vec::new(); - - if let Some(def) = ::__aenter__() { - methods.push(def) - } - if let Some(def) = ::__aexit__() { - methods.push(def) - } - - methods - } } trait PyAsyncAwaitProtocolImpl { @@ -227,29 +207,3 @@ mod anext { } } } - -trait PyAsyncAenterProtocolImpl { - fn __aenter__() -> Option; -} - -impl<'p, T> PyAsyncAenterProtocolImpl for T -where - T: PyAsyncProtocol<'p>, -{ - default fn __aenter__() -> Option { - None - } -} - -trait PyAsyncAexitProtocolImpl { - fn __aexit__() -> Option; -} - -impl<'p, T> PyAsyncAexitProtocolImpl for T -where - T: PyAsyncProtocol<'p>, -{ - default fn __aexit__() -> Option { - None - } -} diff --git a/src/pyclass.rs b/src/pyclass.rs index f0da8c35..665e8c98 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -172,7 +172,7 @@ where // normal methods if !methods.is_empty() { methods.push(ffi::PyMethodDef_INIT); - type_object.tp_methods = Box::into_raw(methods.into_boxed_slice()) as *mut _; + type_object.tp_methods = Box::into_raw(methods.into_boxed_slice()) as _; } // class attributes @@ -197,7 +197,7 @@ where } if !props.is_empty() { props.push(ffi::PyGetSetDef_INIT); - type_object.tp_getset = Box::into_raw(props.into_boxed_slice()) as *mut _; + type_object.tp_getset = Box::into_raw(props.into_boxed_slice()) as _; } // set type flags @@ -264,33 +264,9 @@ fn py_class_method_defs() -> ( } } - for def in ::methods() { - defs.push(def.as_method_def()); - } - for def in ::methods() { - defs.push(def.as_method_def()); - } - for def in ::methods() { - defs.push(def.as_method_def()); - } - for def in ::methods() { - defs.push(def.as_method_def()); - } - for def in ::methods() { - defs.push(def.as_method_def()); - } - - py_class_async_methods::(&mut defs); - (new, call, defs, attrs) } -fn py_class_async_methods(defs: &mut Vec) { - for def in ::methods() { - defs.push(def.as_method_def()); - } -} - fn py_class_properties() -> Vec { let mut defs = std::collections::HashMap::new(); diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index 8b1260dc..740bce31 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -1,5 +1,3 @@ -#![feature(specialization)] - use pyo3::class::basic::CompareOp; use pyo3::class::*; use pyo3::prelude::*; diff --git a/tests/test_dunder.rs b/tests/test_dunder.rs index 3ae14908..421873f0 100644 --- a/tests/test_dunder.rs +++ b/tests/test_dunder.rs @@ -1,5 +1,3 @@ -#![feature(specialization)] - use pyo3::class::{ PyContextProtocol, PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PySequenceProtocol, }; diff --git a/tests/test_mapping.rs b/tests/test_mapping.rs index 17a0203b..0d14d47c 100644 --- a/tests/test_mapping.rs +++ b/tests/test_mapping.rs @@ -1,4 +1,3 @@ -#![feature(specialization)] use std::collections::HashMap; use pyo3::exceptions::KeyError;