# Stabilization proposal Tracking issue: #44019 Version target: TBD As per [the stabilization guide](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#write-a-stabilization-report), I'd like to propose stabilizing `#[non_exhaustive]`: cc @rust-lang/lang ## What is stabilized The `non_exhaustive` attribute is used to indicate that a type will have more fields/variants added in the future. It can be applied to structs, enums and enum variants. Within the defining crate, types annotated with `non_exhaustive` behave exactly the same as if the type were not annotated with `non_exhaustive`: ```rust,ignore #[non_exhaustive] pub struct Config { pub window_width: u16, pub window_height: u16, } #[non_exhaustive] pub enum Error { Message(String), Other, } pub enum Message { #[non_exhaustive] Send { from: u32, to: u32, contents: String }, #[non_exhaustive] Reaction(u32), #[non_exhaustive] Quit, } // Non-exhaustive structs can be constructed as normal within the defining crate. let config = Config { window_width: 640, window_height: 480 }; // Non-exhaustive structs can be matched on exhaustively within the defining crate. if let Ok(Config { window_width, window_height }) = config { // ... } // Non-exhaustive enums can be matched on exhaustively within the defining crate. match error { Error::Message(ref s) => { }, Error::Other => { }, } match message { // Non-exhaustive variants can be matched on exhaustively within the defining crate. Message::Send { from, to, contents } => { }, Message::Reaction(type) => { }, Message::Quit => { }, } ``` In downstream crates, types annotated with `non_exhaustive` have limitations that preserve backwards compatibility when new fields/variants are added. Non-exhaustive types cannot be constructed in downstream crates: ```rust,ignore // `Config`, `Error` and `Message` are types defined in an upstream crate that have been // annotated as `#[non_exhaustive]`. use upstream::{Config, Error, Message}; // Cannot construct an instance of `Config`, if new fields were added in // a new version of `upstream` then this would fail to compile, so it is // disallowed. let config = Config { window_width: 640, window_height: 480 }; // Can construct an instance of `Error`, new variants being introduced would // not result in this failing to compile. let error = Error::Message("foo".to_string()); // Cannot construct an instance of `Message::Send` or `Message::Reaction`, // if new fields were added in a new version of `upstream` then this would // fail to compile, so it is disallowed. let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), }; let message = Message::Reaction(0); // Cannot construct an instance of `Message::Quit`, if this were converted to // a tuple-variant `upstream` then this would fail to compile. let message = Message::Quit; ``` Non-exhaustive types cannot be used in a `match`/`if let` expression without a wildcard arm: ```rust, ignore // `Config`, `Error` and `Message` are types defined in an upstream crate that have been // annotated as `#[non_exhaustive]`. use upstream::{Config, Error, Message}; // Cannot match on a non-exhaustive enum without including a wildcard arm. match error { Error::Message(ref s) => { }, Error::Other => { }, // would compile with: `_ => {},` } // Cannot match on a non-exhaustive struct without a wildcard. if let Ok(Config { window_width, window_height }) = config { // would compile with: `..` } match message { // Cannot match on a non-exhaustive struct enum variant without including a wildcard. Message::Send { from, to, contents } => { }, // Cannot match on a non-exhaustive tuple or unit enum variant. Message::Reaction(type) => { }, Message::Quit => { }, } ``` Non-exhaustive types are always considered inhabited in downstream crates. ## What is not stabilized N/A ## Divergences from RFC It is not specified in the RFC what the inhabitedness of non-exhaustive types used extern crates should be. Since #60529, non-exhaustive types are always considered inhabited in extern crates. ## Tests The tests are all in [`src/test/ui/rfc-2008-non-exhaustive`](https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2008-non-exhaustive). Here are some of them: * [Enums (Extern Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/enum.rs) * [Enum (Same Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate.rs) * [Structs (Extern Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/struct.rs) * [Structs (Same Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/structs_same_crate.rs) * [Variants (Extern Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/variant.rs) * [Variants (Same Crate)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs) * [Invalid Attribute Locations](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.rs) * [Uninhabited Errors (Extern Crate, Patterns)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs) * [Uninhabited Errors (Same Crate, Patterns)](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs) ## Motivation See [RFC 2008](https://github.com/rust-lang/rfcs/blob/master/text/2008-non-exhaustive.md#motivation). ## History * Was originally proposed in RFC [rust-lang/rfcs#2008](https://github.com/rust-lang/rfcs/pull/2008). * Implemented for enums/structs in #45394 by @davidtwco (reviewed by @nikomatsakis, @petrochenkov, @oli-obk, @arielb1). Merged on Nov 4th 2017. * Attribute prohibited on unions, other incorrect locations in #49345 by @davidtwco (reviewed by @nikomatsakis) Merged on Apr 5th 2018. * Support in rustdoc in #51854 by @davidtwco (reviewed by @QuietMisdreavus, @clarfon, @frewsxcv) Merged on Jul 19th 2018. * Improved in #53721 by @arielb1 (reviewed by @nikomatsakis, @eddyb) Merged on Sep 6th 2018. Fixed #53549. * Implemented for enum variants in #59376 by @davidtwco (reviewed by @petrochenkov, @QuietMisdreavus, @GuillaumeGomez) Merged on March 30th 2019. * Fixed and added tests for uninhabitedness in #60529 by @davidtwco (reviewed by @petrochenkov, @Centril) Merged on May 10th 2019. * Update reference for `#[non_exhaustive]` in rust-lang-nursery/reference#609 by @davidtwco Submitted on May 12th 2019. Not yet merged! * Update book for `#[non_exhaustive]` in rust-lang/book#1955 by @davidtwco Submitted on May 12th 2019. Not yet merged!