# 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!