num_enum icon indicating copy to clipboard operation
num_enum copied to clipboard

catch_all generates compilation errors and incorrect discriminant when it is not the last variant

Open oftheforest opened this issue 9 months ago • 0 comments

This example…

use num_enum::FromPrimitive;

#[derive(FromPrimitive)]
#[repr(u8)]
pub enum Number {
    Zero = 0,
    #[num_enum(catch_all)]
    Multiple(u8) = 2,
    One = 1,
}

produces this compiler error:

error[E0308]: `match` arms have incompatible types
 --> src/lib.rs:3:10
  |
3 | #[derive(FromPrimitive)]
  |          ^^^^^^^^^^^^^
  |          |
  |          expected `Number`, found enum constructor
  |          this is found to be of type `Number`
  |          `match` arms have incompatible types
...
8 |     Multiple(u8) = 2,
  |     -------- `Multiple` defines an enum variant constructor here, which should be called
  |
  = note:          expected enum `Number`
          found enum constructor `fn(u8) -> Number {Number::Multiple}`
  = note: this error originates in the derive macro `FromPrimitive` (in Nightly builds, run with -Z macro-backtrace for more info)

Running cargo expand is illuminating:

impl ::num_enum::FromPrimitive for Number {
    type Primitive = u8;
    fn from_primitive(number: Self::Primitive) -> Self {
        #![allow(non_upper_case_globals)]
        const Zero__num_enum_0__: u8 = 0;
        // This is the wrong integer value for this variant:
        const One__num_enum_0__: u8 = 2;
        #[deny(unreachable_patterns)]
        match number {
            Zero__num_enum_0__ => Self::Zero,
            // And this is mapping this constant to the wrong variant:
            One__num_enum_0__ => Self::Multiple,
            #[allow(unreachable_patterns)]
            _ => Self::Multiple(number),
        }
    }
}

Everything works as expected, however, if the catch_all variant is moved to the end:

use num_enum::FromPrimitive;

#[derive(FromPrimitive)]
#[repr(u8)]
pub enum Number {
    Zero = 0,
    One = 1,
    #[num_enum(catch_all)]
    Multiple(u8) = 2,
}

oftheforest avatar May 24 '24 04:05 oftheforest