Skip to content

Commit

Permalink
Rollup merge of rust-lang#120775 - Nadrieril:more-min_exh_pats, r=com…
Browse files Browse the repository at this point in the history
…piler-errors

Make `min_exhaustive_patterns` match `exhaustive_patterns` better

Split off from rust-lang#120742.

There remained two edge cases where `min_exhaustive_patterns` wasn't behaving like `exhaustive_patterns`. This fixes them, and tests the feature in a bunch more cases. I essentially went through all uses of `exhaustive_patterns` to see which ones would be interesting to compare between the two features.

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr committed Feb 8, 2024
2 parents abef17d + 4733b1b commit 949e552
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 25 deletions.
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 @@ -270,7 +270,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

0 comments on commit 949e552

Please sign in to comment.