Description
A syntax error produced by a macro invocation in a trait {}
or impl {}
block will have an incorrect span for its second label:
macro_rules! m {
() => {
let
}
}
trait Foo {
m!();
}
Produces this error:
error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `let`
--> src/lib.rs:3:9
|
1 | macro_rules! m {
| - expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` here
2 | () => {
3 | let
| ^^^ unexpected token
...
8 | m!();
| ----- in this macro invocation
The "expected one of ... here" line is pointing to line 1 but it should be elaborating on the "unexpected token" label, or just replacing it. The behavior is identical for impl {}
blocks.
This appears to be due to some faulty logic in Parser::expect_one_of()
which isn't robust in the face of macro invocations. If it can't get lines for either span from the sourcemap it should assume they're the same (in fact I'm not sure why it emits a separate "unexpected token" label).
Discovered in #54833 but not introduced by it; when that's merged extern {}
blocks will show this behavior too (as seen in issue-54441.stderr
on that PR).
I'll try to look into this sometime this weekend but I'm also willing to mentor on it, though like I mentioned I'm not sure why the error handling logic in Parser::expect_one_of()
is so complex to begin with.