diff options
| author | bors <bors@rust-lang.org> | 2023-11-17 20:57:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-11-17 20:57:12 +0000 |
| commit | 2831701757eb7b3105eda26a306c2f3a97e2664b (patch) | |
| tree | 578877e9b318c070b1b4880e12d302250044ac57 /compiler | |
| parent | f6dcaee23f274dd18b391b2f0f70df6e98f1c3b2 (diff) | |
| parent | 4e418805da5867bc48d82ba1cc7eff2ba68be575 (diff) | |
| download | rust-2831701757eb7b3105eda26a306c2f3a97e2664b.tar.gz rust-2831701757eb7b3105eda26a306c2f3a97e2664b.zip | |
Auto merge of #114292 - estebank:issue-71039, r=b-naber
More detail when expecting expression but encountering bad macro argument
On nested macro invocations where the same macro fragment changes fragment type from one to the next, point at the chain of invocations and at the macro fragment definition place, explaining that the change has occurred.
Fix #71039.
```
error: expected expression, found pattern `1 + 1`
--> $DIR/trace_faulty_macros.rs:49:37
|
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
| ------- -- this is interpreted as expression, but it is expected to be pattern
| |
| this macro fragment matcher is expression
...
LL | (($p:pat, $e:pat)) => {let $p = $e;};
| ------ ^^ expected expression
| |
| this macro fragment matcher is pattern
...
LL | test!(let x = 1+1);
| ------------------
| | |
| | this is expected to be expression
| in this macro invocation
|
= 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
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
```
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/attr/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/token.rs | 53 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/tokenstream.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_ast_pretty/src/pprust/state.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/diagnostics.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/macro_parser.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/proc_macro.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/proc_macro_server.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 58 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/stmt.rs | 2 |
18 files changed, 144 insertions, 57 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index be7d1b207bc..152ef4bcbfd 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -342,7 +342,7 @@ impl MetaItem { let span = span.with_hi(segments.last().unwrap().ident.span.hi()); Path { span, segments, tokens: None } } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt { + Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &nt.0 { token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 7c0a78253a2..541b9872922 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -764,7 +764,10 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) { return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { - visit_nonterminal(Lrc::make_mut(nt), vis); + let nt = Lrc::make_mut(nt); + let (nt, sp) = (&mut nt.0, &mut nt.1); + vis.visit_span(sp); + visit_nonterminal(nt, vis); } _ => {} } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 707238e6c02..3189fcf7ff9 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -110,7 +110,7 @@ impl Lit { Ident(name, false) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), Interpolated(ref nt) - if let NtExpr(expr) | NtLiteral(expr) = &**nt + if let NtExpr(expr) | NtLiteral(expr) = &nt.0 && let ast::ExprKind::Lit(token_lit) = expr.kind => { Some(token_lit) @@ -314,7 +314,7 @@ pub enum TokenKind { /// - It prevents `Token` from implementing `Copy`. /// It adds complexity and likely slows things down. Please don't add new /// occurrences of this token kind! - Interpolated(Lrc<Nonterminal>), + Interpolated(Lrc<(Nonterminal, Span)>), /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) @@ -422,7 +422,7 @@ impl Token { /// if they keep spans or perform edition checks. pub fn uninterpolated_span(&self) -> Span { match &self.kind { - Interpolated(nt) => nt.span(), + Interpolated(nt) => nt.0.use_span(), _ => self.span, } } @@ -465,7 +465,7 @@ impl Token { ModSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | + Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) | NtExpr(..) | NtBlock(..) | NtPath(..)), @@ -489,7 +489,7 @@ impl Token { | DotDot | DotDotDot | DotDotEq // ranges | Lt | BinOp(Shl) // associated path | ModSep => true, // global path - Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | + Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) | NtPat(..) | NtBlock(..) | NtPath(..)), @@ -512,7 +512,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path ModSep => true, // global path - Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)), + Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)), // For anonymous structs or unions, which only appear in specific positions // (type of struct fields or union fields), we don't consider them as regular types _ => false, @@ -523,7 +523,7 @@ impl Token { pub fn can_begin_const_arg(&self) -> bool { match self.kind { OpenDelim(Delimiter::Brace) => true, - Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + Interpolated(ref nt) => matches!(&nt.0, NtExpr(..) | NtBlock(..) | NtLiteral(..)), _ => self.can_begin_literal_maybe_minus(), } } @@ -577,7 +577,7 @@ impl Token { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { + Interpolated(ref nt) => match &nt.0 { NtLiteral(_) => true, NtExpr(e) => match &e.kind { ast::ExprKind::Lit(_) => true, @@ -598,9 +598,9 @@ impl Token { /// otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match &self.kind { - Interpolated(nt) => match **nt { + Interpolated(nt) => match &nt.0 { NtIdent(ident, is_raw) => { - Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) + Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span)) } NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), _ => Cow::Borrowed(self), @@ -615,8 +615,8 @@ impl Token { // We avoid using `Token::uninterpolate` here because it's slow. match &self.kind { &Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)), - Interpolated(nt) => match **nt { - NtIdent(ident, is_raw) => Some((ident, is_raw)), + Interpolated(nt) => match &nt.0 { + NtIdent(ident, is_raw) => Some((*ident, *is_raw)), _ => None, }, _ => None, @@ -629,8 +629,8 @@ impl Token { // We avoid using `Token::uninterpolate` here because it's slow. match &self.kind { &Lifetime(name) => Some(Ident::new(name, self.span)), - Interpolated(nt) => match **nt { - NtLifetime(ident) => Some(ident), + Interpolated(nt) => match &nt.0 { + NtLifetime(ident) => Some(*ident), _ => None, }, _ => None, @@ -656,7 +656,7 @@ impl Token { /// Returns `true` if the token is an interpolated path. fn is_path(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtPath(..) = **nt + && let NtPath(..) = &nt.0 { return true; } @@ -669,7 +669,7 @@ impl Token { /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt + && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &nt.0 { return true; } @@ -680,7 +680,7 @@ impl Token { /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtBlock(..) = **nt + && let NtBlock(..) = &nt.0 { return true; } @@ -928,7 +928,7 @@ impl fmt::Display for NonterminalKind { } impl Nonterminal { - pub fn span(&self) -> Span { + pub fn use_span(&self) -> Span { match self { NtItem(item) => item.span, NtBlock(block) => block.span, @@ -942,6 +942,23 @@ impl Nonterminal { NtVis(vis) => vis.span, } } + + pub fn descr(&self) -> &'static str { + match self { + NtItem(..) => "item", + NtBlock(..) => "block", + NtStmt(..) => "statement", + NtPat(..) => "pattern", + NtExpr(..) => "expression", + NtLiteral(..) => "literal", + NtTy(..) => "type", + NtIdent(..) => "identifier", + NtLifetime(..) => "lifetime", + NtMeta(..) => "attribute", + NtPath(..) => "path", + NtVis(..) => "visibility", + } + } } impl PartialEq for Nonterminal { diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 23b8f9c12d8..48854bbae24 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -477,13 +477,13 @@ impl TokenStream { fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { match &token.kind { - token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = **nt => { + token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => { TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing) } token::Interpolated(nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), Delimiter::Invisible, - TokenStream::from_nonterminal_ast(nt).flattened(), + TokenStream::from_nonterminal_ast(&nt.0).flattened(), ), _ => TokenTree::Token(token.clone(), spacing), } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 48421ff7140..0962cb1b8d4 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -825,7 +825,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere } token::Eof => "<eof>".into(), - token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(), + token::Interpolated(ref nt) => self.nonterminal_to_string(&nt.0).into(), } } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index e060375646c..64cf9ced9c1 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -67,6 +67,12 @@ pub(super) fn failed_to_match_macro<'cx>( && (matches!(expected_token.kind, TokenKind::Interpolated(_)) || matches!(token.kind, TokenKind::Interpolated(_))) { + if let TokenKind::Interpolated(node) = &expected_token.kind { + err.span_label(node.1, ""); + } + if let TokenKind::Interpolated(node) = &token.kind { + err.span_label(node.1, ""); + } err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information"); diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 7e85beaadcb..1c78232a0f3 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -397,7 +397,7 @@ pub(crate) enum NamedMatch { MatchedTokenTree(rustc_ast::tokenstream::TokenTree), // A metavar match of any type other than `tt`. - MatchedNonterminal(Lrc<Nonterminal>), + MatchedNonterminal(Lrc<(Nonterminal, rustc_span::Span)>), } /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) @@ -692,7 +692,7 @@ impl TtParser { Ok(nt) => nt, }; let m = match nt { - ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), + ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))), ParseNtResult::Tt(tt) => MatchedTokenTree(tt), }; mp.push_match(next_metavar, seq_depth, m); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index c617cd76e3c..39a16259fa6 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -126,7 +126,7 @@ impl MultiItemModifier for DeriveProcMacro { Annotatable::Stmt(stmt) => token::NtStmt(stmt), _ => unreachable!(), }; - TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP) + TokenStream::token_alone(token::Interpolated(Lrc::new((nt, span))), DUMMY_SP) } else { item.to_tokens() }; diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index aa4c7a53135..41ec0ed84f7 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -226,18 +226,23 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre })); } - Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => trees - .push(TokenTree::Ident(Ident { sym: ident.name, is_raw, span: ident.span })), + Interpolated(ref nt) if let NtIdent(ident, is_raw) = &nt.0 => { + trees.push(TokenTree::Ident(Ident { + sym: ident.name, + is_raw: *is_raw, + span: ident.span, + })) + } Interpolated(nt) => { - let stream = TokenStream::from_nonterminal_ast(&nt); + let stream = TokenStream::from_nonterminal_ast(&nt.0); // A hack used to pass AST fragments to attribute and derive // macros as a single nonterminal token instead of a token // stream. Such token needs to be "unwrapped" and not // represented as a delimited group. // FIXME: It needs to be removed, but there are some // compatibility issues (see #73345). - if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.sess()) { + if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) { trees.extend(Self::from_internal((stream, rustc))); } else { trees.push(TokenTree::Group(Group { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 104de47b97d..bad7c19cc27 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -249,7 +249,7 @@ impl<'a> Parser<'a> { /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> { let item = match &self.token.kind { - token::Interpolated(nt) => match &**nt { + token::Interpolated(nt) => match &nt.0 { Nonterminal::NtMeta(item) => Some(item.clone().into_inner()), _ => None, }, @@ -369,7 +369,7 @@ impl<'a> Parser<'a> { /// ``` pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match &self.token.kind { - token::Interpolated(nt) => match &**nt { + token::Interpolated(nt) => match &nt.0 { token::NtMeta(e) => Some(e.clone()), _ => None, }, diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f2acb70ac45..262e7b899ad 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -24,11 +24,12 @@ use crate::parser; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; +use rustc_ast::tokenstream::AttrTokenTree; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block, - BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind, - Path, PathSegment, QSelf, Ty, TyKind, + BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat, + PatKind, Path, PathSegment, QSelf, Ty, TyKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -2252,6 +2253,59 @@ impl<'a> Parser<'a> { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); + + // Walk the chain of macro expansions for the current token to point at how the original + // code was interpreted. This helps the user realize when a macro argument of one type is + // later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat` + // in a subsequent macro invocation (#71039). + let mut tok = self.token.clone(); + let mut labels = vec![]; + while let TokenKind::Interpolated(node) = &tok.kind { + let tokens = node.0.tokens(); + labels.push(node.clone()); + if let Some(tokens) = tokens + && let tokens = tokens.to_attr_token_stream() + && let tokens = tokens.0.deref() + && let [AttrTokenTree::Token(token, _)] = &tokens[..] + { + tok = token.clone(); + } else { + break; + } + } + let mut iter = labels.into_iter().peekable(); + let mut show_link = false; + while let Some(node) = iter.next() { + let descr = node.0.descr(); + if let Some(next) = iter.peek() { + let next_descr = next.0.descr(); + if next_descr != descr { + err.span_label(next.1, format!("this macro fragment matcher is {next_descr}")); + err.span_label(node.1, format!("this macro fragment matcher is {descr}")); + err.span_label( + next.0.use_span(), + format!("this is expected to be {next_descr}"), + ); + err.span_label( + node.0.use_span(), + format!( + "this is interpreted as {}, but it is expected to be {}", + next_descr, descr, + ), + ); + show_link = true; + } else { + err.span_label(node.1, ""); + } + } + } + if show_link { + err.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", + ); + } err } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index bfd7e8ef4d0..d8e99d34016 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -46,7 +46,7 @@ use thin_vec::{thin_vec, ThinVec}; macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { + match &nt.0 { token::NtExpr(e) | token::NtLiteral(e) => { let e = e.clone(); $p.bump(); @@ -1952,7 +1952,7 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { if let token::Interpolated(nt) = &self.token.kind - && let token::NtExpr(e) | token::NtLiteral(e) = &**nt + && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 801860c2123..d124ea571ab 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -123,7 +123,7 @@ impl<'a> Parser<'a> { // Don't use `maybe_whole` so that we have precise control // over when we bump the parser if let token::Interpolated(nt) = &self.token.kind - && let token::NtItem(item) = &**nt + && let token::NtItem(item) = &nt.0 { let mut item = item.clone(); self.bump(); @@ -2750,7 +2750,7 @@ impl<'a> Parser<'a> { fn is_named_param(&self) -> bool { let offset = match &self.token.kind { - token::Interpolated(nt) => match **nt { + token::Interpolated(nt) => match &nt.0 { token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), _ => 0, }, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 833381a6503..9bd436f01ac 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -93,7 +93,7 @@ pub enum TrailingToken { macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { if let token::Interpolated(nt) = &$p.token.kind { - if let token::$constructor(x) = &**nt { + if let token::$constructor(x) = &nt.0 { let $x = x.clone(); $p.bump(); return Ok($e); @@ -110,7 +110,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { && $self.may_recover() && $self.look_ahead(1, |t| t == &token::ModSep) && let token::Interpolated(nt) = &$self.token.kind - && let token::NtTy(ty) = &**nt + && let token::NtTy(ty) = &nt.0 { let ty = ty.clone(); $self.bump(); @@ -367,12 +367,14 @@ impl TokenDescription { pub(super) fn token_descr(token: &Token) -> String { let name = pprust::token_to_string(token).to_string(); - let kind = TokenDescription::from_token(token).map(|kind| match kind { - TokenDescription::ReservedIdentifier => "reserved identifier", - TokenDescription::Keyword => "keyword", - TokenDescription::ReservedKeyword => "reserved keyword", - TokenDescription::DocComment => "doc comment", - }); + let kind = match (TokenDescription::from_token(token), &token.kind) { + (Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"), + (Some(TokenDescription::Keyword), _) => Some("keyword"), + (Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"), + (Some(TokenDescription::DocComment), _) => Some("doc comment"), + (None, TokenKind::Interpolated(node)) => Some(node.0.descr()), + (None, _) => None, + }; if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") } } @@ -662,7 +664,7 @@ impl<'a> Parser<'a> { fn check_inline_const(&self, dist: usize) -> bool { self.is_keyword_ahead(dist, &[kw::Const]) && self.look_ahead(dist + 1, |t| match &t.kind { - token::Interpolated(nt) => matches!(**nt, token::NtBlock(..)), + token::Interpolated(nt) => matches!(&nt.0, token::NtBlock(..)), token::OpenDelim(Delimiter::Brace) => true, _ => false, }) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 025b0615a7e..06cc39fbb5a 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -50,12 +50,12 @@ impl<'a> Parser<'a> { NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), NonterminalKind::Vis => match token.kind { // The follow-set of :vis + "priv" keyword + interpolated - token::Comma | token::Ident(..) | token::Interpolated(..) => true, + token::Comma | token::Ident(..) | token::Interpolated(_) => true, _ => token.can_begin_type(), }, NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, - token::Interpolated(nt) => match **nt { + token::Interpolated(nt) => match &nt.0 { NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_) | NtVis(_) => false, @@ -64,7 +64,7 @@ impl<'a> Parser<'a> { }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::ModSep | token::Ident(..) => true, - token::Interpolated(nt) => may_be_ident(nt), + token::Interpolated(nt) => may_be_ident(&nt.0), _ => false, }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { @@ -75,7 +75,7 @@ impl<'a> Parser<'a> { token::BinOp(token::And) | // reference token::BinOp(token::Minus) | // negative literal token::AndAnd | // double reference - token::Literal(..) | // literal + token::Literal(_) | // literal token::DotDot | // range pattern (future compat) token::DotDotDot | // range pattern (future compat) token::ModSep | // path @@ -83,14 +83,14 @@ impl<'a> Parser<'a> { token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), - token::Interpolated(nt) => may_be_ident(nt), + token::Interpolated(nt) => may_be_ident(&nt.0), _ => false, } } NonterminalKind::Lifetime => match &token.kind { token::Lifetime(_) => true, token::Interpolated(nt) => { - matches!(**nt, NtLifetime(_)) + matches!(&nt.0, NtLifetime(_)) } _ => false, }, @@ -191,7 +191,7 @@ impl<'a> Parser<'a> { panic!( "Missing tokens for nt {:?} at {:?}: {:?}", nt, - nt.span(), + nt.use_span(), pprust::nonterminal_to_string(&nt) ); } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index f6e1a21bd26..5cec3f5762d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -592,7 +592,7 @@ impl<'a> Parser<'a> { // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. if let token::Interpolated(nt) = &self.token.kind { - if let token::NtPat(_) = **nt { + if let token::NtPat(..) = &nt.0 { self.expected_ident_found_err().emit(); } } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 8626dbe40af..0f4ba9617c6 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -185,7 +185,7 @@ impl<'a> Parser<'a> { }); if let token::Interpolated(nt) = &self.token.kind { - if let token::NtTy(ty) = &**nt { + if let token::NtTy(ty) = &nt.0 { if let ast::TyKind::Path(None, path) = &ty.kind { let path = path.clone(); self.bump(); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index aa939a71d63..d1c5ca4b93c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -53,7 +53,7 @@ impl<'a> Parser<'a> { // Don't use `maybe_whole` so that we have precise control // over when we bump the parser if let token::Interpolated(nt) = &self.token.kind - && let token::NtStmt(stmt) = &**nt + && let token::NtStmt(stmt) = &nt.0 { let mut stmt = stmt.clone(); self.bump(); |
