Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4e41880

Browse files
committedNov 16, 2023
More detail when expecting expression but encountering bad macro argument
Partially address #71039.
1 parent 1be1e84 commit 4e41880

27 files changed

+200
-67
lines changed
 

‎compiler/rustc_ast/src/attr/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ impl MetaItem {
342342
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
343343
Path { span, segments, tokens: None }
344344
}
345-
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt {
345+
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &nt.0 {
346346
token::Nonterminal::NtMeta(item) => return item.meta(item.path.span),
347347
token::Nonterminal::NtPath(path) => (**path).clone(),
348348
_ => return None,

‎compiler/rustc_ast/src/mut_visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,10 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
764764
return; // Avoid visiting the span for the second time.
765765
}
766766
token::Interpolated(nt) => {
767-
visit_nonterminal(Lrc::make_mut(nt), vis);
767+
let nt = Lrc::make_mut(nt);
768+
let (nt, sp) = (&mut nt.0, &mut nt.1);
769+
vis.visit_span(sp);
770+
visit_nonterminal(nt, vis);
768771
}
769772
_ => {}
770773
}

‎compiler/rustc_ast/src/token.rs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl Lit {
110110
Ident(name, false) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
111111
Literal(token_lit) => Some(token_lit),
112112
Interpolated(ref nt)
113-
if let NtExpr(expr) | NtLiteral(expr) = &**nt
113+
if let NtExpr(expr) | NtLiteral(expr) = &nt.0
114114
&& let ast::ExprKind::Lit(token_lit) = expr.kind =>
115115
{
116116
Some(token_lit)
@@ -314,7 +314,7 @@ pub enum TokenKind {
314314
/// - It prevents `Token` from implementing `Copy`.
315315
/// It adds complexity and likely slows things down. Please don't add new
316316
/// occurrences of this token kind!
317-
Interpolated(Lrc<Nonterminal>),
317+
Interpolated(Lrc<(Nonterminal, Span)>),
318318

319319
/// A doc comment token.
320320
/// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
@@ -421,7 +421,7 @@ impl Token {
421421
/// if they keep spans or perform edition checks.
422422
pub fn uninterpolated_span(&self) -> Span {
423423
match &self.kind {
424-
Interpolated(nt) => nt.span(),
424+
Interpolated(nt) => nt.0.use_span(),
425425
_ => self.span,
426426
}
427427
}
@@ -464,7 +464,7 @@ impl Token {
464464
ModSep | // global path
465465
Lifetime(..) | // labeled loop
466466
Pound => true, // expression attributes
467-
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
467+
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
468468
NtExpr(..) |
469469
NtBlock(..) |
470470
NtPath(..)),
@@ -488,7 +488,7 @@ impl Token {
488488
| DotDot | DotDotDot | DotDotEq // ranges
489489
| Lt | BinOp(Shl) // associated path
490490
| ModSep => true, // global path
491-
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
491+
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
492492
NtPat(..) |
493493
NtBlock(..) |
494494
NtPath(..)),
@@ -511,7 +511,7 @@ impl Token {
511511
Lifetime(..) | // lifetime bound in trait object
512512
Lt | BinOp(Shl) | // associated path
513513
ModSep => true, // global path
514-
Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
514+
Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)),
515515
// For anonymous structs or unions, which only appear in specific positions
516516
// (type of struct fields or union fields), we don't consider them as regular types
517517
_ => false,
@@ -522,7 +522,7 @@ impl Token {
522522
pub fn can_begin_const_arg(&self) -> bool {
523523
match self.kind {
524524
OpenDelim(Delimiter::Brace) => true,
525-
Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
525+
Interpolated(ref nt) => matches!(&nt.0, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
526526
_ => self.can_begin_literal_maybe_minus(),
527527
}
528528
}
@@ -576,7 +576,7 @@ impl Token {
576576
match self.uninterpolate().kind {
577577
Literal(..) | BinOp(Minus) => true,
578578
Ident(name, false) if name.is_bool_lit() => true,
579-
Interpolated(ref nt) => match &**nt {
579+
Interpolated(ref nt) => match &nt.0 {
580580
NtLiteral(_) => true,
581581
NtExpr(e) => match &e.kind {
582582
ast::ExprKind::Lit(_) => true,
@@ -597,9 +597,9 @@ impl Token {
597597
/// otherwise returns the original token.
598598
pub fn uninterpolate(&self) -> Cow<'_, Token> {
599599
match &self.kind {
600-
Interpolated(nt) => match **nt {
600+
Interpolated(nt) => match &nt.0 {
601601
NtIdent(ident, is_raw) => {
602-
Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
602+
Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span))
603603
}
604604
NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
605605
_ => Cow::Borrowed(self),
@@ -614,8 +614,8 @@ impl Token {
614614
// We avoid using `Token::uninterpolate` here because it's slow.
615615
match &self.kind {
616616
&Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
617-
Interpolated(nt) => match **nt {
618-
NtIdent(ident, is_raw) => Some((ident, is_raw)),
617+
Interpolated(nt) => match &nt.0 {
618+
NtIdent(ident, is_raw) => Some((*ident, *is_raw)),
619619
_ => None,
620620
},
621621
_ => None,
@@ -628,8 +628,8 @@ impl Token {
628628
// We avoid using `Token::uninterpolate` here because it's slow.
629629
match &self.kind {
630630
&Lifetime(name) => Some(Ident::new(name, self.span)),
631-
Interpolated(nt) => match **nt {
632-
NtLifetime(ident) => Some(ident),
631+
Interpolated(nt) => match &nt.0 {
632+
NtLifetime(ident) => Some(*ident),
633633
_ => None,
634634
},
635635
_ => None,
@@ -655,7 +655,7 @@ impl Token {
655655
/// Returns `true` if the token is an interpolated path.
656656
fn is_path(&self) -> bool {
657657
if let Interpolated(nt) = &self.kind
658-
&& let NtPath(..) = **nt
658+
&& let NtPath(..) = &nt.0
659659
{
660660
return true;
661661
}
@@ -668,7 +668,7 @@ impl Token {
668668
/// (which happens while parsing the result of macro expansion)?
669669
pub fn is_whole_expr(&self) -> bool {
670670
if let Interpolated(nt) = &self.kind
671-
&& let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt
671+
&& let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &nt.0
672672
{
673673
return true;
674674
}
@@ -679,7 +679,7 @@ impl Token {
679679
/// Is the token an interpolated block (`$b:block`)?
680680
pub fn is_whole_block(&self) -> bool {
681681
if let Interpolated(nt) = &self.kind
682-
&& let NtBlock(..) = **nt
682+
&& let NtBlock(..) = &nt.0
683683
{
684684
return true;
685685
}
@@ -927,7 +927,7 @@ impl fmt::Display for NonterminalKind {
927927
}
928928

929929
impl Nonterminal {
930-
pub fn span(&self) -> Span {
930+
pub fn use_span(&self) -> Span {
931931
match self {
932932
NtItem(item) => item.span,
933933
NtBlock(block) => block.span,
@@ -941,6 +941,23 @@ impl Nonterminal {
941941
NtVis(vis) => vis.span,
942942
}
943943
}
944+
945+
pub fn descr(&self) -> &'static str {
946+
match self {
947+
NtItem(..) => "item",
948+
NtBlock(..) => "block",
949+
NtStmt(..) => "statement",
950+
NtPat(..) => "pattern",
951+
NtExpr(..) => "expression",
952+
NtLiteral(..) => "literal",
953+
NtTy(..) => "type",
954+
NtIdent(..) => "identifier",
955+
NtLifetime(..) => "lifetime",
956+
NtMeta(..) => "attribute",
957+
NtPath(..) => "path",
958+
NtVis(..) => "visibility",
959+
}
960+
}
944961
}
945962

946963
impl PartialEq for Nonterminal {

‎compiler/rustc_ast/src/tokenstream.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,13 +477,13 @@ impl TokenStream {
477477

478478
fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
479479
match &token.kind {
480-
token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = **nt => {
480+
token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => {
481481
TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
482482
}
483483
token::Interpolated(nt) => TokenTree::Delimited(
484484
DelimSpan::from_single(token.span),
485485
Delimiter::Invisible,
486-
TokenStream::from_nonterminal_ast(nt).flattened(),
486+
TokenStream::from_nonterminal_ast(&nt.0).flattened(),
487487
),
488488
_ => TokenTree::Token(token.clone(), spacing),
489489
}

‎compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
825825
}
826826
token::Eof => "<eof>".into(),
827827

828-
token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(),
828+
token::Interpolated(ref nt) => self.nonterminal_to_string(&nt.0).into(),
829829
}
830830
}
831831

‎compiler/rustc_expand/src/mbe/diagnostics.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ pub(super) fn failed_to_match_macro<'cx>(
6767
&& (matches!(expected_token.kind, TokenKind::Interpolated(_))
6868
|| matches!(token.kind, TokenKind::Interpolated(_)))
6969
{
70+
if let TokenKind::Interpolated(node) = &expected_token.kind {
71+
err.span_label(node.1, "");
72+
}
73+
if let TokenKind::Interpolated(node) = &token.kind {
74+
err.span_label(node.1, "");
75+
}
7076
err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
7177
err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information");
7278

‎compiler/rustc_expand/src/mbe/macro_parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ pub(crate) enum NamedMatch {
397397
MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
398398

399399
// A metavar match of any type other than `tt`.
400-
MatchedNonterminal(Lrc<Nonterminal>),
400+
MatchedNonterminal(Lrc<(Nonterminal, rustc_span::Span)>),
401401
}
402402

403403
/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
@@ -692,7 +692,7 @@ impl TtParser {
692692
Ok(nt) => nt,
693693
};
694694
let m = match nt {
695-
ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
695+
ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))),
696696
ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
697697
};
698698
mp.push_match(next_metavar, seq_depth, m);

‎compiler/rustc_expand/src/proc_macro.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl MultiItemModifier for DeriveProcMacro {
126126
Annotatable::Stmt(stmt) => token::NtStmt(stmt),
127127
_ => unreachable!(),
128128
};
129-
TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
129+
TokenStream::token_alone(token::Interpolated(Lrc::new((nt, span))), DUMMY_SP)
130130
} else {
131131
item.to_tokens()
132132
};

‎compiler/rustc_expand/src/proc_macro_server.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,18 +226,23 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
226226
}));
227227
}
228228

229-
Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => trees
230-
.push(TokenTree::Ident(Ident { sym: ident.name, is_raw, span: ident.span })),
229+
Interpolated(ref nt) if let NtIdent(ident, is_raw) = &nt.0 => {
230+
trees.push(TokenTree::Ident(Ident {
231+
sym: ident.name,
232+
is_raw: *is_raw,
233+
span: ident.span,
234+
}))
235+
}
231236

232237
Interpolated(nt) => {
233-
let stream = TokenStream::from_nonterminal_ast(&nt);
238+
let stream = TokenStream::from_nonterminal_ast(&nt.0);
234239
// A hack used to pass AST fragments to attribute and derive
235240
// macros as a single nonterminal token instead of a token
236241
// stream. Such token needs to be "unwrapped" and not
237242
// represented as a delimited group.
238243
// FIXME: It needs to be removed, but there are some
239244
// compatibility issues (see #73345).
240-
if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.sess()) {
245+
if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) {
241246
trees.extend(Self::from_internal((stream, rustc)));
242247
} else {
243248
trees.push(TokenTree::Group(Group {

‎compiler/rustc_parse/src/parser/attr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl<'a> Parser<'a> {
249249
/// The delimiters or `=` are still put into the resulting token stream.
250250
pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> {
251251
let item = match &self.token.kind {
252-
token::Interpolated(nt) => match &**nt {
252+
token::Interpolated(nt) => match &nt.0 {
253253
Nonterminal::NtMeta(item) => Some(item.clone().into_inner()),
254254
_ => None,
255255
},
@@ -369,7 +369,7 @@ impl<'a> Parser<'a> {
369369
/// ```
370370
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
371371
let nt_meta = match &self.token.kind {
372-
token::Interpolated(nt) => match &**nt {
372+
token::Interpolated(nt) => match &nt.0 {
373373
token::NtMeta(e) => Some(e.clone()),
374374
_ => None,
375375
},

‎compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ use crate::parser;
2424
use rustc_ast as ast;
2525
use rustc_ast::ptr::P;
2626
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
27+
use rustc_ast::tokenstream::AttrTokenTree;
2728
use rustc_ast::util::parser::AssocOp;
2829
use rustc_ast::{
2930
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block,
30-
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
31-
Path, PathSegment, QSelf, Ty, TyKind,
31+
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat,
32+
PatKind, Path, PathSegment, QSelf, Ty, TyKind,
3233
};
3334
use rustc_ast_pretty::pprust;
3435
use rustc_data_structures::fx::FxHashSet;
@@ -2252,6 +2253,59 @@ impl<'a> Parser<'a> {
22522253
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
22532254
}
22542255
err.span_label(span, "expected expression");
2256+
2257+
// Walk the chain of macro expansions for the current token to point at how the original
2258+
// code was interpreted. This helps the user realize when a macro argument of one type is
2259+
// later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat`
2260+
// in a subsequent macro invocation (#71039).
2261+
let mut tok = self.token.clone();
2262+
let mut labels = vec![];
2263+
while let TokenKind::Interpolated(node) = &tok.kind {
2264+
let tokens = node.0.tokens();
2265+
labels.push(node.clone());
2266+
if let Some(tokens) = tokens
2267+
&& let tokens = tokens.to_attr_token_stream()
2268+
&& let tokens = tokens.0.deref()
2269+
&& let [AttrTokenTree::Token(token, _)] = &tokens[..]
2270+
{
2271+
tok = token.clone();
2272+
} else {
2273+
break;
2274+
}
2275+
}
2276+
let mut iter = labels.into_iter().peekable();
2277+
let mut show_link = false;
2278+
while let Some(node) = iter.next() {
2279+
let descr = node.0.descr();
2280+
if let Some(next) = iter.peek() {
2281+
let next_descr = next.0.descr();
2282+
if next_descr != descr {
2283+
err.span_label(next.1, format!("this macro fragment matcher is {next_descr}"));
2284+
err.span_label(node.1, format!("this macro fragment matcher is {descr}"));
2285+
err.span_label(
2286+
next.0.use_span(),
2287+
format!("this is expected to be {next_descr}"),
2288+
);
2289+
err.span_label(
2290+
node.0.use_span(),
2291+
format!(
2292+
"this is interpreted as {}, but it is expected to be {}",
2293+
next_descr, descr,
2294+
),
2295+
);
2296+
show_link = true;
2297+
} else {
2298+
err.span_label(node.1, "");
2299+
}
2300+
}
2301+
}
2302+
if show_link {
2303+
err.note(
2304+
"when forwarding a matched fragment to another macro-by-example, matchers in the \
2305+
second macro will see an opaque AST of the fragment type, not the underlying \
2306+
tokens",
2307+
);
2308+
}
22552309
err
22562310
}
22572311

‎compiler/rustc_parse/src/parser/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use thin_vec::{thin_vec, ThinVec};
4646
macro_rules! maybe_whole_expr {
4747
($p:expr) => {
4848
if let token::Interpolated(nt) = &$p.token.kind {
49-
match &**nt {
49+
match &nt.0 {
5050
token::NtExpr(e) | token::NtLiteral(e) => {
5151
let e = e.clone();
5252
$p.bump();
@@ -1952,7 +1952,7 @@ impl<'a> Parser<'a> {
19521952
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
19531953
) -> PResult<'a, L> {
19541954
if let token::Interpolated(nt) = &self.token.kind
1955-
&& let token::NtExpr(e) | token::NtLiteral(e) = &**nt
1955+
&& let token::NtExpr(e) | token::NtLiteral(e) = &nt.0
19561956
&& matches!(e.kind, ExprKind::Err)
19571957
{
19581958
let mut err = errors::InvalidInterpolatedExpression { span: self.token.span }

‎compiler/rustc_parse/src/parser/item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'a> Parser<'a> {
123123
// Don't use `maybe_whole` so that we have precise control
124124
// over when we bump the parser
125125
if let token::Interpolated(nt) = &self.token.kind
126-
&& let token::NtItem(item) = &**nt
126+
&& let token::NtItem(item) = &nt.0
127127
{
128128
let mut item = item.clone();
129129
self.bump();
@@ -2750,7 +2750,7 @@ impl<'a> Parser<'a> {
27502750

27512751
fn is_named_param(&self) -> bool {
27522752
let offset = match &self.token.kind {
2753-
token::Interpolated(nt) => match **nt {
2753+
token::Interpolated(nt) => match &nt.0 {
27542754
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
27552755
_ => 0,
27562756
},

‎compiler/rustc_parse/src/parser/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub enum TrailingToken {
9393
macro_rules! maybe_whole {
9494
($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
9595
if let token::Interpolated(nt) = &$p.token.kind {
96-
if let token::$constructor(x) = &**nt {
96+
if let token::$constructor(x) = &nt.0 {
9797
let $x = x.clone();
9898
$p.bump();
9999
return Ok($e);
@@ -110,7 +110,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
110110
&& $self.may_recover()
111111
&& $self.look_ahead(1, |t| t == &token::ModSep)
112112
&& let token::Interpolated(nt) = &$self.token.kind
113-
&& let token::NtTy(ty) = &**nt
113+
&& let token::NtTy(ty) = &nt.0
114114
{
115115
let ty = ty.clone();
116116
$self.bump();
@@ -367,12 +367,14 @@ impl TokenDescription {
367367
pub(super) fn token_descr(token: &Token) -> String {
368368
let name = pprust::token_to_string(token).to_string();
369369

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

377379
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
378380
}
@@ -662,7 +664,7 @@ impl<'a> Parser<'a> {
662664
fn check_inline_const(&self, dist: usize) -> bool {
663665
self.is_keyword_ahead(dist, &[kw::Const])
664666
&& self.look_ahead(dist + 1, |t| match &t.kind {
665-
token::Interpolated(nt) => matches!(**nt, token::NtBlock(..)),
667+
token::Interpolated(nt) => matches!(&nt.0, token::NtBlock(..)),
666668
token::OpenDelim(Delimiter::Brace) => true,
667669
_ => false,
668670
})

‎compiler/rustc_parse/src/parser/nonterminal.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ impl<'a> Parser<'a> {
5050
NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
5151
NonterminalKind::Vis => match token.kind {
5252
// The follow-set of :vis + "priv" keyword + interpolated
53-
token::Comma | token::Ident(..) | token::Interpolated(..) => true,
53+
token::Comma | token::Ident(..) | token::Interpolated(_) => true,
5454
_ => token.can_begin_type(),
5555
},
5656
NonterminalKind::Block => match &token.kind {
5757
token::OpenDelim(Delimiter::Brace) => true,
58-
token::Interpolated(nt) => match **nt {
58+
token::Interpolated(nt) => match &nt.0 {
5959
NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
6060
NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
6161
| NtVis(_) => false,
@@ -64,7 +64,7 @@ impl<'a> Parser<'a> {
6464
},
6565
NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
6666
token::ModSep | token::Ident(..) => true,
67-
token::Interpolated(nt) => may_be_ident(nt),
67+
token::Interpolated(nt) => may_be_ident(&nt.0),
6868
_ => false,
6969
},
7070
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
@@ -75,22 +75,22 @@ impl<'a> Parser<'a> {
7575
token::BinOp(token::And) | // reference
7676
token::BinOp(token::Minus) | // negative literal
7777
token::AndAnd | // double reference
78-
token::Literal(..) | // literal
78+
token::Literal(_) | // literal
7979
token::DotDot | // range pattern (future compat)
8080
token::DotDotDot | // range pattern (future compat)
8181
token::ModSep | // path
8282
token::Lt | // path (UFCS constant)
8383
token::BinOp(token::Shl) => true, // path (double UFCS)
8484
// leading vert `|` or-pattern
8585
token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
86-
token::Interpolated(nt) => may_be_ident(nt),
86+
token::Interpolated(nt) => may_be_ident(&nt.0),
8787
_ => false,
8888
}
8989
}
9090
NonterminalKind::Lifetime => match &token.kind {
9191
token::Lifetime(_) => true,
9292
token::Interpolated(nt) => {
93-
matches!(**nt, NtLifetime(_))
93+
matches!(&nt.0, NtLifetime(_))
9494
}
9595
_ => false,
9696
},
@@ -191,7 +191,7 @@ impl<'a> Parser<'a> {
191191
panic!(
192192
"Missing tokens for nt {:?} at {:?}: {:?}",
193193
nt,
194-
nt.span(),
194+
nt.use_span(),
195195
pprust::nonterminal_to_string(&nt)
196196
);
197197
}

‎compiler/rustc_parse/src/parser/pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ impl<'a> Parser<'a> {
592592

593593
// Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
594594
if let token::Interpolated(nt) = &self.token.kind {
595-
if let token::NtPat(_) = **nt {
595+
if let token::NtPat(..) = &nt.0 {
596596
self.expected_ident_found_err().emit();
597597
}
598598
}

‎compiler/rustc_parse/src/parser/path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<'a> Parser<'a> {
185185
});
186186

187187
if let token::Interpolated(nt) = &self.token.kind {
188-
if let token::NtTy(ty) = &**nt {
188+
if let token::NtTy(ty) = &nt.0 {
189189
if let ast::TyKind::Path(None, path) = &ty.kind {
190190
let path = path.clone();
191191
self.bump();

‎compiler/rustc_parse/src/parser/stmt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<'a> Parser<'a> {
5353
// Don't use `maybe_whole` so that we have precise control
5454
// over when we bump the parser
5555
if let token::Interpolated(nt) = &self.token.kind
56-
&& let token::NtStmt(stmt) = &**nt
56+
&& let token::NtStmt(stmt) = &nt.0
5757
{
5858
let mut stmt = stmt.clone();
5959
self.bump();

‎tests/ui/issues/issue-39848.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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/nonterminal-matching.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error: no rules expected the token `enum E {}`
22
--> $DIR/nonterminal-matching.rs:19:10
33
|
4+
LL | macro complex_nonterminal($nt_item: item) {
5+
| --------------
46
LL | macro n(a $nt_item b) {
57
| --------------------- when calling this macro
68
...

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,14 @@ fn use_bang_macro_as_attr() {}
4141

4242
#[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s
4343
fn use_derive_macro_as_attr() {}
44+
45+
macro_rules! test {
46+
(let $p:pat = $e:expr) => {test!(($p,$e))};
47+
// this should be expr
48+
// vvv
49+
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1 + 1`
50+
}
51+
52+
fn foo() {
53+
test!(let x = 1+1);
54+
}

‎tests/ui/macros/trace_faulty_macros.stderr

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ 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
|
5656
LL | $a
@@ -69,6 +69,28 @@ LL | #[derive(Debug)]
6969
LL | fn use_derive_macro_as_attr() {}
7070
| -------------------------------- not a `struct`, `enum` or `union`
7171

72+
error: expected expression, found pattern `1 + 1`
73+
--> $DIR/trace_faulty_macros.rs:49:37
74+
|
75+
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
76+
| ------- -- this is interpreted as expression, but it is expected to be pattern
77+
| |
78+
| this macro fragment matcher is expression
79+
...
80+
LL | (($p:pat, $e:pat)) => {let $p = $e;};
81+
| ------ ^^ expected expression
82+
| |
83+
| this macro fragment matcher is pattern
84+
...
85+
LL | test!(let x = 1+1);
86+
| ------------------
87+
| | |
88+
| | this is expected to be expression
89+
| in this macro invocation
90+
|
91+
= 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
92+
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
93+
7294
note: trace_macro
7395
--> $DIR/trace_faulty_macros.rs:36:13
7496
|
@@ -80,6 +102,17 @@ LL | let a = pat_macro!();
80102
= note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }`
81103
= note: to `A { a: a, b: 0, c: _, .. }`
82104

83-
error: aborting due to 4 previous errors
105+
note: trace_macro
106+
--> $DIR/trace_faulty_macros.rs:53:5
107+
|
108+
LL | test!(let x = 1+1);
109+
| ^^^^^^^^^^^^^^^^^^
110+
|
111+
= note: expanding `test! { let x = 1 + 1 }`
112+
= note: to `test! ((x, 1 + 1))`
113+
= note: expanding `test! { (x, 1 + 1) }`
114+
= note: to `let x = 1 + 1 ;`
115+
116+
error: aborting due to 5 previous errors
84117

85118
For more information about this error, try `rustc --explain E0774`.

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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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)
Please sign in to comment.