@@ -20,6 +20,12 @@ pub struct Config {
2020 pub window_height : u16 ,
2121}
2222
23+ #[non_exhaustive]
24+ pub struct Token ;
25+
26+ #[non_exhaustive]
27+ pub struct Id (pub u64 );
28+
2329#[non_exhaustive]
2430pub enum Error {
2531 Message (String ),
@@ -34,11 +40,13 @@ pub enum Message {
3440
3541// Non-exhaustive structs can be constructed as normal within the defining crate.
3642let config = Config { window_width : 640 , window_height : 480 };
43+ let token = Token ;
44+ let id = Id (4 );
3745
3846// 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 ;
4250
4351let error = Error :: Other ;
4452let message = Message :: Reaction (3 );
@@ -64,30 +72,47 @@ Non-exhaustive types cannot be constructed outside of the defining crate:
6472
6573- Non-exhaustive variants ([ ` struct ` ] [ struct ] or [ ` enum ` variant] [ enum ] ) cannot be constructed
6674 with a [ _ StructExpression_ ] \( including with [ functional update syntax] ).
75+ - The visibility of the same-named constant of a [ unit-like struct] [ struct ]
76+ is lowered to ` min($vis, pub(crate)) ` .
77+ - The visibility of the same-named constructor function of a [ tuple struct] [ struct ]
78+ is lowered to ` min($vis, pub(crate)) ` .
6779- [ ` enum ` ] [ enum ] instances can be constructed.
6880
81+ The following examples of construction do not compile when outside the defining crate:
82+
6983<!-- ignore: requires external crates -->
7084``` 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};
85+ // These are types defined in an upstream crate that have been annotated as
86+ // `#[non_exhaustive]`.
87+ use upstream::{Config, Token, Id, Error, Message};
7488
75- // Cannot construct an instance of `Config`, if new fields were added in
89+ // Cannot construct an instance of `Config`; if new fields were added in
7690// a new version of `upstream` then this would fail to compile, so it is
7791// disallowed.
7892let config = Config { window_width: 640, window_height: 480 };
7993
80- // Can construct an instance of `Error`, new variants being introduced would
94+ // Cannot construct an instance of `Token`; if new fields were added, then
95+ // it would not be a unit-like struct any more, so the same-named constant
96+ // created by it being a unit-like struct is not public outside the crate;
97+ // this code fails to compile.
98+ let token = Token;
99+
100+ // Cannot construct an instance of `Id`; if new fields were added, then
101+ // its constructor function signature would change, so its constructor
102+ // function is not public outside the crate; this code fails to compile.
103+ let id = Id(5);
104+
105+ // Can construct an instance of `Error`; new variants being introduced would
81106// not result in this failing to compile.
82107let error = Error::Message("foo".to_string());
83108
84- // Cannot construct an instance of `Message::Send` or `Message::Reaction`,
109+ // Cannot construct an instance of `Message::Send` or `Message::Reaction`;
85110// if new fields were added in a new version of `upstream` then this would
86111// fail to compile, so it is disallowed.
87112let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), };
88113let message = Message::Reaction(0);
89114
90- // Cannot construct an instance of `Message::Quit`, if this were converted to
115+ // Cannot construct an instance of `Message::Quit`; if this were converted to
91116// a tuple-variant `upstream` then this would fail to compile.
92117let message = Message::Quit;
93118```
@@ -100,11 +125,13 @@ There are limitations when matching on non-exhaustive types outside of the defin
100125- When pattern matching on a non-exhaustive [ ` enum ` ] [ enum ] , matching on a variant does not
101126 contribute towards the exhaustiveness of the arms.
102127
128+ The following examples of matching do not compile when outside the defining crate:
129+
103130<!-- ignore: requires external crates -->
104131``` 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};
132+ // These are types defined in an upstream crate that have been annotated as
133+ // `#[non_exhaustive]`.
134+ use upstream::{Config, Token, Id, Error, Message};
108135
109136// Cannot match on a non-exhaustive enum without including a wildcard arm.
110137match error {
@@ -118,6 +145,13 @@ if let Ok(Config { window_width, window_height }) = config {
118145 // would compile with: `..`
119146}
120147
148+ // Cannot match a non-exhaustive unit-like or tuple struct except by using
149+ // braced struct syntax with a wildcard.
150+ // This would compile as `let Token { .. } = token;`
151+ let Token = token;
152+ // This would compile as `let Id { 0: id_number, .. } = id;`
153+ let Id(id_number) = id;
154+
121155match message {
122156 // Cannot match on a non-exhaustive struct enum variant without including a wildcard.
123157 Message::Send { from, to, contents } => { },
0 commit comments