Iterate over enum variants in macro

I'm trying to write a macro that extends an existing macro with some additional variants.
Example:

enum MyEnum {
    VariantA,
    VariantB,
}

extend_enum!("MyExtendedEnum", MyEnum);

fn main() {
    // variants from original enum...
    let a = MyExtendedEnum::VariantA;
    let b = MyExtendedEnum::VariantB;
    // plus the new variants...
    let c = MyExtendedEnum::VariantC;
    let d = MyExtendedEnum::VariantD;
}

I've used a procedural macro which accepts the original enum name as an Ident. I'm stuck on how to get the enum variants from the Ident.

extern crate proc_macro;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse::{Parse, ParseStream}, parse_macro_input, Ident, LitStr, Token};

struct ExtendEnumInput {
    extended_enum_name: LitStr,
    base_enum: Ident,
}

impl Parse for ExtendEnumInput {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let extended_enum_name = input.parse()?;
        input.parse::<Token![,]>()?;
        let base_enum = input.parse()?;    
        Ok(ExtendEnumInput {
            extended_enum_name,
            base_enum,
        })
    }
}

#[proc_macro]
pub fn extend_enum(input: TokenStream) -> TokenStream {
    let ExtendEnumInput { extended_enum_name, base_enum} = parse_macro_input!(input as ExtendEnumInput);
    let enum_name = format_ident!("{}", extended_enum_name.value());  
    let original_variants = todo!();

    let output = quote! {
        enum #enum_name {
            #(
                #original_variants,
            )*
            VariantC,
            VariantD,
        }
    };

    TokenStream::from(output)
}

I've tried using ItemEnum instead of Ident but this fails to compile with an error saying it expects an enum.

you can't. macros only have access to syntactical tokens, they don't have any type information.

if you need to access the variants of an enum, your macro must be applied to the definition of the enum, not just the name of the enum. e.g. you can use an attribute macro, or a derive macro, and parse the enum definition in the macro (usually with the help of the syn crate).

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.