]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/attributes/type_system.md
New upstream version 1.41.1+dfsg1
[rustc.git] / src / doc / reference / src / attributes / type_system.md
CommitLineData
e74abb32
XL
1# Type system attributes
2
3The following [attributes] are used for changing how a type can be used.
4
5## The `non_exhaustive` attribute
6
7The *`non_exhaustive` attribute* indicates that a type or variant may have
8more fields or variants added in the future. It can be applied to
9[`struct`s][struct], [`enum`s][enum], and `enum` variants.
10
11The `non_exhaustive` attribute uses the [_MetaWord_] syntax and thus does not
12take any inputs.
13
14Within the defining crate, `non_exhaustive` has no effect.
15
16```rust
17#[non_exhaustive]
18pub struct Config {
19 pub window_width: u16,
20 pub window_height: u16,
21}
22
23#[non_exhaustive]
24pub enum Error {
25 Message(String),
26 Other,
27}
28
29pub enum Message {
30 #[non_exhaustive] Send { from: u32, to: u32, contents: String },
31 #[non_exhaustive] Reaction(u32),
32 #[non_exhaustive] Quit,
33}
34
35// Non-exhaustive structs can be constructed as normal within the defining crate.
36let config = Config { window_width: 640, window_height: 480 };
37
38// Non-exhaustive structs can be matched on exhaustively within the defining crate.
39if let Config { window_width, window_height } = config {
40 // ...
41}
42
43let error = Error::Other;
44let message = Message::Reaction(3);
45
46// Non-exhaustive enums can be matched on exhaustively within the defining crate.
47match error {
48 Error::Message(ref s) => { },
49 Error::Other => { },
50}
51
52match message {
53 // Non-exhaustive variants can be matched on exhaustively within the defining crate.
54 Message::Send { from, to, contents } => { },
55 Message::Reaction(id) => { },
56 Message::Quit => { },
57}
58```
59
60Outside of the defining crate, types annotated with `non_exhaustive` have limitations that
61preserve backwards compatibility when new fields or variants are added.
62
63Non-exhaustive types cannot be constructed outside of the defining crate:
64
65- Non-exhaustive variants ([`struct`][struct] or [`enum` variant][enum]) cannot be constructed
66 with a [_StructExpression_] \(including with [functional update syntax]).
67- [`enum`][enum] instances can be constructed in an [_EnumerationVariantExpression_].
68
60c5eb7d
XL
69<!-- ignore: requires external crates -->
70```rust,ignore
e74abb32
XL
71// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
72// annotated as `#[non_exhaustive]`.
73use upstream::{Config, Error, Message};
74
75// Cannot construct an instance of `Config`, if new fields were added in
76// a new version of `upstream` then this would fail to compile, so it is
77// disallowed.
78let config = Config { window_width: 640, window_height: 480 };
79
80// Can construct an instance of `Error`, new variants being introduced would
81// not result in this failing to compile.
82let error = Error::Message("foo".to_string());
83
84// Cannot construct an instance of `Message::Send` or `Message::Reaction`,
85// if new fields were added in a new version of `upstream` then this would
86// fail to compile, so it is disallowed.
87let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), };
88let message = Message::Reaction(0);
89
90// Cannot construct an instance of `Message::Quit`, if this were converted to
91// a tuple-variant `upstream` then this would fail to compile.
92let message = Message::Quit;
93```
94
95There are limitations when matching on non-exhaustive types outside of the defining crate:
96
97- When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]),
98 a [_StructPattern_] must be used which must include a `..`. Tuple variant constructor visibility
99 is lowered to `min($vis, pub(crate))`.
100- When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not
101 contribute towards the exhaustiveness of the arms.
102
60c5eb7d
XL
103<!-- ignore: requires external crates -->
104```rust, ignore
e74abb32
XL
105// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
106// annotated as `#[non_exhaustive]`.
107use upstream::{Config, Error, Message};
108
109// Cannot match on a non-exhaustive enum without including a wildcard arm.
110match error {
111 Error::Message(ref s) => { },
112 Error::Other => { },
113 // would compile with: `_ => {},`
114}
115
116// Cannot match on a non-exhaustive struct without a wildcard.
117if let Ok(Config { window_width, window_height }) = config {
118 // would compile with: `..`
119}
120
121match message {
122 // Cannot match on a non-exhaustive struct enum variant without including a wildcard.
123 Message::Send { from, to, contents } => { },
124 // Cannot match on a non-exhaustive tuple or unit enum variant.
125 Message::Reaction(type) => { },
126 Message::Quit => { },
127}
128```
129
130Non-exhaustive types are always considered inhabited in downstream crates.
131
132[_EnumerationVariantExpression_]: ../expressions/enum-variant-expr.md
133[_MetaWord_]: ../attributes.md#meta-item-attribute-syntax
134[_StructExpression_]: ../expressions/struct-expr.md
135[_StructPattern_]: ../patterns.md#struct-patterns
136[_TupleStructPattern_]: ../patterns.md#tuple-struct-patterns
137[`if let`]: ../expressions/if-expr.md#if-let-expressions
138[`match`]: ../expressions/match-expr.md
139[attributes]: ../attributes.md
140[enum]: ../items/enumerations.md
141[functional update syntax]: ../expressions/struct-expr.md#functional-update-syntax
142[struct]: ../items/structs.md