Generate union pattern in match statement from macro?

Given an enum Foo, I'm trying to create macro that takes an expression v and a series of idents and generates a match expression like the following:

generate_match!(value, A, B, C)

should create

match value {
     Foo::A | Foo::B | Foo::C => {
         println!("value: {:?}", value);
     },
    _ => {
         println!("No match!");
    }
}

Here is my current attempt:

macro_rules! attempt {
  ($x:expr, $($a:ident),+) => {
    match $x {
      NodeValue::$($a) | + => {
        println!("hit match!");
      },
      _ => {
        println!("other arm!");
      }
    };
  };
}

And this works fine for attempt!(value, A), but it fails for attempt!(value, A, B).

I tried to create a simpler macro just to generate the union like this:

macro_rules! union {
  ($x:ident) => Foo::$x,
  ($x:ident, $($y:ident),+) => Foo::$x | union!(+)
}

However, this complains with "no rules expected the token ::".

Anyone have guidance?

If you'll expand the macro, you'll see that it expands to:

match value {
     Foo::A | B | C => {
         println!("value: {:?}", value);
     },
    _ => {
         println!("No match!");
    }
}

Because the repetition only includes $a.

What you need:

macro_rules! attempt {
  ($x:expr, $($a:ident),+) => {
    match $x {
      $(NodeValue::$a) | + => {
        println!("hit match!");
      },
      _ => {
        println!("other arm!");
      }
    };
  };
}
2 Likes