Skip to content

Commit 51f3d24

Browse files
committed
Only point at the two macro invocations that diverged
1 parent 9b76e07 commit 51f3d24

10 files changed

+52
-40
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+29-17
Original file line numberDiff line numberDiff line change
@@ -2168,39 +2168,51 @@ impl<'a> Parser<'a> {
21682168
// Walk the chain of macro expansions for the current token to point at how the original
21692169
// code was interpreted. This helps the user realize when a macro argument of one type is
21702170
// later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat`
2171-
// in a subsequent macro invokation (#71039).
2171+
// in a subsequent macro invocation (#71039).
21722172
let mut tok = self.token.clone();
21732173
let mut labels = vec![];
2174-
let mut pos = 0;
21752174
while let TokenKind::Interpolated(node) = &tok.kind {
21762175
// FIXME: figure out how to point at `$x:pat` when `tok`
21772176
// is a `NtPat` corresponding to `$x`.
21782177
let tokens = node.tokens();
2179-
labels.push((
2180-
pos,
2181-
node.span(),
2182-
format!("this is interpreted as {} {}", node.descr(), super::token_descr(&tok)),
2183-
));
2178+
labels.push((node.span(), node.descr()));
21842179
if let Some(tokens) = tokens
21852180
&& let tokens = tokens.to_attr_token_stream()
21862181
&& let tokens = tokens.0.deref()
21872182
&& let [AttrTokenTree::Token(token, _)] = &tokens[..]
21882183
{
2189-
info!(?token);
21902184
tok = token.clone();
2191-
pos += 1;
21922185
} else {
21932186
break;
21942187
}
21952188
}
2196-
for (i, span, label) in labels {
2197-
let post = if pos > 0 {
2198-
// When there are more than one macro expansions at play, clarify the order.
2199-
format!(" (in expansion #{})", pos + 1 - i)
2200-
} else {
2201-
String::new()
2202-
};
2203-
err.span_label(span, format!("{label}{post}"));
2189+
let mut iter = labels.into_iter().peekable();
2190+
let mut show_link = false;
2191+
while let Some((span, descr)) = iter.next() {
2192+
if let Some((next_span, next_descr)) = iter.peek()
2193+
&& next_descr != &descr
2194+
{
2195+
err.span_label(
2196+
*next_span,
2197+
format!("this is interpreted as {next_descr}"),
2198+
);
2199+
err.span_label(
2200+
span,
2201+
format!(
2202+
"this is interpreted as {}, but it was previously interpreted as {}",
2203+
descr,
2204+
next_descr,
2205+
),
2206+
);
2207+
show_link = true;
2208+
}
2209+
}
2210+
if show_link {
2211+
err.note(
2212+
"when forwarding a matched fragment to another macro-by-example, matchers in the \
2213+
second macro will see an opaque AST of the fragment type, not the underlying \
2214+
tokens",
2215+
);
22042216
}
22052217
err
22062218
}

compiler/rustc_parse/src/parser/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,14 @@ impl TokenDescription {
365365
pub(super) fn token_descr(token: &Token) -> String {
366366
let name = pprust::token_to_string(token).to_string();
367367

368-
let kind = TokenDescription::from_token(token).map(|kind| match kind {
369-
TokenDescription::ReservedIdentifier => "reserved identifier",
370-
TokenDescription::Keyword => "keyword",
371-
TokenDescription::ReservedKeyword => "reserved keyword",
372-
TokenDescription::DocComment => "doc comment",
373-
});
368+
let kind = match (TokenDescription::from_token(token), &token.kind) {
369+
(Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"),
370+
(Some(TokenDescription::Keyword), _) => Some("keyword"),
371+
(Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
372+
(Some(TokenDescription::DocComment), _) => Some("doc comment"),
373+
(None, TokenKind::Interpolated(node)) => Some(node.descr()),
374+
(None, _) => None,
375+
};
374376

375377
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
376378
}

tests/ui/issues/issue-39848.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
macro_rules! get_opt {
22
($tgt:expr, $field:ident) => {
3-
if $tgt.has_$field() {} //~ ERROR expected `{`, found `foo`
3+
if $tgt.has_$field() {} //~ ERROR expected `{`, found identifier `foo`
44
}
55
}
66

tests/ui/issues/issue-39848.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: expected `{`, found `foo`
1+
error: expected `{`, found identifier `foo`
22
--> $DIR/issue-39848.rs:3:21
33
|
44
LL | if $tgt.has_$field() {}

tests/ui/macros/syntax-error-recovery.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ macro_rules! values {
99
}
1010
};
1111
}
12-
//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
12+
//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)`
1313
//~| ERROR macro expansion ignores token `(String)` and any following
1414

1515
values!(STRING(1) as (String) => cfg(test),);

tests/ui/macros/syntax-error-recovery.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
1+
error: expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)`
22
--> $DIR/syntax-error-recovery.rs:7:26
33
|
44
LL | $token $($inner)? = $value,

tests/ui/macros/trace_faulty_macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ macro_rules! test {
4646
(let $p:pat = $e:expr) => {test!(($p,$e))};
4747
// this should be expr
4848
// vvv
49-
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found `1 + 1`
49+
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1 + 1`
5050
}
5151

