diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 065c93e86a866..14b7fb9ce6fff 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -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) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 1156e8be13e74..692f4511bb807 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -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() diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..b54341f82c794 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr @@ -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 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs index 72652ef60349a..bc2386e5d23d8 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs @@ -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() { diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr rename to tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr index cd5c283f9fd93..553daff2d969d 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr @@ -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() { | ^^^^^^^^^^^^^ @@ -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 { | ^^^ diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a1d8002c64895 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr @@ -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 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`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs index 7d1cac8a442f5..247b7f21f6866 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -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)] diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/match-privately-empty.stderr rename to tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr index d760790dff6fe..708a1511244c2 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr @@ -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 @@ -12,7 +12,7 @@ note: `Option` defined here = note: the matched value is of type `Option` 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!() | diff --git a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a6ce02c0c3c6a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr @@ -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 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` 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` +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`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs index 315eb03d16564..67a9aa2e91614 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.rs +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -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 { @@ -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, .. }) => {} } } diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr similarity index 93% rename from tests/ui/pattern/usefulness/slice_of_empty.stderr rename to tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr index d56360d4cec07..9770f680b2da8 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.stderr +++ b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr @@ -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 diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..3b9e71f50d5ff --- /dev/null +++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr @@ -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 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`. diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs index 3cbd0eba57fd1..5f64dd3fecc9a 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.rs +++ b/tests/ui/pattern/usefulness/slice_of_empty.rs @@ -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 &[] => (), }; @@ -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 &[_] => (), }; } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 31a23fa002c30..72ee4d24bb629 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -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)] @@ -107,7 +107,7 @@ fn never_pattern_typeck_pass(void: Void) { } match (&[] as &[Void]) { [] => {} - [!], + [!, ..], } // Accept on a composite empty type. match None::<&(u32, Void)> { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs index df8e22abf6232..0374cbdbc1fd2 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs @@ -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)] diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr similarity index 91% rename from tests/ui/uninhabited/uninhabited-irrefutable.stderr rename to tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr index 304e738ed2561..c9131a8372ab1 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ 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 @@ -7,7 +7,7 @@ LL | let Foo::D(_y, _z) = x; = 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 { | ^^^ diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..c9131a8372ab1 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr @@ -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`. diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs index cfd60a8d903fa..2ef3b668cb089 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.rs +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -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 {