Rollup merge of #118803 - Nadrieril:min-exhaustive-patterns, r=compiler-errors

Add the `min_exhaustive_patterns` feature gate

## Motivation

Pattern-matching on empty types is tricky around unsafe code. For that reason, current stable rust conservatively requires arms for empty types in all but the simplest case. It has long been the intention to allow omitting empty arms when it's safe to do so. The [`exhaustive_patterns`](https://github.com/rust-lang/rust/issues/51085) feature allows the omission of all empty arms, but hasn't been stabilized because that was deemed dangerous around unsafe code.

## Proposal

This feature aims to stabilize an uncontroversial subset of exhaustive_patterns. Namely: when `min_exhaustive_patterns` is enabled and the data we're matching on is guaranteed to be valid by rust's operational semantics, then we allow empty arms to be omitted. E.g.:

```rust
let x: Result<T, !> = foo();
match x { // ok
    Ok(y) => ...,
}
let Ok(y) = x; // ok
```

If the place is not guaranteed to hold valid data (namely ptr dereferences, ref dereferences (conservatively) and union field accesses), then we keep stable behavior i.e. we (usually) require arms for the empty cases.

```rust
unsafe {
    let ptr: *const Result<u32, !> = ...;
    match *ptr {
        Ok(x) => { ... }
        Err(_) => { ... } // still required
    }
}
let foo: Result<u32, &!> = ...;
match foo {
    Ok(x) => { ... }
    Err(&_) => { ... } // still required because of the dereference
}
unsafe {
    let ptr: *const ! = ...;
    match *ptr {} // already allowed on stable
}
```

Note that we conservatively consider that a valid reference can point to invalid data, hence we don't allow arms of type `&!` and similar cases to be omitted. This could eventually change depending on [opsem decisions](https://github.com/rust-lang/unsafe-code-guidelines/issues/413). Whenever opsem is undecided on a case, we conservatively keep today's stable behavior.

