Why is a negative integer not a valid pattern in a macro?

Viewed 408

Let us consider a simple enum implementation with a static method that check whether a value has an associated value (the efficiency of the implementation is not to be regarded here):

enum Letter {
    Alpha = -1,
    A = 0,
    B = 1,
    C = 2,
}

impl Letter {
    pub fn in_enum(value: isize) -> bool
    {
        match value {
            -1 => true,
            0 => true,
            1 => true,
            2 => true,
            _ => false,
        }
    }
}

Now, let us write a macro for building enums with an equivalent in_enum method. The macro below was written with some guidance from the Serde guide for enum deserialization as numbers, in which matching for enum variant values also occurs.

macro_rules! my_enum {
    ($name:ident { $($variant:ident = $value:expr, )* }) => {
        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
        pub enum $name {
            $($variant = $value,)*
        }

        impl $name {
            pub fn in_enum(value: isize) -> bool
            {
                match value {
                    $( $value => true, )*
                    _ => false,
                }
            }
        }
    }
}

my_enum!(Letter {
  Alpha = -1,
  A = 0,
  B = 1,
  C = 2,
});

Playground. With version 1.18.0, the compiler won't accept the variant with a negative integer.

error: expected pattern, found `-1`
  --> src/main.rs:13:24
   |
13 |                     $( $value => true, )*
   |                        ^^^^^^

This seems to happen regardless of how I write this pattern down in the macro, or whether I use i32 or isize for the value method parameter. Changing the fragment specifier of $value to pat is also out of the question: the compiler will refuse to build the enum, even without negative variant values.

error: expected expression, found `-1`
 --> src/main.rs:5:26
  |
5 |             $($variant = $value,)*
  |                          ^^^^^^

What's surprising about this is that it works without using macros, as well as when I discard the Alpha variant.

Why does this happen?

1 Answers
Related