Skip to content

Commit 004472b

Browse files
committed
Split enum-exhaustiveness into a separate rule
The existing rule was mixing pattern match restrictions with match arm exhaustiveness. Although very closely related, I think they deserve to be split up. This also adds a little clarity about tuple matching.
1 parent f50c66b commit 004472b

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

src/attributes/type_system.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,9 @@ The implicitly defined same-named constant of a [unit-like struct][struct], or t
135135
> ```
136136
137137
r[attributes.type-system.non_exhaustive.match]
138-
There are limitations when matching on non-exhaustive types outside of the defining crate:
138+
When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]) from an external crate, a [StructPattern] must be used which must include a [`..` rest pattern][patterns.rest].
139139
140-
- When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]), a [StructPattern] must be used which must include a `..`. A tuple enum variant's constructor's [visibility] is reduced to be no greater than `pub(crate)`.
141-
- When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not contribute towards the exhaustiveness of the arms.
140+
Because a tuple enum variant's constructor's [visibility] is reduced to be no greater than `pub(crate)`, a [tuple struct pattern][patterns.tuple-struct] cannot be used in a pattern; a [StructPattern] with tuple indexes must be used instead.
142141
143142
> [!EXAMPLE]
144143
> Using the definitions from [above][attributes.type-system.non_exhaustive.intro], the following examples of matching do not compile when outside the defining crate:
@@ -149,13 +148,6 @@ There are limitations when matching on non-exhaustive types outside of the defin
149148
> // `#[non_exhaustive]`.
150149
> use upstream::{Config, Token, Id, Error, Message};
151150
>
152-
> // Cannot match on a non-exhaustive enum without including a wildcard arm.
153-
> match error {
154-
> Error::Message(ref s) => { },
155-
> Error::Other => { },
156-
> // would compile with: `_ => {},`
157-
> }
158-
>
159151
> // Cannot match on a non-exhaustive struct without a wildcard.
160152
> if let Ok(Config { window_width, window_height }) = config {
161153
> // would compile with: `..`
@@ -174,6 +166,24 @@ There are limitations when matching on non-exhaustive types outside of the defin
174166
> // Cannot match on a non-exhaustive tuple or unit enum variant.
175167
> Message::Reaction(type) => { },
176168
> Message::Quit => { },
169+
170+
r[attributes.type-system.non_exhaustive.enum-exhaustiveness]
171+
When using a [`match` expression][expr.match] on a non-exhaustive [`enum`][enum] from an external crate, matching on a variant does not contribute towards the exhaustiveness of the arms. A [`_` wildcard][patterns.wildcard] arm is needed to make the match exhaustive.
172+
173+
> [!EXAMPLE]
174+
> Using the definitions from [above][attributes.type-system.non_exhaustive.intro], the following examples of matching do not compile when outside the defining crate:
175+
>
176+
> <!-- ignore: requires external crates -->
177+
> ```rust, ignore
178+
> // These are types defined in an upstream crate that have been annotated as
179+
> // `#[non_exhaustive]`.
180+
> use upstream::Error;
181+
>
182+
> // Cannot match on a non-exhaustive enum without including a wildcard arm.
183+
> match error { // ERROR: `_` not covered
184+
> Error::Message(ref s) => { },
185+
> Error::Other => { },
186+
> // would compile with: `_ => {},`
177187
> }
178188
> ```
179189

0 commit comments

Comments
 (0)