]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/attributes/type_system.md
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / doc / reference / src / attributes / type_system.md
1 # Type system attributes
2
3 The following [attributes] are used for changing how a type can be used.
4
5 ## The `non_exhaustive` attribute
6
7 The *`non_exhaustive` attribute* indicates that a type or variant may have
8 more fields or variants added in the future. It can be applied to
9 [`struct`s][struct], [`enum`s][enum], and `enum` variants.
10
11 The `non_exhaustive` attribute uses the [_MetaWord_] syntax and thus does not
12 take any inputs.
13
14 Within the defining crate, `non_exhaustive` has no effect.
15
16 ```rust
17 #[non_exhaustive]
18 pub struct Config {
19 pub window_width: u16,
20 pub window_height: u16,
21 }
22
23 #[non_exhaustive]
24 pub enum Error {
25 Message(String),
26 Other,
27 }
28
29 pub 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.
36 let config = Config { window_width: 640, window_height: 480 };
37
38 // Non-exhaustive structs can be matched on exhaustively within the defining crate.
39 if let Config { window_width, window_height } = config {
40 // ...
41 }
42
43 let error = Error::Other;
44 let message = Message::Reaction(3);
45
46 // Non-exhaustive enums can be matched on exhaustively within the defining crate.
47 match error {
48 Error::Message(ref s) => { },
49 Error::Other => { },
50 }
51
52 match 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
60 Outside of the defining crate, types annotated with `non_exhaustive` have limitations that
61 preserve backwards compatibility when new fields or variants are added.
62
63 Non-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.
68
69 <!-- ignore: requires external crates -->
70 ```rust,ignore
71 // `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
72 // annotated as `#[non_exhaustive]`.
73 use 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.
78 let 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.
82 let 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.
87 let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), };
88 let 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.
92 let message = Message::Quit;
93 ```
94
95 There 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
103 <!-- ignore: requires external crates -->
104 ```rust, ignore
105 // `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
106 // annotated as `#[non_exhaustive]`.
107 use upstream::{Config, Error, Message};
108
109 // Cannot match on a non-exhaustive enum without including a wildcard arm.
110 match 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.
117 if let Ok(Config { window_width, window_height }) = config {
118 // would compile with: `..`
119 }
120
121 match 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
130 Non-exhaustive types are always considered inhabited in downstream crates.
131
132 [_MetaWord_]: ../attributes.md#meta-item-attribute-syntax
133 [_StructExpression_]: ../expressions/struct-expr.md
134 [_StructPattern_]: ../patterns.md#struct-patterns
135 [_TupleStructPattern_]: ../patterns.md#tuple-struct-patterns
136 [`if let`]: ../expressions/if-expr.md#if-let-expressions
137 [`match`]: ../expressions/match-expr.md
138 [attributes]: ../attributes.md
139 [enum]: ../items/enumerations.md
140 [functional update syntax]: ../expressions/struct-expr.md#functional-update-syntax
141 [struct]: ../items/structs.md