5252
fn foo() {
5353
test!(let x = 1+1);
54-
}
54+
}

tests/ui/macros/trace_faulty_macros.stderr

+5-7
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,9 @@ LL | my_recursive_macro!();
5050
= note: expanding `my_recursive_macro! { }`
5151
= note: to `my_recursive_macro! () ;`
5252

53-
error: expected expression, found `A { a: a, b: 0, c: _, .. }`
53+
error: expected expression, found pattern `A { a: a, b: 0, c: _, .. }`
5454
--> $DIR/trace_faulty_macros.rs:16:9
5555
|
56-
LL | pat_macro!(A{a:a, b:0, c:_, ..});
57-
| -------------------- this is interpreted as pattern `A { a: a, b: 0, c: _, .. }`
58-
...
5956
LL | $a
6057
| ^^ expected expression
6158
...
@@ -72,21 +69,22 @@ LL | #[derive(Debug)]
7269
LL | fn use_derive_macro_as_attr() {}
7370
| -------------------------------- not a `struct`, `enum` or `union`
7471

75-
error: expected expression, found `1 + 1`
72+
error: expected expression, found pattern `1 + 1`
7673
--> $DIR/trace_faulty_macros.rs:49:37
7774
|
7875
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
79-
| -- this is interpreted as pattern `1 + 1` (in expansion #2)
76+
| -- this is interpreted as pattern, but it was previously interpreted as expression
8077
...
8178
LL | (($p:pat, $e:pat)) => {let $p = $e;};
8279
| ^^ expected expression
8380
...
8481
LL | test!(let x = 1+1);
8582
| ------------------
8683
| | |
87-
| | this is interpreted as expression `1 + 1` (in expansion #1)
84+
| | this is interpreted as expression
8885
| in this macro invocation
8986
|
87+
= note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens
9088
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
9189

9290
note: trace_macro

tests/ui/parser/float-field-interpolated.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ macro_rules! generate_field_accesses {
66

77
s.$a; // OK
88
{ s.$b; } //~ ERROR unexpected token: `1.1`
9-
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1`
9+
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1`
1010
{ s.$c; } //~ ERROR unexpected token: `1.1`
11-
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1`
11+
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1`
1212
};
1313
}
1414

tests/ui/parser/float-field-interpolated.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1);
99
|
1010
= note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info)
1111

12-
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1`
12+
error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1`
1313
--> $DIR/float-field-interpolated.rs:8:13
1414
|
1515
LL | { s.$b; }
@@ -31,7 +31,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1);
3131
|
3232
= note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info)
3333

34-
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1`
34+
error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1`
3535
--> $DIR/float-field-interpolated.rs:10:13
3636
|
3737
LL | { s.$c; }

0 commit comments

Comments
 (0)