Repository navigation
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
- private items (meaning: the suggestion will lead to errors) or
- 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
Activity
fmease commentedon Oct 11, 2025
I'm aware of the fixed issue #147303. Its linked PR #147320 simply suppressed the diagnostic for function parameters but whether the unused binding is inside a parameter, a
matchexpr,letbinding or XY is immaterial, this affects all pattern locations.What actually matters for addressing this issue is the following and I summarize:
_I'm also aware of PR #147310 which downgraded the suggestion from machine-applicable to maybe-incorrect.
estebank commentedon Oct 15, 2025
For the second case above, the suggestion is wrong even if it was public: the lev distance should be too high!
I think that we should still at least point at reasonable private items (in the same way that if we have a binding out of scope, we point at it). There are cases where the item being private is the mistake, specially if the lev distance is 0.
I'm surprised that
find_best_match_for_namewith adist: Nonewould pick these names at all, because in that case it should be looking at things with at most 1/3rd distance change :-/IIRC, the problem is that being in resolve we have to duplicate/reimplement the logic for getting the appropriate path to print, this was a best-effort approximation :(
reddevilmidzy commentedon Nov 18, 2025
I've encountered a similar issue with the "typoed pattern" suggestion, but in a different context: simple variable bindings (not pattern matching).
Reproduction:
Compiler Output:
The suggested let system::Y = system::Y; is a pattern match that doesn't bind any variable, so it doesn't solve the original problem (the value is still unused).
rustc versionfmease commentedon Sep 19, 2026
Incidentally, the 2nd case (privacy) was addressed the same day I opened this issue (on main, not nightly): PR RUST-142390 added the necessary
is_accessible_fromcheck.Of course, it means this suggestion wasn't implemented.