Skip to content

rustc non-exhaustive patterns: Misleading error message when match arm uses if over a general pattern #104653

@LeoniePhiline

Description

@LeoniePhiline

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f8368327e56743a1f798a6086383804d

fn main() {
    let some_condition = true;
    let some_option: Option<u8> = None;

    let _res = match some_option {
        Some(val) if some_condition => val,
        None => 0,
    };
}

The current output is:

Compiling playground v0.0.1 (/playground)
error[[E0004]](https://doc.rust-lang.org/stable/error-index.html#E0004): non-exhaustive patterns: `Some(_)` not covered
 --> src/main.rs:5:22
  |
5 |     let _res = match some_option {
  |                      ^^^^^^^^^^^ pattern `Some(_)` not covered
  |
note: `Option<u8>` defined here
  = note: the matched value is of type `Option<u8>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
  |
7 ~         None => 0,
8 ~         Some(_) => todo!(),
  |

For more information about this error, try `rustc --explain E0004`.
error: could not compile `playground` due to previous error

The output might rather look like something akin to:

Compiling playground v0.0.1 (/playground)
error[[E0004]](https://doc.rust-lang.org/stable/error-index.html#E0004): non-exhaustive patterns: `Some(val) if !some_condition` not covered
 --> src/main.rs:5:22
  |
5 |     let _res = match some_option {
  |                      ^^^^^^^^^^^ pattern `Some(val) if !some_condition` not covered
  |
note: `Option<u8>` defined here
  = note: the matched value is of type `Option<u8>`
  = note: match arms are evaluated from top to bottom. 
  = note: instead of negating the condition of the previous match arm, just match without it to cover other cases
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
  |
7 ~         Some(val) => todo!(),
8 ~         None => 0,
  |

For more information about this error, try `rustc --explain E0004`.
error: could not compile `playground` due to previous error

The main pattern Some(val) is general and matches identical to Some(_).
The compiler should point to the match branch's if condition and explain how to match cases not covered by the initial pattern due to the if additional condition.

The compiler is misleading by indicating the Some(val) pattern did not match in all cases - although the restraint lies in the added if - and suggesting Some(_) to match all other patterns. The additional if condition is entirely ignored.

Ideally, the compiler should suggest two variants:

fn main() {
    let some_condition = true;
    let some_option: Option<u8> = None;

    let _res = match some_option {
        Some(val) if some_condition => val,
        Some(val) => todo!(),
        None => 0,
    };
}

And:

fn main() {
    let some_condition = true;
    let some_option: Option<u8> = None;

    let _res = match some_option {
        Some(val) if some_condition => val,
        _ => 0,
    };
}

The output on Nightly is identical to the output on Stable.


May be related: #93611

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions