Skip to content
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

Make min_exhaustive_patterns match exhaustive_patterns better #120775

Merged
merged 2 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
i == variant_index || {
self.tcx.features().exhaustive_patterns
(self.tcx.features().exhaustive_patterns
|| self.tcx.features().min_exhaustive_patterns)
&& !v
.inhabited_predicate(self.tcx, adt_def)
.instantiate(self.tcx, args)
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {

// Emit an extra note if the first uncovered witness would be uninhabited
// if we disregard visibility.
let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns
let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns
|| self.tcx.features().min_exhaustive_patterns)
&& let Some(witness_1) = witnesses.get(0)
&& let ty::Adt(adt, args) = witness_1.ty().kind()
&& adt.is_enum()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/multivariant.rs:7:46
|
LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information
= note: `#[warn(incomplete_features)]` on by default

warning: 1 warning emitted

Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Test precise capture of a multi-variant enum (when remaining variants are
// visibly uninhabited).
// revisions: min_exhaustive_patterns exhaustive_patterns
// edition:2021
// run-pass
#![feature(exhaustive_patterns)]
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete
#![feature(never_type)]

pub fn main() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
--> $DIR/always-inhabited-union-ref.rs:23:11
--> $DIR/always-inhabited-union-ref.rs:26:11
|
LL | match uninhab_ref() {
| ^^^^^^^^^^^^^
Expand All @@ -14,13 +14,13 @@ LL + }
|

error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
--> $DIR/always-inhabited-union-ref.rs:27:11
--> $DIR/always-inhabited-union-ref.rs:30:11
|
LL | match uninhab_union() {
| ^^^^^^^^^^^^^^^
|
note: `Foo` defined here
--> $DIR/always-inhabited-union-ref.rs:10:11
--> $DIR/always-inhabited-union-ref.rs:13:11
|
LL | pub union Foo {
| ^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/always-inhabited-union-ref.rs:7:46
|
LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0004]: non-exhaustive patterns: type `&!` is non-empty
--> $DIR/always-inhabited-union-ref.rs:26:11
|
LL | match uninhab_ref() {
| ^^^^^^^^^^^^^
|
= note: the matched value is of type `&!`
= note: references are always considered inhabited
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match uninhab_ref() {
LL + _ => todo!(),
LL + }
|

error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
--> $DIR/always-inhabited-union-ref.rs:30:11
|
LL | match uninhab_union() {
| ^^^^^^^^^^^^^^^
|
note: `Foo` defined here
--> $DIR/always-inhabited-union-ref.rs:13:11
|
LL | pub union Foo {
| ^^^
= note: the matched value is of type `Foo`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match uninhab_union() {
LL + _ => todo!(),
LL + }
|

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0004`.
7 changes: 5 additions & 2 deletions tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// revisions: min_exhaustive_patterns exhaustive_patterns

// The precise semantics of inhabitedness with respect to unions and references is currently
// undecided. This test file currently checks a conservative choice.

#![feature(exhaustive_patterns)]
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete
#![feature(never_type)]

#![allow(dead_code)]
#![allow(unreachable_code)]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
--> $DIR/match-privately-empty.rs:13:11
--> $DIR/match-privately-empty.rs:16:11
|
LL | match private::DATA {
| ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
Expand All @@ -12,7 +12,7 @@ note: `Option<Private>` defined here
= note: the matched value is of type `Option<Private>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ }) => {},
LL ~ Some(private::Private { misc: false, .. }) => {},
LL + Some(Private { misc: true, .. }) => todo!()
|

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/match-privately-empty.rs:3:46
|
LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
--> $DIR/match-privately-empty.rs:16:11
|
LL | match private::DATA {
| ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
|
note: `Option<Private>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<Private>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Some(private::Private { misc: false, .. }) => {},
LL + Some(Private { misc: true, .. }) => todo!()
|

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0004`.
12 changes: 6 additions & 6 deletions tests/ui/pattern/usefulness/match-privately-empty.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// revisions: min_exhaustive_patterns exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete
#![feature(never_type)]
#![feature(exhaustive_patterns)]

mod private {
pub struct Private {
Expand All @@ -11,11 +14,8 @@ mod private {

fn main() {
match private::DATA {
//~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
//~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
None => {}
Some(private::Private {
misc: false,
..
}) => {}
Some(private::Private { misc: false, .. }) => {}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/slice_of_empty.rs:18:11
--> $DIR/slice_of_empty.rs:22:11
|
LL | match nevers {
| ^^^^^^ pattern `&[]` not covered
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/slice_of_empty.rs:3:46
|
LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/slice_of_empty.rs:11:11
|
LL | match nevers {
| ^^^^^^ pattern `&[_, ..]` not covered
|
= note: the matched value is of type `&[!]`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ &[] => (),
LL ~ &[_, ..] => todo!(),
|

error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
--> $DIR/slice_of_empty.rs:22:11
|
LL | match nevers {
| ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered
|
= note: the matched value is of type `&[!]`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
LL ~ &[_] => (),
LL ~ &[] | &[_, _, ..] => todo!(),
|

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0004`.
9 changes: 7 additions & 2 deletions tests/ui/pattern/usefulness/slice_of_empty.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// revisions: min_exhaustive_patterns exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![deny(unreachable_patterns)]

fn main() {}

fn foo(nevers: &[!]) {
match nevers {
//[min_exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered
&[] => (),
};

Expand All @@ -16,7 +20,8 @@ fn foo(nevers: &[!]) {
};

match nevers {
//~^ ERROR non-exhaustive patterns: `&[]` not covered
//[exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[]` not covered
//[min_exhaustive_patterns]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
&[_] => (),
};
}
4 changes: 2 additions & 2 deletions tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//[pass] check-pass
//[fail] check-fail
#![feature(never_patterns)]
#![feature(exhaustive_patterns)]
#![feature(min_exhaustive_patterns)]
#![allow(incomplete_features)]

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -107,7 +107,7 @@ fn never_pattern_typeck_pass(void: Void) {
}
match (&[] as &[Void]) {
[] => {}
[!],
[!, ..],
}
// Accept on a composite empty type.
match None::<&(u32, Void)> {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//[normal] check-pass
#![feature(never_patterns)]
#![allow(incomplete_features)]
#![cfg_attr(exh_pats, feature(exhaustive_patterns))]
#![cfg_attr(exh_pats, feature(min_exhaustive_patterns))]
#![allow(dead_code, unreachable_code)]
#![deny(unreachable_patterns)]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0005]: refutable pattern in local binding
--> $DIR/uninhabited-irrefutable.rs:29:9
--> $DIR/uninhabited-irrefutable.rs:32:9
|
LL | let Foo::D(_y, _z) = x;
| ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Foo` defined here
--> $DIR/uninhabited-irrefutable.rs:18:6
--> $DIR/uninhabited-irrefutable.rs:21:6
|
LL | enum Foo {
| ^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error[E0005]: refutable pattern in local binding
--> $DIR/uninhabited-irrefutable.rs:32:9
|
LL | let Foo::D(_y, _z) = x;
| ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Foo` defined here
--> $DIR/uninhabited-irrefutable.rs:21:6
|
LL | enum Foo {
| ^^^
LL |
LL | A(foo::SecretlyEmpty),
| - not covered
= note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
= note: the matched value is of type `Foo`
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Foo::D(_y, _z) = x else { todo!() };
| ++++++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0005`.
5 changes: 4 additions & 1 deletion tests/ui/uninhabited/uninhabited-irrefutable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// revisions: min_exhaustive_patterns exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![cfg_attr(min_exhaustive_patterns, allow(incomplete_features))]
#![feature(never_type)]
#![feature(exhaustive_patterns)]

mod foo {
pub struct SecretlyEmpty {
Expand Down
Loading