Open
Description
Uplifted from #141213 (comment). Given
struct Type { field: i32 }
impl Type {
fn method(&self) { {field} }
}
the compiler outputs
error[E0425]: cannot find value `field` in this scope
--> file.rs:4:25
|
4 | fn method(&self) { {field} }
| ^^^^^
|
= help: you might have meant to use the available field in a format string: `"{}", self.field`
warning: unnecessary braces around block return value
--> file.rs:4:24
|
4 | fn method(&self) { {field} }
| ^ ^
|
= note: `#[warn(unused_braces)]` on by default
help: remove these braces
|
4 - fn method(&self) { {field} }
4 + fn method(&self) { field }
|
error: aborting due to 1 previous error; 1 warning emitted
Notice the (unstructured) suggestion you might have meant to use the available field in a format string: `"{}", self.field`
which is obviously incorrect, there's no format string in sight and fn method(&self) { "{}", self.field; }
is butchered.
For context, this regressed in PR #141213.
Version Information
rustc 1.89.0-nightly (c43786c9b 2025-05-21)
binary: rustc
commit-hash: c43786c9b7b8d8dcc3f9c604e0e3074c16ed69d3
commit-date: 2025-05-21
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5
Metadata
Metadata
Assignees
Labels
Area: Messages for errors, warnings, and lintsArea: Name/path resolution done by `rustc_resolve` specificallyDiagnostics: A diagnostic that is giving misleading or incorrect information.Diagnostics: An error or lint that needs small tweaks.Relevant to the compiler team, which will review and decide on the PR/issue.
Activity
fmease commentedon May 21, 2025
We might be able to fix this by marking the span with
DesugaringKind::FormatArgs
(yet to be defined) by usingmark_with_reason
during the lowering ofast::FormatArgs
(no surface syntax) (not to be confused with the expansion offormat_args!(…)
) and querying it at the relevant site.However, even then we'd need to be wary of cases like
format!("{}", {field})
(we don't want to (essentially) suggestformat!("{}", "{}", self.field)
).self
#141213[-]Diagnostic assumes that braced unresolved identifiers are formatting argument[/-][+]Diagnostic assumes that braced unresolved identifiers are formatting arguments[/+]xizheyin commentedon May 21, 2025
Great case, I'll look at adding
DesugaringKind::FormatArgs
in the near future if you're not going to do that.xizheyin commentedon May 21, 2025
@rustbot claim
fmease commentedon May 21, 2025
Also CC @mejrs to whom I recently also suggested to create
DesugaringKind::FormatArgs
& tomark_with_reason
during the lowering ofast::FormatArgs
for an unrelated diagnostic improvement. Pinging them to avoid duplicate efforts.mejrs commentedon May 21, 2025
I did not get that far with the implementation of the desugaring aspect of it, that turned out to be more complicated than I thought. Feel free to take it if you want.
Just some thought:
xizheyin commentedon May 25, 2025
Here are some notes as I'm going along, and feel free to make some suggestions.
I've found that marking span at
ast_lowering
doesn't solve the problem because the diagnostic occurs atrustc_resolve
, which comes beforeast_lowering
.I also tried to mark
FormatArgs
as soon as the span is generated inrustc_builtin_macros
, but found thattcx
is missing, and I may have to add arustc_middle
dependency, which I'm worried will interfere with compilation efficiency.I need to do some more investigation to see if I can mark elsewhere.
mejrs commentedon May 25, 2025
In rustc_resolve we should at least be able to tell if we're in an expansion of some particular macros, using the
outer*
methods on Span and that the format macros are diagnostic items.Another way would be to revert #141213 and instead just tell the user to write
let x = self.x;
orlet x = &self.x;
in the surrounding scope. This also gets around issues like "what if the macro already has positional arguments".7 remaining items