Prevent Rest Condition in Rust Match Statement

41 Views Asked by At

I'm working on a rust project that relies heavily on match statements. Rust's exhaustive matching is a big part of the reason that we picked this language to work in, and I'm curious if it's possible to not allow matches against an enum to include a rest condition _ => {} -- rather, we want to ensure that every single match statement matches against every variant of the enum. This is because the enum variants will grow over time as the project undergoes long-term development, and we want to make sure that every variant is always matched against.

For example:

enum MyEnum {
    VariantA,
    VariantB,
    VariantC,
    VariantD,
}

impl MyEnum {
    fn some_method(&self) {
        match self {
            MyEnum::VariantA => todo!(),
            MyEnum::VariantB => todo!(),
            _ => todo!(),  // <-- DON'T ALLOW THIS
        }
    }
}

Currently, we are simply communicating never to use rest conditions like this, but we're wondering if there's a way to enforce this more thoroughly.

I tried to search for information about macros, VSCode extensions, or other ways of checking for/enforcing that no rest conditions are included in match statements, but couldn't find anything. I also couldn't find a clearly-defined name for these conditions -- I call them "rest conditions" but didn't find official rust vocabulary for such cases. Not knowing a more widely-used term might have also hurt my ability to search.

1

There are 1 best solutions below

0
Aleksander Krauze On

Yes. You can enforce that by turning on Clippy's wildcard_enum_match_arm lint. For example following code:

#![deny(clippy::wildcard_enum_match_arm)]

enum MyEnum {
    VariantA,
    VariantB,
    VariantC,
    VariantD,
}

impl MyEnum {
    fn some_method(&self) {
        match self {
            MyEnum::VariantA => todo!(),
            MyEnum::VariantB => todo!(),
            _ => todo!(),  // <-- DON'T ALLOW THIS
        }
    }
}

Will fail cargo clippy check with following error:

error: wildcard match will also match any future added variants
  --> src/lib.rs:15:13
   |
15 |             _ => todo!(),  // <-- DON'T ALLOW THIS
   |             ^ help: try: `MyEnum::VariantC | MyEnum::VariantD`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm
note: the lint level is defined here
  --> src/lib.rs:1:9
   |
1  | #![deny(clippy::wildcard_enum_match_arm)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^