1 # Type system attributes
3 The following [attributes] are used for changing how a type can be used.
5 ## The `non_exhaustive` attribute
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.
11 The `non_exhaustive` attribute uses the [_MetaWord_] syntax and thus does not
14 Within the defining crate, `non_exhaustive` has no effect.
19 pub window_width: u16,
20 pub window_height: u16,
30 #[non_exhaustive] Send { from: u32, to: u32, contents: String },
31 #[non_exhaustive] Reaction(u32),
32 #[non_exhaustive] Quit,
35 // Non-exhaustive structs can be constructed as normal within the defining crate.
36 let config = Config { window_width: 640, window_height: 480 };
38 // Non-exhaustive structs can be matched on exhaustively within the defining crate.
39 if let Config { window_width, window_height } = config {
43 let error = Error::Other;
44 let message = Message::Reaction(3);
46 // Non-exhaustive enums can be matched on exhaustively within the defining crate.
48 Error::Message(ref s) => { },
53 // Non-exhaustive variants can be matched on exhaustively within the defining crate.
54 Message::Send { from, to, contents } => { },
55 Message::Reaction(id) => { },
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.
63 Non-exhaustive types cannot be constructed outside of the defining crate:
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.
69 <!-- ignore: requires external crates -->
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};
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
78 let config = Config { window_width: 640, window_height: 480 };
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());
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);
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;
95 There are limitations when matching on non-exhaustive types outside of the defining crate:
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.
103 <!-- ignore: requires external crates -->
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};
109 // Cannot match on a non-exhaustive enum without including a wildcard arm.
111 Error::Message(ref s) => { },
113 // would compile with: `_ => {},`
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: `..`
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 => { },
130 Non-exhaustive types are always considered inhabited in downstream crates.
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