I proposed this behavior in the [`never_patterns`](https://github.com/rust-lang/rust/issues/118155) feature gate but it makes sense on its own and could be stabilized more quickly. The two proposals nicely complement each other.

## Unresolved Questions

Part of the question is whether this requires an RFC. I'd argue this doesn't need one since there is no design question beyond the intent to omit unreachable patterns, but I'm aware the problem can be framed in ways that require design (I'm thinking of the [original never patterns proposal](https://smallcultfollowing.com/babysteps/blog/2018/08/13/never-patterns-exhaustive-matching-and-uninhabited-types-oh-my/), which would frame this behavior as "auto-nevering" happening).

EDIT: I initially proposed a future-compatibility lint as part of this feature, I don't anymore.
This commit is contained in:
Matthias Krüger 2024-01-26 06:36:36 +01:00 committed by GitHub
commit a37fa37281
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 810 additions and 158 deletions

View File

@ -516,6 +516,9 @@ declare_features! (
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
/// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
/// unambiguously sound.
(incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
/// A minimal, sound subset of specialization intended to be used by the
/// standard library until the soundness issues with specialization
/// are fixed.

View File

@ -95,6 +95,7 @@ pub trait TypeCx: Sized + fmt::Debug {
type PatData: Clone;
fn is_exhaustive_patterns_feature_on(&self) -> bool;
fn is_min_exhaustive_patterns_feature_on(&self) -> bool;
/// The number of fields for this constructor.
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;

View File

@ -181,7 +181,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
// `field.ty()` doesn't normalize after substituting.
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
|| cx.tcx.features().min_exhaustive_patterns)
&& cx.is_uninhabited(ty);
if is_uninhabited && (!is_visible || is_non_exhaustive) {
None
@ -863,6 +865,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
fn is_exhaustive_patterns_feature_on(&self) -> bool {
self.tcx.features().exhaustive_patterns
}
fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
self.tcx.features().min_exhaustive_patterns
}
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
self.ctor_arity(ctor, *ty)

View File

@ -548,11 +548,12 @@
//! [`ValidityConstraint::specialize`].
//!
//! Having said all that, in practice we don't fully follow what's been presented in this section.
//! Under `exhaustive_patterns`, we allow omitting empty arms even in `!known_valid` places, for
//! backwards-compatibility until we have a better alternative. Without `exhaustive_patterns`, we
//! mostly treat empty types as inhabited, except specifically a non-nested `!` or empty enum. In
//! this specific case we also allow the empty match regardless of place validity, for
//! backwards-compatibility. Hopefully we can eventually deprecate this.
//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or
//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart
//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow
//! omitting patterns in the cases described above. There's a final detail: in the toplevel
//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking
//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior.
//!
//!
//!
@ -1442,10 +1443,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
let is_toplevel_exception =
is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
// Whether empty patterns can be omitted for exhaustiveness.
let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
// Whether empty patterns are counted as useful or not.
let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms;
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
let empty_arms_are_unreachable = place_validity.is_known_valid()
&& (is_toplevel_exception
|| mcx.tycx.is_exhaustive_patterns_feature_on()
|| mcx.tycx.is_min_exhaustive_patterns_feature_on());
// Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
// toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
let can_omit_empty_arms = empty_arms_are_unreachable
|| is_toplevel_exception
|| mcx.tycx.is_exhaustive_patterns_feature_on();
// Analyze the constructors present in this column.
let ctors = matrix.heads().map(|p| p.ctor());

View File

@ -1029,6 +1029,7 @@ symbols! {
min_const_fn,
min_const_generics,
min_const_unsafe_fn,
min_exhaustive_patterns,
min_specialization,
min_type_alias_impl_trait,
minnumf32,

View File

@ -1,23 +1,23 @@
error: unreachable pattern
--> $DIR/empty-types.rs:47:9
--> $DIR/empty-types.rs:50:9
|
LL | _ => {}
| ^
|
note: the lint level is defined here
--> $DIR/empty-types.rs:13:9
--> $DIR/empty-types.rs:16:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:50:9
--> $DIR/empty-types.rs:53:9
|
LL | _x => {}
| ^^
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
--> $DIR/empty-types.rs:54:11
--> $DIR/empty-types.rs:57:11
|
LL | match ref_never {}
| ^^^^^^^^^
@ -32,31 +32,31 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:69:9
--> $DIR/empty-types.rs:72:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:76:9
--> $DIR/empty-types.rs:79:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:79:9
--> $DIR/empty-types.rs:82:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:83:9
--> $DIR/empty-types.rs:86:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
--> $DIR/empty-types.rs:87:11
--> $DIR/empty-types.rs:90:11
|
LL | match res_u32_never {}
| ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@ -75,19 +75,19 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:95:9
--> $DIR/empty-types.rs:98:9
|
LL | Err(_) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:100:9
--> $DIR/empty-types.rs:103:9
|
LL | Err(_) => {}
| ^^^^^^
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
--> $DIR/empty-types.rs:97:11
--> $DIR/empty-types.rs:100:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@ -105,7 +105,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!()
|
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:104:9
--> $DIR/empty-types.rs:107:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` not covered
@ -119,17 +119,11 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
| ++++++++++++++++
error: unreachable pattern
--> $DIR/empty-types.rs:115:9
--> $DIR/empty-types.rs:118:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:119:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:122:9
|
@ -137,103 +131,109 @@ LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:123:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:126:9
--> $DIR/empty-types.rs:125:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:127:9
--> $DIR/empty-types.rs:126:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:129:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:130:9
|
LL | Err(_) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:136:13
--> $DIR/empty-types.rs:139:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:139:13
--> $DIR/empty-types.rs:142:13
|
LL | _ if false => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:148:13
--> $DIR/empty-types.rs:151:13
|
LL | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:152:13
--> $DIR/empty-types.rs:155:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:204:13
--> $DIR/empty-types.rs:207:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:209:13
--> $DIR/empty-types.rs:212:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:214:13
--> $DIR/empty-types.rs:217:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:219:13
--> $DIR/empty-types.rs:222:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:225:13
--> $DIR/empty-types.rs:228:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:284:9
--> $DIR/empty-types.rs:287:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:287:9
--> $DIR/empty-types.rs:290:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:290:9
--> $DIR/empty-types.rs:293:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:291:9
--> $DIR/empty-types.rs:294:9
|
LL | Err(_) => {}
| ^^^^^^
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:323:11
--> $DIR/empty-types.rs:326:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@ -247,7 +247,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/empty-types.rs:334:11
--> $DIR/empty-types.rs:337:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@ -260,7 +260,7 @@ LL + &[] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/empty-types.rs:347:11
--> $DIR/empty-types.rs:350:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@ -274,7 +274,7 @@ LL + &[] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:353:11
--> $DIR/empty-types.rs:356:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@ -288,25 +288,25 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:363:9
--> $DIR/empty-types.rs:366:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:366:9
--> $DIR/empty-types.rs:369:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:369:9
--> $DIR/empty-types.rs:372:9
|
LL | [_, ..] => {}
| ^^^^^^^
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:383:11
--> $DIR/empty-types.rs:386:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@ -320,13 +320,13 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:390:9
--> $DIR/empty-types.rs:393:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:392:11
--> $DIR/empty-types.rs:395:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@ -340,49 +340,49 @@ LL + [] => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:411:9
--> $DIR/empty-types.rs:414:9
|
LL | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:416:9
--> $DIR/empty-types.rs:419:9
|
LL | Some(_a) => {}
| ^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:421:9
--> $DIR/empty-types.rs:424:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:426:9
--> $DIR/empty-types.rs:429:9
|
LL | _a => {}
| ^^
error: unreachable pattern
--> $DIR/empty-types.rs:598:9
--> $DIR/empty-types.rs:601:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:601:9
--> $DIR/empty-types.rs:604:9
|
LL | _x => {}
| ^^
error: unreachable pattern
--> $DIR/empty-types.rs:604:9
--> $DIR/empty-types.rs:607:9
|
LL | _ if false => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:607:9
--> $DIR/empty-types.rs:610:9
|
LL | _x if false => {}
| ^^

View File

@ -0,0 +1,630 @@
warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/empty-types.rs:13:35
|
LL | #![cfg_attr(min_exh_pats, 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: unreachable pattern
--> $DIR/empty-types.rs:50:9
|
LL | _ => {}
| ^
|
note: the lint level is defined here
--> $DIR/empty-types.rs:16:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:53:9
|
LL | _x => {}
| ^^
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
--> $DIR/empty-types.rs:57:11
|
LL | match ref_never {}
| ^^^^^^^^^
|
= 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 ref_never {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:72:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:79:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:82:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:86:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
--> $DIR/empty-types.rs:90:11
|
LL | match res_u32_never {}
| ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
|
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<u32, !>`
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 ~ match res_u32_never {
LL + Ok(_) => todo!(),
LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:98:9
|
LL | Err(_) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:103:9
|
LL | Err(_) => {}
| ^^^^^^
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
--> $DIR/empty-types.rs:100:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
|
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<u32, !>`
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 ~ Err(_) => {},
LL ~ Ok(1_u32..=u32::MAX) => todo!()
|
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:107:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` 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: the matched value is of type `Result<&u32, &!>`
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
| ++++++++++++++++
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:111:9
|
LL | let Ok(_x) = &res_u32_never;
| ^^^^^^ pattern `&Err(_)` 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: the matched value is of type `&Result<u32, !>`
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(_x) = &res_u32_never else { todo!() };
| ++++++++++++++++
error: unreachable pattern
--> $DIR/empty-types.rs:118:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:122:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:125:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:126:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:129:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:130:9
|
LL | Err(_) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:139:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:142:13
|
LL | _ if false => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:151:13
|
LL | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:155:13
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:164:15
|
LL | match *ref_opt_void {
| ^^^^^^^^^^^^^ pattern `Some(_)` not covered
|
note: `Option<Void>` 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<Void>`
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 ~ None => {},
LL + Some(_) => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:207:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:212:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:217:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:222:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:228:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:287:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:290:9
|
LL | (_, _) => {}
| ^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:293:9
|
LL | Ok(_) => {}
| ^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:294:9
|
LL | Err(_) => {}
| ^^^^^^
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:315:11
|
LL | match *x {}
| ^^
|
= note: the matched value is of type `(u32, !)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match *x {
LL + _ => todo!(),
LL ~ }
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
--> $DIR/empty-types.rs:317:11
|
LL | match *x {}
| ^^
|
= 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 as shown
|
LL ~ match *x {
LL + _ => todo!(),
LL ~ }
|
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
--> $DIR/empty-types.rs:319:11
|
LL | match *x {}
| ^^ patterns `Ok(_)` and `Err(_)` not covered
|
note: `Result<!, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
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 ~ match *x {
LL + Ok(_) | Err(_) => todo!(),
LL ~ }
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
--> $DIR/empty-types.rs:321:11
|
LL | match *x {}
| ^^
|
= note: the matched value is of type `[!; 3]`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match *x {
LL + _ => todo!(),
LL ~ }
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:326:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
|
= 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 as shown
|
LL ~ match slice_never {
LL + _ => todo!(),
LL + }
|
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/empty-types.rs:328:11
|
LL | match slice_never {
| ^^^^^^^^^^^ 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/empty-types.rs:337:11
|
LL | match slice_never {
| ^^^^^^^^^^^ 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[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
--> $DIR/empty-types.rs:350:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
|
= note: the matched value is of type `&[!]`
= note: match arms with guards don't count towards exhaustivity
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 ~ &[..] if false => {},
LL + &[] | &[_, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:356:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
|
= 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 as shown
|
LL ~ match *slice_never {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:366:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:369:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:372:9
|
LL | [_, ..] => {}
| ^^^^^^^
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:386:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
|
= note: the matched value is of type `[!; 0]`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match array_0_never {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:393:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:395:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
|
= note: the matched value is of type `[!; 0]`
= note: match arms with guards don't count towards exhaustivity
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 ~ [..] if false => {},
LL + [] => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:414:9
|
LL | Some(_) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:419:9
|
LL | Some(_a) => {}
| ^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:424:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:429:9
|
LL | _a => {}
| ^^
error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
--> $DIR/empty-types.rs:449:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(_)` 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 ~ &None => {},
LL + &Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:490:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(_)` 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 ~ None => {},
LL + Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:538:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
|
note: `Result<!, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
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 ~ Ok(_) => {},
LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:549:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
|
note: `Result<!, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
::: $SRC_DIR/core/src/result.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
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 ~ Ok(_a) => {},
LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:568:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: the matched value is of type `(u32, !)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match *ref_tuple_half_never {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:601:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:604:9
|
LL | _x => {}
| ^^
error: unreachable pattern
--> $DIR/empty-types.rs:607:9
|
LL | _ if false => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:610:9
|
LL | _x if false => {}
| ^^
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/empty-types.rs:635:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&_` not covered
|
= note: the matched value is of type `&!`
= note: references are always considered inhabited
= note: match arms with guards don't count towards exhaustivity
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 ~ &_a if false => {},
LL + &_ => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:663:11
|
LL | match *x {
| ^^ pattern `Some(_)` not covered
|
note: `Option<Result<!, !>>` 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<Result<!, !>>`
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 ~ None => {},
LL + Some(_) => todo!()
|
error: aborting due to 63 previous errors; 1 warning emitted
Some errors have detailed explanations: E0004, E0005.
For more information about an error, try `rustc --explain E0004`.

View File

@ -1,23 +1,23 @@
error: unreachable pattern
--> $DIR/empty-types.rs:47:9
--> $DIR/empty-types.rs:50:9
|
LL | _ => {}
| ^
|
note: the lint level is defined here
--> $DIR/empty-types.rs:13:9
--> $DIR/empty-types.rs:16:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/empty-types.rs:50:9
--> $DIR/empty-types.rs:53:9
|
LL | _x => {}
| ^^
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
--> $DIR/empty-types.rs:54:11
--> $DIR/empty-types.rs:57:11
|
LL | match ref_never {}
| ^^^^^^^^^
@ -32,7 +32,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:66:11
--> $DIR/empty-types.rs:69:11
|
LL | match tuple_half_never {}
| ^^^^^^^^^^^^^^^^
@ -46,7 +46,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
--> $DIR/empty-types.rs:73:11
--> $DIR/empty-types.rs:76:11
|
LL | match tuple_never {}
| ^^^^^^^^^^^
@ -60,13 +60,13 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:83:9
--> $DIR/empty-types.rs:86:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
--> $DIR/empty-types.rs:87:11
--> $DIR/empty-types.rs:90:11
|
LL | match res_u32_never {}
| ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
@ -88,7 +88,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:89:11
--> $DIR/empty-types.rs:92:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -106,7 +106,7 @@ LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
--> $DIR/empty-types.rs:97:11
--> $DIR/empty-types.rs:100:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@ -124,7 +124,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!()
|
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:102:9
--> $DIR/empty-types.rs:105:9
|
LL | let Ok(_x) = res_u32_never;
| ^^^^^^ pattern `Err(_)` not covered
@ -138,7 +138,7 @@ LL | let Ok(_x) = res_u32_never else { todo!() };
| ++++++++++++++++
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:104:9
--> $DIR/empty-types.rs:107:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` not covered
@ -152,7 +152,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
| ++++++++++++++++
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:108:9
--> $DIR/empty-types.rs:111:9
|
LL | let Ok(_x) = &res_u32_never;
| ^^^^^^ pattern `&Err(_)` not covered
@ -166,7 +166,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() };
| ++++++++++++++++
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
--> $DIR/empty-types.rs:112:11
--> $DIR/empty-types.rs:115:11
|
LL | match result_never {}
| ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
@ -188,7 +188,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:117:11
--> $DIR/empty-types.rs:120:11
|
LL | match result_never {
| ^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -205,19 +205,19 @@ LL | Ok(_) => {}, Err(_) => todo!()
| +++++++++++++++++++
error: unreachable pattern
--> $DIR/empty-types.rs:136:13
--> $DIR/empty-types.rs:139:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:139:13
--> $DIR/empty-types.rs:142:13
|
LL | _ if false => {}
| ^
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:142:15
--> $DIR/empty-types.rs:145:15
|
LL | match opt_void {
| ^^^^^^^^ pattern `Some(_)` not covered
@ -235,7 +235,7 @@ LL + Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:161:15
--> $DIR/empty-types.rs:164:15
|
LL | match *ref_opt_void {
| ^^^^^^^^^^^^^ pattern `Some(_)` not covered
@ -253,43 +253,43 @@ LL + Some(_) => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:204:13
--> $DIR/empty-types.rs:207:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:209:13
--> $DIR/empty-types.rs:212:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:214:13
--> $DIR/empty-types.rs:217:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:219:13
--> $DIR/empty-types.rs:222:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:225:13
--> $DIR/empty-types.rs:228:13
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:284:9
--> $DIR/empty-types.rs:287:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:312:11
--> $DIR/empty-types.rs:315:11
|
LL | match *x {}
| ^^
@ -303,7 +303,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
--> $DIR/empty-types.rs:314:11
--> $DIR/empty-types.rs:317:11
|
LL | match *x {}
| ^^
@ -317,7 +317,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
--> $DIR/empty-types.rs:316:11
--> $DIR/empty-types.rs:319:11
|
LL | match *x {}
| ^^ patterns `Ok(_)` and `Err(_)` not covered
@ -339,7 +339,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
--> $DIR/empty-types.rs:318:11
--> $DIR/empty-types.rs:321:11
|
LL | match *x {}
| ^^
@ -353,7 +353,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:323:11
--> $DIR/empty-types.rs:326:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@ -367,7 +367,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/empty-types.rs:325:11
--> $DIR/empty-types.rs:328:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[_, ..]` not covered
@ -380,7 +380,7 @@ LL + &[_, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
--> $DIR/empty-types.rs:334:11
--> $DIR/empty-types.rs:337:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@ -393,7 +393,7 @@ LL + &[] | &[_] | &[_, _] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
--> $DIR/empty-types.rs:347:11
--> $DIR/empty-types.rs:350:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@ -407,7 +407,7 @@ LL + &[] | &[_, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:353:11
--> $DIR/empty-types.rs:356:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@ -421,7 +421,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
--> $DIR/empty-types.rs:360:11
--> $DIR/empty-types.rs:363:11
|
LL | match array_3_never {}
| ^^^^^^^^^^^^^
@ -435,7 +435,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:383:11
--> $DIR/empty-types.rs:386:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@ -449,13 +449,13 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:390:9
--> $DIR/empty-types.rs:393:9
|
LL | _ => {}
| ^
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:392:11
--> $DIR/empty-types.rs:395:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@ -469,7 +469,7 @@ LL + [] => todo!()
|
error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
--> $DIR/empty-types.rs:446:11
--> $DIR/empty-types.rs:449:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@ -487,7 +487,7 @@ LL + &Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:487:11
--> $DIR/empty-types.rs:490:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@ -505,7 +505,7 @@ LL + Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:535:11
--> $DIR/empty-types.rs:538:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -523,7 +523,7 @@ LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:546:11
--> $DIR/empty-types.rs:549:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -541,7 +541,7 @@ LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:565:11
--> $DIR/empty-types.rs:568:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
@ -555,31 +555,31 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:598:9
--> $DIR/empty-types.rs:601:9
|
LL | _ => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:601:9
--> $DIR/empty-types.rs:604:9
|
LL | _x => {}
| ^^
error: unreachable pattern
--> $DIR/empty-types.rs:604:9
--> $DIR/empty-types.rs:607:9
|
LL | _ if false => {}
| ^
error: unreachable pattern
--> $DIR/empty-types.rs:607:9
--> $DIR/empty-types.rs:610:9
|
LL | _x if false => {}
| ^^
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/empty-types.rs:631:11
--> $DIR/empty-types.rs:635:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&_` not covered
@ -594,7 +594,7 @@ LL + &_ => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:659:11
--> $DIR/empty-types.rs:663:11
|
LL | match *x {
| ^^ pattern `Some(_)` not covered

View File

@ -1,4 +1,5 @@
// revisions: normal exhaustive_patterns
// revisions: normal min_exh_pats exhaustive_patterns
// gate-test-min_exhaustive_patterns
//
// This tests correct handling of empty types in exhaustiveness checking.
//
@ -9,6 +10,8 @@
// This feature is useful to avoid `!` falling back to `()` all the time.
#![feature(never_type_fallback)]
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))]
//[min_exh_pats]~^ WARN the feature `min_exhaustive_patterns` is incomplete
#![allow(dead_code, unreachable_code)]
#![deny(unreachable_patterns)]
@ -66,17 +69,17 @@ fn basic(x: NeverBundle) {
match tuple_half_never {}
//[normal]~^ ERROR non-empty
match tuple_half_never {
(_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
(_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
let tuple_never: (!, !) = x.tuple_never;
match tuple_never {}
//[normal]~^ ERROR non-empty
match tuple_never {
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match tuple_never {
(_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
(_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match tuple_never.0 {}
match tuple_never.0 {
@ -92,12 +95,12 @@ fn basic(x: NeverBundle) {
}
match res_u32_never {
Ok(_) => {}
Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match res_u32_never {
//~^ ERROR non-exhaustive
Ok(0) => {}
Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
let Ok(_x) = res_u32_never;
//[normal]~^ ERROR refutable
@ -106,25 +109,25 @@ fn basic(x: NeverBundle) {
// Non-obvious difference: here there's an implicit dereference in the patterns, which makes the
// inner place !known_valid. `exhaustive_patterns` ignores this.
let Ok(_x) = &res_u32_never;
//[normal]~^ ERROR refutable
//[normal,min_exh_pats]~^ ERROR refutable
let result_never: Result<!, !> = x.result_never;
match result_never {}
//[normal]~^ ERROR non-exhaustive
match result_never {
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match result_never {
//[normal]~^ ERROR non-exhaustive
Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match result_never {
Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match result_never {
Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
}
@ -145,11 +148,11 @@ fn void_same_as_never(x: NeverBundle) {
}
match opt_void {
None => {}
Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match opt_void {
None => {}
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
let ref_void: &Void = &x.void;
@ -159,7 +162,7 @@ fn void_same_as_never(x: NeverBundle) {
}
let ref_opt_void: &Option<Void> = &None;
match *ref_opt_void {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
None => {}
}
match *ref_opt_void {
@ -284,11 +287,11 @@ fn nested_validity_tracking(bundle: NeverBundle) {
_ => {} //~ ERROR unreachable pattern
}
match tuple_never {
(_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
(_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match result_never {
Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
// These should be considered !known_valid and not warn unreachable.
@ -309,13 +312,13 @@ fn invalid_empty_match(bundle: NeverBundle) {
match *x {}
let x: &(u32, !) = &bundle.tuple_half_never;
match *x {} //[normal]~ ERROR non-exhaustive
match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
let x: &(!, !) = &bundle.tuple_never;
match *x {} //[normal]~ ERROR non-exhaustive
match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
let x: &Result<!, !> = &bundle.result_never;
match *x {} //[normal]~ ERROR non-exhaustive
match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
let x: &[!; 3] = &bundle.array_3_never;
match *x {} //[normal]~ ERROR non-exhaustive
match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
}
fn arrays_and_slices(x: NeverBundle) {
@ -323,7 +326,7 @@ fn arrays_and_slices(x: NeverBundle) {
match slice_never {}
//~^ ERROR non-empty
match slice_never {
//[normal]~^ ERROR not covered
//[normal,min_exh_pats]~^ ERROR not covered
[] => {}
}
match slice_never {
@ -332,7 +335,7 @@ fn arrays_and_slices(x: NeverBundle) {
[_, _, ..] => {}
}
match slice_never {
//[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
//[normal,min_exh_pats]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
//[exhaustive_patterns]~^^ ERROR `&[]` not covered
[_, _, _, ..] => {}
}
@ -345,7 +348,7 @@ fn arrays_and_slices(x: NeverBundle) {
_x => {}
}
match slice_never {
//[normal]~^ ERROR `&[]` and `&[_, ..]` not covered
//[normal,min_exh_pats]~^ ERROR `&[]` and `&[_, ..]` not covered
//[exhaustive_patterns]~^^ ERROR `&[]` not covered
&[..] if false => {}
}
@ -360,13 +363,13 @@ fn arrays_and_slices(x: NeverBundle) {
match array_3_never {}
//[normal]~^ ERROR non-empty
match array_3_never {
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match array_3_never {
[_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
[_, _, _] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match array_3_never {
[_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
[_, ..] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
let ref_array_3_never: &[!; 3] = &array_3_never;
@ -408,22 +411,22 @@ fn bindings(x: NeverBundle) {
match opt_never {
None => {}
// !useful, !reachable
Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
Some(_a) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
_ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
_a => {} //[exhaustive_patterns]~ ERROR unreachable pattern
_a => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
}
// The scrutinee is known_valid, but under the `&` isn't anymore.
@ -444,7 +447,7 @@ fn bindings(x: NeverBundle) {
&_a => {}
}
match ref_opt_never {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
&None => {}
}
match ref_opt_never {
@ -485,7 +488,7 @@ fn bindings(x: NeverBundle) {
ref _a => {}
}
match *ref_opt_never {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
None => {}
}
match *ref_opt_never {
@ -533,7 +536,7 @@ fn bindings(x: NeverBundle) {
let ref_res_never: &Result<!, !> = &x.result_never;
match *ref_res_never {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
// useful, reachable
Ok(_) => {}
}
@ -544,7 +547,7 @@ fn bindings(x: NeverBundle) {
_ => {}
}
match *ref_res_never {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
// useful, !reachable
Ok(_a) => {}
}
@ -563,7 +566,7 @@ fn bindings(x: NeverBundle) {
let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never;
match *ref_tuple_half_never {}
//[normal]~^ ERROR non-empty
//[normal,min_exh_pats]~^ ERROR non-empty
match *ref_tuple_half_never {
// useful, reachable
(_, _) => {}
@ -614,6 +617,7 @@ fn guards_and_validity(x: NeverBundle) {
// useful, reachable
_ => {}
}
// Now the madness commences. The guard caused a load of the value thus asserting validity. So
// there's no invalid value for `_` to catch. So the second pattern is unreachable despite the
// guard not being taken.
@ -629,7 +633,7 @@ fn guards_and_validity(x: NeverBundle) {
_a if false => {}
}
match ref_never {
//[normal]~^ ERROR non-exhaustive
//[normal,min_exh_pats]~^ ERROR non-exhaustive
// useful, !reachable
&_a if false => {}
}
@ -657,7 +661,7 @@ fn diagnostics_subtlety(x: NeverBundle) {
// Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`.
let x: &Option<Result<!, !>> = &None;
match *x {
//[normal]~^ ERROR `Some(_)` not covered
//[normal,min_exh_pats]~^ ERROR `Some(_)` not covered
None => {}
}
}