num_enum
num_enum copied to clipboard
catch_all generates compilation errors and incorrect discriminant when it is not the last variant
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,
}