7
votes

I'm trying to write a macro that generates a From impl for an enum by wrapping the type in a certain variant.

I've come up with this:

macro_rules! variant_derive_from {
    ($enum:ty:$variant:ident($from:ty)) => {
        impl From<$from> for $enum {
            fn from(thing: $from) -> $enum { return $enum::$variant(thing) }
        }
    };
}

However, whenever I try to actually use this macro I get the following error:

error: expected expression, found `B`
|             fn from(thing: $from) -> $enum { $enum::$variant(thing) }
|                                               ^^^^

I couldn't figure out why this might be happening, so I ran a build with macro tracing on, and the macro apparently expands to the following (dummy types, of course):

impl From < A > for B { fn from ( thing : A ) -> B { B :: AVariant ( thing ) } }

When pasting this directly into the code, it compiles successfully. What gives??

Here's a full example of the error.

1

1 Answers

4
votes

A ty placeholder only works as type, not as a namespace. Using ident instead should work just fine in your example.

ident doesn't accept paths ("foo::Bar") though (and using path also doesn't seem to work in this case); you should be able to workaround it by manually constructing paths like matching this: $enum:ident $(:: $enum_path:ident)* (use it like this: $enum $(:: $enum_path)*).