diff --git a/derive/src/union.rs b/derive/src/union.rs index d557995e..62c8d074 100644 --- a/derive/src/union.rs +++ b/derive/src/union.rs @@ -60,9 +60,14 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { } }; - if let Type::Path(p) = &ty { + let mut ty = ty; + while let Type::Group(group) = ty { + ty = &*group.elem; + } + + if matches!(ty, Type::Path(_) | Type::Macro(_)) { // This validates that the field type wasn't already used - if !enum_items.insert(p) { + if !enum_items.insert(ty) { return Err( Error::new_spanned(&ty, "This type already used in another variant").into(), ); @@ -70,16 +75,16 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { enum_names.push(enum_name); - let mut assert_ty = p.clone(); - RemoveLifetime.visit_type_path_mut(&mut assert_ty); + let mut assert_ty = ty.clone(); + RemoveLifetime.visit_type_mut(&mut assert_ty); if !variant.flatten { type_into_impls.push(quote! { #crate_name::static_assertions::assert_impl_one!(#assert_ty: #crate_name::ObjectType); #[allow(clippy::all, clippy::pedantic)] - impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause { - fn from(obj: #p) -> Self { + impl #impl_generics ::std::convert::From<#ty> for #ident #ty_generics #where_clause { + fn from(obj: #ty) -> Self { #ident::#enum_name(obj) } } @@ -89,8 +94,8 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { #crate_name::static_assertions::assert_impl_one!(#assert_ty: #crate_name::UnionType); #[allow(clippy::all, clippy::pedantic)] - impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause { - fn from(obj: #p) -> Self { + impl #impl_generics ::std::convert::From<#ty> for #ident #ty_generics #where_clause { + fn from(obj: #ty) -> Self { #ident::#enum_name(obj) } } @@ -99,15 +104,15 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { if !variant.flatten { registry_types.push(quote! { - <#p as #crate_name::OutputType>::create_type_info(registry); + <#ty as #crate_name::OutputType>::create_type_info(registry); }); possible_types.push(quote! { - possible_types.insert(<#p as #crate_name::OutputType>::type_name().into_owned()); + possible_types.insert(<#ty as #crate_name::OutputType>::type_name().into_owned()); }); } else { possible_types.push(quote! { if let #crate_name::registry::MetaType::Union { possible_types: possible_types2, .. } = - registry.create_fake_output_type::<#p>() { + registry.create_fake_output_type::<#ty>() { possible_types.extend(possible_types2); } }); @@ -115,11 +120,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult { if !variant.flatten { get_introspection_typename.push(quote! { - #ident::#enum_name(obj) => <#p as #crate_name::OutputType>::type_name() + #ident::#enum_name(obj) => <#ty as #crate_name::OutputType>::type_name() }); } else { get_introspection_typename.push(quote! { - #ident::#enum_name(obj) => <#p as #crate_name::OutputType>::introspection_type_name(obj) + #ident::#enum_name(obj) => <#ty as #crate_name::OutputType>::introspection_type_name(obj) }); } diff --git a/tests/union.rs b/tests/union.rs index 4de78dee..06db6ae0 100644 --- a/tests/union.rs +++ b/tests/union.rs @@ -419,3 +419,24 @@ pub async fn test_trait_object_in_union() { }) ); } + +macro_rules! generate_union { + ($name:ident, $variant_ty:ty) => { + #[derive(Union)] + pub enum $name { + Val($variant_ty), + } + }; +} + +#[test] +pub fn test_macro_generated_union() { + #[derive(SimpleObject)] + pub struct IntObj { + pub val: i32, + } + + generate_union!(MyEnum, IntObj); + + let _ = MyEnum::Val(IntObj { val: 1 }); +}