Skip to content

collapsible_match might produce an incorrect suggestion for nested fields, when ref / mut / box modifiers are used #13287

@sobolevn

Description

@sobolevn

Description

enum Token {
    Name,
    Other,
}

struct Error {
    location: u32,
    token: Option<Token>,
}

fn add_anon_function_hint(err: Option<Error>) {
    if let Some(Error { ref token, .. }) = err {  // notice the `ref` part
        if let Some(Token::Name) = token {
            println!("token used as a ref");
        }
    }
}

On main produces:

warning: this `if let` can be collapsed into the outer `if let`
  --> compiler-core/src/regression.rs:13:9
   |
13 | /         if let Some(Token::Name) = token {
14 | |             println!("Name error");
15 | |         }
   | |_________^
   |
help: the outer pattern can be modified to include the inner pattern
  --> compiler-core/src/regression.rs:12:25
   |
12 |     if let Some(Error { ref token, .. }) = err {
   |                         ^^^^^^^^^ replace this binding
13 |         if let Some(Token::Name) = token {
   |                ^^^^^^^^^^^^^^^^^ with this pattern, prefixed by `ref token:`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
note: the lint level is defined here
  --> compiler-core/src/lib.rs:2:5
   |
2  |     clippy::all,
   |     ^^^^^^^^^^^
   = note: `#[warn(clippy::collapsible_match)]` implied by `#[warn(clippy::all)]`

Notice that "by ref token:" part. I think that it might be wrong.
Looks like if let Some(Error { ref token: Some(Token::Name), .. }) is not allowed by the grammar: https://github.com/intellij-rust/intellij-rust/blob/c6657c02bb62075bf7b7ceb84d000f93dda34dc1/src/main/grammars/RustParser.bnf#L642-L645

When this suggestion is applied I get:

error: expected `,`
  --> compiler-core/src/regression.rs:12:34
   |
12 |     if let Some(Error { mut token: Some(Token::Name), .. }) = err {
   |                 -----            ^
   |                 |
   |                 while parsing the fields for this pattern

error[E0425]: cannot find value `token` in this scope
  --> compiler-core/src/regression.rs:13:36
   |
13 |         if let Some(Token::Name) = token {
   |                                    ^^^^^ not found in this scope

For more information about this error, try `rustc --explain E0425`.

The same is in question for box and mut.

Version

rustc 1.82.0-nightly (8b3870784 2024-08-07)
binary: rustc
commit-hash: 8b3870784f69d8ed2ae4246d1b56f150e3131499
commit-date: 2024-08-07
host: aarch64-apple-darwin
release: 1.82.0-nightly
LLVM version: 19.1.0

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions