From e39881c208bad9da9bf7f37393e937b1af901a5b Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sun, 6 Feb 2022 23:26:57 +0000 Subject: [PATCH] refactor: inline pyclass_intrinsic_items --- guide/src/class.md | 3 +- pyo3-macros-backend/src/pyclass.rs | 73 +++++++++++++++--------------- src/impl_/pyclass.rs | 3 -- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/guide/src/class.md b/guide/src/class.md index 50478df4..047e1703 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -861,8 +861,9 @@ impl pyo3::impl_::pyclass::PyClassImpl for MyClass { fn for_all_items(visitor: &mut dyn FnMut(&pyo3::impl_::pyclass::PyClassItems)) { use pyo3::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); + static INTRINSIC_ITEMS: &PyClassItems = PyClassItems { slots: &[], methods: &[] }; + visitor(&INTRINSIC_ITEMS); visitor(collector.py_methods()); - visitor(collector.pyclass_intrinsic_items()); } fn get_new() -> Option { use pyo3::impl_::pyclass::*; diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index 3d6d5678..3f2ed76d 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -382,11 +382,14 @@ fn impl_class( ) -> syn::Result { let pytypeinfo_impl = impl_pytypeinfo(cls, attr, Some(&deprecations)); - let py_class_impl = PyClassImplsBuilder::new(cls, attr, methods_type) - .doc(doc) - .impl_all(); - - let descriptors = impl_descriptors(cls, field_options)?; + let py_class_impl = PyClassImplsBuilder::new( + cls, + attr, + methods_type, + descriptors_to_items(cls, field_options)?, + ) + .doc(doc) + .impl_all(); Ok(quote! { const _: () = { @@ -395,8 +398,6 @@ fn impl_class( #pytypeinfo_impl #py_class_impl - - #descriptors }; }) } @@ -452,10 +453,14 @@ fn impl_enum_class( krate: syn::Path, ) -> syn::Result { let pytypeinfo = impl_pytypeinfo(cls, args, None); - let pyclass_impls = PyClassImplsBuilder::new(cls, args, methods_type) - .doc(doc) - .impl_all(); - let descriptors = unit_variants_as_descriptors(cls, variants.iter().map(|v| v.ident)); + let pyclass_impls = PyClassImplsBuilder::new( + cls, + args, + methods_type, + unit_variants_as_items(cls, variants.iter().map(|v| v.ident)), + ) + .doc(doc) + .impl_all(); let default_repr_impl = { let variants_repr = variants.iter().map(|variant| { @@ -487,13 +492,11 @@ fn impl_enum_class( #pyclass_impls #default_impls - - #descriptors }; }) } -fn unit_variants_as_descriptors<'a>( +fn unit_variants_as_items<'a>( cls: &'a syn::Ident, variant_names: impl IntoIterator, ) -> TokenStream { @@ -511,16 +514,9 @@ fn unit_variants_as_descriptors<'a>( .map(|var| gen_py_const(&cls_type, &variant_to_attribute(var))); quote! { - impl _pyo3::impl_::pyclass::PyClassIntrinsicItems<#cls> - for _pyo3::impl_::pyclass::PyClassImplCollector<#cls> - { - fn pyclass_intrinsic_items(self) -> &'static _pyo3::impl_::pyclass::PyClassItems { - static ITEMS: _pyo3::impl_::pyclass::PyClassItems = _pyo3::impl_::pyclass::PyClassItems { - methods: &[#(#py_methods),*], - slots: &[] - }; - &ITEMS - } + _pyo3::impl_::pyclass::PyClassItems { + methods: &[#(#py_methods),*], + slots: &[] } } } @@ -537,7 +533,7 @@ fn extract_variant_data(variant: &syn::Variant) -> syn::Result, ) -> syn::Result { @@ -577,16 +573,9 @@ fn impl_descriptors( .collect::>()?; Ok(quote! { - impl _pyo3::impl_::pyclass::PyClassIntrinsicItems<#cls> - for _pyo3::impl_::pyclass::PyClassImplCollector<#cls> - { - fn pyclass_intrinsic_items(self) -> &'static _pyo3::impl_::pyclass::PyClassItems { - static ITEMS: _pyo3::impl_::pyclass::PyClassItems = _pyo3::impl_::pyclass::PyClassItems { - methods: &[#(#py_methods),*], - slots: &[] - }; - &ITEMS - } + _pyo3::impl_::pyclass::PyClassItems { + methods: &[#(#py_methods),*], + slots: &[] } }) } @@ -632,15 +621,22 @@ struct PyClassImplsBuilder<'a> { cls: &'a syn::Ident, attr: &'a PyClassArgs, methods_type: PyClassMethodsType, + default_items: TokenStream, doc: Option, } impl<'a> PyClassImplsBuilder<'a> { - fn new(cls: &'a syn::Ident, attr: &'a PyClassArgs, methods_type: PyClassMethodsType) -> Self { + fn new( + cls: &'a syn::Ident, + attr: &'a PyClassArgs, + methods_type: PyClassMethodsType, + default_items: TokenStream, + ) -> Self { Self { cls, attr, methods_type, + default_items, doc: None, } } @@ -802,6 +798,8 @@ impl<'a> PyClassImplsBuilder<'a> { None }; + let default_items = &self.default_items; + quote! { impl _pyo3::impl_::pyclass::PyClassImpl for #cls { const DOC: &'static str = #doc; @@ -817,7 +815,8 @@ impl<'a> PyClassImplsBuilder<'a> { fn for_all_items(visitor: &mut dyn ::std::ops::FnMut(& _pyo3::impl_::pyclass::PyClassItems)) { use _pyo3::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); - visitor(collector.pyclass_intrinsic_items()); + static INTRINSIC_ITEMS: PyClassItems = #default_items; + visitor(&INTRINSIC_ITEMS); // This depends on Python implementation detail; // an old slot entry will be overriden by newer ones. visitor(collector.pyclass_default_items()); diff --git a/src/impl_/pyclass.rs b/src/impl_/pyclass.rs index 146a20f0..8f33b964 100644 --- a/src/impl_/pyclass.rs +++ b/src/impl_/pyclass.rs @@ -736,9 +736,6 @@ pub trait PyClassInventory: inventory::Collect { fn items(&'static self) -> &'static PyClassItems; } -// Methods from #[pyo3(get, set)] on struct fields. -items_trait!(PyClassIntrinsicItems, pyclass_intrinsic_items); - // Items from #[pymethods] if not using inventory. #[cfg(not(feature = "multiple-pymethods"))] items_trait!(PyMethods, py_methods);