Using non-exhaustive enums in one crate prevents codes in other crates from listing all the possible matches in a match expression. It forces developers to use wildcards and thereby making the match expression non-exhaustive. By having a non-exhaustive match expression, it future-proofs our codes. Note that it has no effect when we use it in the same crate. For our example, we have two projects wherein one uses the other.
Future-Proof Project
This crate does not have dependencies and only has a single public enum.
Cargo.toml
1 2 3 4 5 6 7 | [package] name = "rust1_40_lib" version = "0.1.0" authors = ["Karl San Gabriel"] edition = "2018" [dependencies] |
lib.rs with Non-Exhaustive Enum
The Countries enum contains six items. It uses two metadata. The first makes it printable; while the second makes it non-exhaustive enum using #[non_exhaustive]
1 2 3 | #[derive(Debug)] #[non_exhaustive] pub enum Countries { PHILIPPINES, MALAYSIA, SINGAPORE, INDONESIA, THAILAND, VIETNAM } |
Build it to make sure there are no errors.
Project With Non-Exhaustive Match Expression
Cargo.toml
This crate uses the abovementioned crate.
1 2 3 4 5 6 7 8 9 | [package] name = "rust1_40features" version = "0.1.0" authors = ["Karl San Gabriel"] edition = "2018" [dependencies] # Change path accordingly countrylib={version="0.1.0", path = "..\\rust\\countrylib" } |
main.rs
1 2 3 4 5 6 7 8 9 10 11 12 | extern crate countrylib; use countrylib::Countries; fn main() { let home = Countries::THAILAND; match home { Countries::PHILIPPINES | Countries::MALAYSIA | Countries::INDONESIA | Countries::SINGAPORE | Countries::THAILAND | Countries::VIETNAM => { println!("GROUP 1: {:?}", home) }, } } |
When we build this project, we will get the following:
To fix this error, modify the codes as follow. In the new codes, the matching expression is no longer exhaustive for the non-exhaustive enum. The codes will remain unchanged even if there are new enum items.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | extern crate countrylib; use countrylib::Countries; fn main() { let home = Countries::THAILAND; match home { Countries::PHILIPPINES | Countries::MALAYSIA | Countries::INDONESIA | Countries::SINGAPORE | Countries::THAILAND | Countries::VIETNAM => { println!("GROUP 1: {:?}", home) }, _ => { println!("OTHER GROUP: {:?}", home) } } } |
We tested the codes with Rust 1.40.0. For more information, please visit the non-exhaustive attribute.
Non-Exhaustive Struts
The non-exhaustive attribute can also make Structs non-exhaustive.