New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stabilize min_exhaustive_patterns
#122792
base: master
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment has been minimized.
This comment has been minimized.
86b2747
to
3a7fd6c
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
98f42a7
to
be31f20
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
4c3c0fc
to
ca10919
Compare
This comment has been minimized.
This comment has been minimized.
ca10919
to
b86a6f8
Compare
Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 Some changes occurred in compiler/rustc_codegen_gcc Some changes occurred in src/tools/clippy cc @rust-lang/clippy The Miri subtree was changed cc @rust-lang/miri |
Note that this feature *does* consider (some) structs with an uninhabited field as uninhabited, see the PR description. There seems to be a misunderstanding?
Also crucially, "by value" excludes the contents of unions.
|
Thank you, @RalfJung, you're right that I misread it. Updated my FCP text to include not- |
Quick thought, clippy nowadays takes |
I didn't write it explicitly but arrays and tuples can also be empty, in the expected way. I'll add it to the OP. |
For arrays I hope that |
b86a6f8
to
cb625d1
Compare
To my own shock I did not find a test for that :') There's one now. |
This comment has been minimized.
This comment has been minimized.
696076a
to
b7198f2
Compare
☔ The latest upstream changes (presumably #122225) made this pull request unmergeable. Please resolve the merge conflicts. |
b7198f2
to
8b91d64
Compare
This comment has been minimized.
This comment has been minimized.
8b91d64
to
8a5d6b4
Compare
tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff
Show resolved
Hide resolved
8a5d6b4
to
22b985d
Compare
I stumbled upon #108993 which changes how we compute inhabitedness. If I follow correctly, this would mean we don't look into inferred types to determine inhabitedness. So the following, which works today (play), would error instead: #![feature(min_exhaustive_patterns)]
#![allow(unused)]
fn infer<F: FnOnce() -> R, R>(_: Result<bool, R>) {}
enum Void {}
fn with_void() {
let mut x = Ok(true);
match x {
Ok(_) => {}
}
infer::<fn() -> Void, _>(x)
} Hence #108993 becomes a breaking change. We thus need to decide whether to accept #108993 before we stabilize |
Would it make sense to put #108993 under this feature gate? |
☔ The latest upstream changes (presumably #123762) made this pull request unmergeable. Please resolve the merge conflicts. |
Alright, having chatted with @cjgillot and @WaffleLapkin I no longer think it would make sense for exhaustiveness to infer less than it does today. Normalization is important to patterns behaving consistently. My concern is resolved and we don't need to wait for #108993. |
Stabilisation report
I propose we stabilize the
min_exhaustive_patterns
language feature.With this feature, patterns of empty types are considered unreachable when matched by-value. This allows:
This is a subset of the long-unstable
exhaustive_patterns
feature. That feature is blocked because omitting empty patterns is tricky when not matched by-value. This PR stabilizes the by-value case, which is not tricky.The not-by-value cases (behind references, pointers, and unions) stay as they are today, e.g.
The consequence on existing code is some extra "unreachable pattern" warnings. This is fully backwards-compatible.
Comparison with today's rust
This proposal only affects match checking of empty types (i.e. types with no valid values). Non-empty types behave the same with or without this feature. Note that everything below is phrased in terms of
match
but applies equallly toif let
and other pattern-matching expressions.To be precise, a visibly empty type is:
!
;#[non_exhaustive]
annotation);[T; N]
withN != 0
andT
visibly empty;(An extra change was proposed below: that we ignore #[non_exhaustive] for structs since adding fields cannot turn an empty struct into a non-empty one)
For normal types, exhaustiveness checking requires that we list all variants (or use a wildcard). For empty types it's more subtle: in some cases we require a
_
pattern even though there are no valid values that can match it. This is where the difference lies regarding this feature.Today's rust
Under today's rust, a
_
is required for all empty types, except specifically: if the matched expression is of type!
(the never type) orEmptyEnum
(whereEmptyEnum
is an enum with no variants), then the_
is not required.After this PR
After this PR, a pattern of an empty type can be omitted if (and only if):
!
orEmptyEnum
(like before);In all other cases, a
_
is required to match on an empty type.Documentation
The reference does not say anything specific about exhaustiveness checking, hence there is nothing to update there. The nomicon does, I opened rust-lang/nomicon#445 to reflect the changes.
Tests
The relevant tests are in
tests/ui/pattern/usefulness/empty-types.rs
.Unresolved Questions
None that I know of.