Hello everyone, recently I have come across a feature in Rust, known as non_exhaustive
. It was introduced in Rust 1.40.0 . This attribute prevents source code-breaking changes in projects downstream. enums
can be non-exhaustive or exhaustive, depending upon their needs. A non-exhaustive enum indicates that this enum may get new value in the future. By adding #[non_exhaustive]
attribute, we can create a non-exhaustive enum which forces downstream crates to use wildcard pattern (_
) in the match expression and make it non-exhaustive. Otherwise, we will get the compilation error.
Let’s see with a simple example.
- Create a project using
cargo new
and define a rust modulemovie_genres
under this project. - Create a file
lib.rs
and add an enum for movie genres with#[non_exhaustive]
attribute.
#[non_exhaustive]
pub enum Genres {
Horror,
Comedy,
Romance,
}
- In main
Cargo.toml
add the dependency.
movie_genres = {version = "0.1.0", path="./movie_genres"}
- Now import
movie_genres
inmain.rs
and start testing.
extern crate movie_genres;
use movie_genres::Genres;
fn main() {
let genres = Genres::Horror;
match genres {
Genres::Horror => println!("Horror Movie!!"),
Genres::Comedy => println!("Comedy Movie!!"),
Genres::Romance => println!("Romance Movie!!"),
}
}
- Now if we hit
cargo run
, we will get a compilation error.

- Now add wildcard arm in match expression.
match genres {
Genres::Horror => println!("Horror Movie!!"),
Genres::Comedy => println!("Comedy Movie!!"),
Genres::Romance => println!("Romance Movie!!"),
_ => println!("Other movie category"),
}
- Add hit
cargo run
.

You can find full example here https://github.com/knoldus/non_exhaustive_rust_template.
Thanks for reading the blog. If you want to read more content like this? Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7 .

Be careful about deciding to use this. A compilation error is often much better than a runtime error! Exhaustive enums are the default for a reason.
I agree David. However there are some scenarios where we have to use non exhaustive Enum. Most common use case is Rust error types. Please find more details here https://rust-lang.github.io/rfcs/2008-non-exhaustive.html#enums
I see it would be useful for enums generated by bindgen, where handling wildcard is mandatory to prevent panics for unknown values.