Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C-style enum doesn't work in match arm #44266

Closed
ctz opened this issue Sep 2, 2017 · 7 comments
Closed

C-style enum doesn't work in match arm #44266

ctz opened this issue Sep 2, 2017 · 7 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@ctz
Copy link
Contributor

ctz commented Sep 2, 2017

I expected this to work, but it doesn't:

enum Thing {
    Foo = 0,
    Bar = 1,
}

fn main() {
    // works
    println!("Foo is {}", Thing::Foo as u8);
    
    // doesn't
    match 0u8 {
        Thing::Foo as u8 => println!("0 is Foo"),
        _ => println!("eh")
    };
}

with:

error: expected one of `::`, `=>`, `if`, or `|`, found `as`
  --> src/main.rs:11:20
   |
11 |         Thing::Foo as u8 => println!("0 is Foo"),
   |                   -^^ unexpected token
   |                   |
   |                   expected one of `::`, `=>`, `if`, or `|` here

Putting the cast inside extra parens doesn't help.

My use case is having an enum whose ordinals match an external protocol definition, then matching against the value read off the wire to convert into a member of the enum. I would expect this to be super common.

Previous history:

@ctz
Copy link
Contributor Author

ctz commented Sep 2, 2017

In fact, this has little to do with C-style enums per se. Instead, it's casts which aren't allowed in match arms: see eg #11791. That's... less than ideal.

@ctz
Copy link
Contributor Author

ctz commented Sep 2, 2017

From that issue, the workaround seems to be:

enum Thing {
    Foo = 0,
    Bar = 1,
}

const THING_FOO: u8 = Thing::Foo as u8;
const THING_BAR: u8 = Thing::Bar as u8;

fn main() {
    // works
    println!("Foo is {}", Thing::Foo as u8);
    
    // doesn't
    match 0u8 {
        THING_FOO => println!("0 is Foo"),
        _ => println!("eh")
    };
}

That's doable but pretty annoying and unergonomic.

@steffengy
Copy link
Contributor

steffengy commented Sep 2, 2017

I think the following is the more widely used workaround for that:

match 0u8 {
    x if x == Thing::Foo as u8 => { ... }
    x if x == Thing::Bar as u8 => { ... }
    _ => println!("..."),
}

(Which obviously is even worse since you easily can get overlapping variants and lose
most benefits of enums in the first place)

@Mark-Simulacrum Mark-Simulacrum added C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Sep 2, 2017
@durka
Copy link
Contributor

durka commented Sep 2, 2017

Better workaround:

#[macro_use] extern crate enum_primitive_derive;
extern crate num_traits;
use num_traits::FromPrimitive;

#[derive(Primitive)]
enum Thing {
    Foo = 0,
    Bar = 1,
}

match Thing::from_u8(0) {
    Some(Thing::Foo) => ...,
    Some(Thing::Bar) => ....,
    None => panic!("out of range"),
}

@briansmith
Copy link
Contributor

Thing::Foo as u8

I think this explicitly SHOULD NOT work. In particular, I think we should be working towards the deprecation of the as operator and so extending support for it would be a step in the wrong direction.

@oli-obk
Copy link
Contributor

oli-obk commented Sep 11, 2017

This is a feature request that sounds like it'll be a heavily discussed RFC. You should close it here and open an issue on the RFC repo or the internals forum

@steveklabnik
Copy link
Member

Yup, agreed with @oli-obk . Please pursue this through the usual RFC-ish channels, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants