rust-lang / rust-lang/rust

Lint `unused_variables`'s "typoed pattern" suggestion still suggests invalid and unrelated paths

Open
#147,595 4 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-patterns D-invalid-suggestion L-unused_variables T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I just stumbled upon this organically. Since PR #145827 rustc suggests paths to underscore (!) constant items which is syntactically invalid. Consider:

mod assertions { const _: () = assert!(true); }

pub fn demo(x: Option<()>) {
    match x {
        Some(x) => {}
        None => {}
    }
}
Compiler Output
warning: unused variable: `x`
 --> src/lib.rs:5:14
  |
5 |         Some(x) => {}
  |              ^
  |
  = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
help: if this is intentional, prefix it with an underscore
  |
5 |         Some(_x) => {}
  |              +
help: you might have meant to pattern match on the similarly named constant `_`
  |
5 -         Some(x) => {}
5 +         Some(assertions::_) => {}
  |

The suggested path assertions::_ is syntactically invalid and should never be a suggestion.


Moreover, while rustc does seem to make sure that the type of the unused binding and the suggested constant / constructor match, it doesn't seem to filter out

  1. private items (meaning: the suggestion will lead to errors) or
  2. items with textually dissimilar names (according to a string metric like Levenshtein distance).

Consider:

mod enclosed { #[allow(dead_code)] const EXTRA_OFFSET: i32 = 1; }

pub fn demo(x: Option<i32>) {
    match x {
        Some(x) => {}
        None => {}
    }
}
Compiler Output
warning: unused variable: `x`
 --> src/lib.rs:5:14
  |
5 |         Some(x) => {}
  |              ^
  |
  = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
help: if this is intentional, prefix it with an underscore
  |
5 |         Some(_x) => {}
  |              +
help: you might have meant to pattern match on the similarly named constant `EXTRA_OFFSET`
  |
5 -         Some(x) => {}
5 +         Some(enclosed::EXTRA_OFFSET) => {}
  |

The suggested path enclosed::EXTRA_OFFSET is (1) inaccessible inside demo due to privacy and (2) looks nothing like the unused x, so it can't possibly be a typo.


Finally, the suggestion doesn't properly qualify the path. Consider

pub mod enclosed { pub const X: i32 = 1; }

pub mod separated {
    pub fn demo(x: Option<i32>) {
        let Some(x) = x else { return };
    }
}
Compiler Output
warning: unused variable: `x`
 --> src/lib.rs:7:18
  |
7 |         let Some(x) = x else { return };
  |                  ^
  |
  = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
help: if this is intentional, prefix it with an underscore
  |
7 |         let Some(_x) = x else { return };
  |                  +
help: you might have meant to pattern match on the similarly named constant `X`
  |
7 -         let Some(x) = x else { return };
7 +         let Some(enclosed::X) = x else { return };
  |

It suggests enclosed::X inside separated::demo while it should suggest super::enclosed::X or crate::enclosed::X otherwise it doesn't resolve.


rustc 1.92.0-nightly (3d8c1c1fc 2025-10-06)
binary: rustc
commit-hash: 3d8c1c1fc077d04658de63261d8ce2903546db13
commit-date: 2025-10-06
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the three examples with the cited rustc nightly and inspect the unused_variables lint's typoed-pattern suggestion path. Done means suggestions no longer reference the underscore constant, inaccessible or textually unrelated items, and paths resolve correctly from separated::demo.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.