Skip to content

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

@fmease

Description

@fmease

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 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 

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-patternsRelating to patterns and pattern matchingD-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.L-unused_variablesLint: unused_variablesT-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