diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index 96c055e54..aa77b4e63 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -1,7 +1,7 @@ use super::Diagnostic; use crate::util::{ - path_eq, AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, - ItemMetaInner, ItemNursery, ALL_ALLOWED_NAMES, + path_eq, pyclass_ident_and_attrs, AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, + ErrorVec, ItemMeta, ItemMetaInner, ItemNursery, ALL_ALLOWED_NAMES, }; use proc_macro2::TokenStream; use quote::{quote, quote_spanned, ToTokens}; @@ -165,15 +165,7 @@ pub(crate) fn impl_pyclass( attr: AttributeArgs, item: Item, ) -> std::result::Result { - let (ident, attrs) = match &item { - Item::Struct(syn::ItemStruct { ident, attrs, .. }) => (ident, attrs), - Item::Enum(syn::ItemEnum { ident, attrs, .. }) => (ident, attrs), - other => bail_span!( - other, - "#[pyclass] can only be on a struct or enum declaration" - ), - }; - + let (ident, attrs) = pyclass_ident_and_attrs(&item)?; let fake_ident = Ident::new("pyclass", item.span()); let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?; let class_name = class_meta.class_name()?; diff --git a/derive/src/pymodule.rs b/derive/src/pymodule.rs index d85ae3553..152236fd3 100644 --- a/derive/src/pymodule.rs +++ b/derive/src/pymodule.rs @@ -1,7 +1,7 @@ use crate::error::Diagnostic; use crate::util::{ - AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery, - SimpleItemMeta, ALL_ALLOWED_NAMES, + pyclass_ident_and_attrs, AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, + ItemMeta, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES, }; use proc_macro2::TokenStream; use quote::{quote, quote_spanned, ToTokens}; @@ -279,13 +279,7 @@ impl ModuleItem for FunctionItem { impl ModuleItem for ClassItem { fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> { - let ident = match args.item { - Item::Struct(syn::ItemStruct { ident, .. }) => ident.clone(), - Item::Enum(syn::ItemEnum { ident, .. }) => ident.clone(), - other => { - return Err(self.new_syn_error(other.span(), "can only be on a struct or enum")) - } - }; + let (ident, _) = pyclass_ident_and_attrs(&args.item)?; let (module_name, class_name) = { let class_attr = &mut args.attrs[self.inner.index]; if self.pyattrs.is_empty() { diff --git a/derive/src/util.rs b/derive/src/util.rs index 2fa3e40ef..0759ce91a 100644 --- a/derive/src/util.rs +++ b/derive/src/util.rs @@ -397,6 +397,18 @@ impl AttributeExt for Attribute { } } +pub(crate) fn pyclass_ident_and_attrs(item: &syn::Item) -> Result<(&Ident, &[Attribute])> { + use syn::Item::*; + match item { + Struct(syn::ItemStruct { ident, attrs, .. }) => Ok((ident, attrs)), + Enum(syn::ItemEnum { ident, attrs, .. }) => Ok((ident, attrs)), + other => Err(syn::Error::new_spanned( + other, + "#[pyclass] can only be on a struct or enum declaration", + )), + } +} + pub(crate) trait ErrorVec: Sized { fn into_error(self) -> Option; fn into_result(self) -> Result<()> {