Skip to content

unreachable_patterns fires on match arm that can't be removed. #129352

Open
@Dirbaio

Description

@Dirbaio

playground

use core::future::Future;

async fn select<A: Future, B: Future>(_: A, _: B) -> Result<A::Output, B::Output> {
    todo!()
}

pub async fn wtf() -> ! {
    let a = async { loop {} };
    let b = async { loop {} };
    match select(a, b).await {
        Ok(x) => x,
        Err(x) => x,
    }
}

warns with unreachable_patterns on both arms

warning: unreachable pattern
  --> src/lib.rs:11:9
   |
11 |         Ok(x) => x,
   |         ^^^^^
   |
   = note: this pattern matches no values because `Result<!, !>` is uninhabited
   = note: `#[warn(unreachable_patterns)]` on by default

but removing either doesn't actually compile

error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
   --> src/lib.rs:10:11
    |
10  |     match select(a, b).await {
    |           ^^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
    |
note: `Result<(), !>` defined here
   --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:527:1
    |
527 | pub enum Result<T, E> {
    | ^^^^^^^^^^^^^^^^^^^^^
...
531 |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     -- 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
    |
11  ~         Err(x) => x,
12  ~         Ok(_) => todo!(),

So this code seems "unfixable" with the new lint.

What's happening is the match arm is unreachable, but it still has the "side effect" of making the async block be inferred to Future<Output=!> instead of Future<Output=()>. So, if you remove it the future now gets inferred to return (), and the arm is not unreachable anymore.

In edition 2024 it Just Works if you write match select(a, b).await {}, because the fallback is ! instead of ().

This seems a bit hard to mitigate in Edition 2021, it seems more like an unfortunate combination of the lint and the inference fallback more than a bug. I'm opening the issue anyway to share it, just in case anyone has an idea.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.F-never_type`#![feature(never_type)]`L-unreachable_patternsLint: unreachable_patternsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions