Specify type of enum?

If I have an enum like this:

#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
pub enum Foo {
    Bar = 0x42,
}

is it possible to pass that to a function that expects a u32, without explicitly casting Foo::Bar as u32 ?

Alternatively - if that’s purely a typesystem restriction, can I be certain that due to the #[repr(u32)], a cast to u32 will effectively be a noop?

The first one is easy to answer: no.

fn test(int: u32) {}

fn main() {
    test(Foo::Bar);
}

gives the error expected u32, found enum "Foo".

From the reference on Enums and Operators, I’d say it’s a noop.

1 Like

Would this be any better for you?

#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
pub enum Foo {
    Bar = 123,
    Baz = 5_000,
}

impl Into<u32> for Foo {
    fn into(self) -> u32 {
        self as u32
    }
}

fn main() {
    test(Foo::Baz.into());
}

fn test(x: u32) {
    println!("{}", x);
}
3 Likes

And a step further:

fn test(int: impl Into<u32>) {
   let int = int.into();
}

However, the blurry line between enums and integers is a C-ism, and a code smell in Rust. If the code isn’t needed for interoperability with some pre-existing C solution, there may be a better solution for Rust:

3 Likes

Very close! Use case here is interoperability with wasm/web-sys :slight_smile:

I see. In that case you’ll need to convert :frowning: Also be careful when converting the other way — casting an invalid integer value to an enum (e.g. 11 to an enum that has 10 options) is an undefined behavior and can cause the code to seriously misbehave.

1 Like