@@ -20,6 +20,12 @@ pub struct Config {
20
20
pub window_height : u16 ,
21
21
}
22
22
23
+ #[non_exhaustive]
24
+ pub struct Token ;
25
+
26
+ #[non_exhaustive]
27
+ pub struct Id (pub u64 );
28
+
23
29
#[non_exhaustive]
24
30
pub enum Error {
25
31
Message (String ),
@@ -34,11 +40,13 @@ pub enum Message {
34
40
35
41
// Non-exhaustive structs can be constructed as normal within the defining crate.
36
42
let config = Config { window_width : 640 , window_height : 480 };
43
+ let token = Token ;
44
+ let id = Id (4 );
37
45
38
46
// Non-exhaustive structs can be matched on exhaustively within the defining crate.
39
- if let Config { window_width , window_height } = config {
40
- // ...
41
- }
47
+ let Config { window_width , window_height } = config ;
48
+ let Token = token ;
49
+ let Id ( id_number ) = id ;
42
50
43
51
let error = Error :: Other ;
44
52
let message = Message :: Reaction (3 );
@@ -64,47 +72,68 @@ Non-exhaustive types cannot be constructed outside of the defining crate:
64
72
65
73
- Non-exhaustive variants ([ ` struct ` ] [ struct ] or [ ` enum ` variant] [ enum ] ) cannot be constructed
66
74
with a [ _ StructExpression_ ] \( including with [ functional update syntax] ).
75
+ - The implicitly defined same-named constant of a [ unit-like struct] [ struct ] ,
76
+ or the same-named constructor function of a [ tuple struct] [ struct ] ,
77
+ has a [ visibility] no greater than ` pub(crate) ` .
78
+ That is, if the struct’s visibility is ` pub ` , then the constant or constructor’s visibility
79
+ is ` pub(crate) ` , and otherwise the visibility of the two items is the same
80
+ (as is the case without ` #[non_exhaustive] ` ).
67
81
- [ ` enum ` ] [ enum ] instances can be constructed.
68
82
83
+ The following examples of construction do not compile when outside the defining crate:
84
+
69
85
<!-- ignore: requires external crates -->
70
86
``` 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};
87
+ // These are types defined in an upstream crate that have been annotated as
88
+ // `#[non_exhaustive]`.
89
+ use upstream::{Config, Token, Id, Error, Message};
74
90
75
- // Cannot construct an instance of `Config`, if new fields were added in
91
+ // Cannot construct an instance of `Config`; if new fields were added in
76
92
// a new version of `upstream` then this would fail to compile, so it is
77
93
// disallowed.
78
94
let config = Config { window_width: 640, window_height: 480 };
79
95
80
- // Can construct an instance of `Error`, new variants being introduced would
96
+ // Cannot construct an instance of `Token`; if new fields were added, then
97
+ // it would not be a unit-like struct any more, so the same-named constant
98
+ // created by it being a unit-like struct is not public outside the crate;
99
+ // this code fails to compile.
100
+ let token = Token;
101
+
102
+ // Cannot construct an instance of `Id`; if new fields were added, then
103
+ // its constructor function signature would change, so its constructor
104
+ // function is not public outside the crate; this code fails to compile.
105
+ let id = Id(5);
106
+
107
+ // Can construct an instance of `Error`; new variants being introduced would
81
108
// not result in this failing to compile.
82
109
let error = Error::Message("foo".to_string());
83
110
84
- // Cannot construct an instance of `Message::Send` or `Message::Reaction`,
111
+ // Cannot construct an instance of `Message::Send` or `Message::Reaction`;
85
112
// if new fields were added in a new version of `upstream` then this would
86
113
// fail to compile, so it is disallowed.
87
114
let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), };
88
115
let message = Message::Reaction(0);
89
116
90
- // Cannot construct an instance of `Message::Quit`, if this were converted to
117
+ // Cannot construct an instance of `Message::Quit`; if this were converted to
91
118
// a tuple-variant `upstream` then this would fail to compile.
92
119
let message = Message::Quit;
93
120
```
94
121
95
122
There are limitations when matching on non-exhaustive types outside of the defining crate:
96
123
97
124
- 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) )` .
125
+ a [ _ StructPattern_ ] must be used which must include a ` .. ` . A tuple variant's constructor's
126
+ [ visibility ] is reduced to be no greater than ` pub(crate) ` .
100
127
- When pattern matching on a non-exhaustive [ ` enum ` ] [ enum ] , matching on a variant does not
101
128
contribute towards the exhaustiveness of the arms.
102
129
130
+ The following examples of matching do not compile when outside the defining crate:
131
+
103
132
<!-- ignore: requires external crates -->
104
133
``` 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};
134
+ // These are types defined in an upstream crate that have been annotated as
135
+ // `#[non_exhaustive]`.
136
+ use upstream::{Config, Token, Id, Error, Message};
108
137
109
138
// Cannot match on a non-exhaustive enum without including a wildcard arm.
110
139
match error {
@@ -118,6 +147,13 @@ if let Ok(Config { window_width, window_height }) = config {
118
147
// would compile with: `..`
119
148
}
120
149
150
+ // Cannot match a non-exhaustive unit-like or tuple struct except by using
151
+ // braced struct syntax with a wildcard.
152
+ // This would compile as `let Token { .. } = token;`
153
+ let Token = token;
154
+ // This would compile as `let Id { 0: id_number, .. } = id;`
155
+ let Id(id_number) = id;
156
+
121
157
match message {
122
158
// Cannot match on a non-exhaustive struct enum variant without including a wildcard.
123
159
Message::Send { from, to, contents } => { },
@@ -147,3 +183,4 @@ Non-exhaustive types are always considered inhabited in downstream crates.
147
183
[ enum ] : ../items/enumerations.md
148
184
[ functional update syntax ] : ../expressions/struct-expr.md#functional-update-syntax
149
185
[ struct ] : ../items/structs.md
186
+ [ visibility ] : ../visibility-and-privacy.md
0 commit comments