#Proc Macro to implement marker trait for enum variants

9 messages · Page 1 of 1 (latest)

sand robin
#

Hello everyone, I am trying to create a Macro that I can put on Enum variants to add a generic marker trait to them. I intend to use it in combination with strum to build type-safe string keys.

The goal:

pub enum FieldDataKey {
    #[data_key(f64)] // <-- my macro
    Enabled(u32),

    #[data_key(String)] // <- my macro
    Name(u32),
}

should generate

impl DataKey<f64> for FieldDataKey::Enabled {}
impl DataKey<String> for FieldDataKey::Name {}

How does this work? I am having a hard time finding any resources that explain how the macro system can be applied to enum variants.

balmy spear
# sand robin Hello everyone, I am trying to create a Macro that I can put on Enum variants to...

You can't apply a macro to an enum variant, since wherever you call the macro still has to be valid rust before expansion. Quoting from The Little Book of Rust Macros (which is a very good read for learning about macros):

Because syntax extensions are parsed into the AST, they can only appear in positions where they are explicitly supported.

  • Patterns
  • Statements
  • Expressions
  • Items(this includes impl items)
  • Types
    Some things not on this list:
  • Identifiers
  • Match arms
  • Struct fields
    There is absolutely, definitely no way to use syntax extensions in any position not on the first list.
    This means you must enclose the entire enum in a macro, ie ```rust
    make_data_keys!{
    pub enum FieldDataKey {
    ...
    }
    }

#[make_data_keys]
pub enum FieldDataKey {
...
}

#[derive(DataKeys)]
pub enum FieldDataKey {
...
}

You can have the macro use the attributes `#[data_key(...)]` that you place on enum variants, but you must enclose the entire enum.
sand robin
#

I am okay with putting an extra macro on top of my enum so that I can do what strum does

#

in strum, I can do #[derive(Display)] and then #[strum(to_string = "...")] on each Enum variant

sand robin
balmy spear
#

I'm not familiar with strum, but generally impl Trait for Enum::Variant would be invalid. At least in current rust, enum variants are not their own types, so you can't impl for a specific variant.

sand robin
#

oh. I mistakenly assumed that this would work because my IDE didn't complain when I tried explicitly writing that code

#

I guess I should've tried to compile it first.

#

therefore, I am probably better off using separate unit types as my data keys