about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/token.rs7
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs3
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs33
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs7
-rw-r--r--compiler/rustc_parse/src/parser/path.rs17
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs14
-rw-r--r--tests/ui/associated-consts/issue-93835.rs4
-rw-r--r--tests/ui/associated-consts/issue-93835.stderr37
-rw-r--r--tests/ui/macros/macro-interpolation.rs2
-rw-r--r--tests/ui/macros/macro-interpolation.stderr4
-rw-r--r--tests/ui/macros/syntax-error-recovery.rs4
-rw-r--r--tests/ui/macros/syntax-error-recovery.stderr4
-rw-r--r--tests/ui/parser/macro/issue-37113.rs2
-rw-r--r--tests/ui/parser/macro/issue-37113.stderr4
-rw-r--r--tests/ui/parser/macro/trait-object-macro-matcher.rs1
-rw-r--r--tests/ui/parser/macro/trait-object-macro-matcher.stderr10
19 files changed, 109 insertions, 48 deletions
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index a2923d6448a..346edc87c86 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -203,7 +203,6 @@ impl HasTokens for Nonterminal {
             Nonterminal::NtStmt(stmt) => stmt.tokens(),
             Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(),
             Nonterminal::NtPat(pat) => pat.tokens(),
-            Nonterminal::NtTy(ty) => ty.tokens(),
             Nonterminal::NtMeta(attr_item) => attr_item.tokens(),
             Nonterminal::NtPath(path) => path.tokens(),
             Nonterminal::NtBlock(block) => block.tokens(),
@@ -215,7 +214,6 @@ impl HasTokens for Nonterminal {
             Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
             Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
             Nonterminal::NtPat(pat) => pat.tokens_mut(),
-            Nonterminal::NtTy(ty) => ty.tokens_mut(),
             Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 47cf77cefa7..40b29fdba25 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -907,7 +907,6 @@ fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
         }),
         token::NtPat(pat) => vis.visit_pat(pat),
         token::NtExpr(expr) => vis.visit_expr(expr),
-        token::NtTy(ty) => vis.visit_ty(ty),
         token::NtLiteral(expr) => vis.visit_expr(expr),
         token::NtMeta(item) => {
             let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 661f2c3eca2..8ac6dc3b4d8 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -659,7 +659,6 @@ impl Token {
                     | NtMeta(..)
                     | NtPat(..)
                     | NtPath(..)
-                    | NtTy(..)
                 ),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Expr { .. } |
@@ -688,7 +687,7 @@ impl Token {
             Lifetime(..)                | // lifetime bound in trait object
             Lt | BinOp(Shl)             | // associated path
             PathSep                      => true, // global path
-            Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)),
+            Interpolated(ref nt) => matches!(&**nt, NtPath(..)),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Ty |
                 MetaVarKind::Path
@@ -1076,7 +1075,6 @@ pub enum Nonterminal {
     NtStmt(P<ast::Stmt>),
     NtPat(P<ast::Pat>),
     NtExpr(P<ast::Expr>),
-    NtTy(P<ast::Ty>),
     NtLiteral(P<ast::Expr>),
     /// Stuff inside brackets for attributes
     NtMeta(P<ast::AttrItem>),
@@ -1174,7 +1172,6 @@ impl Nonterminal {
             NtStmt(stmt) => stmt.span,
             NtPat(pat) => pat.span,
             NtExpr(expr) | NtLiteral(expr) => expr.span,
-            NtTy(ty) => ty.span,
             NtMeta(attr_item) => attr_item.span(),
             NtPath(path) => path.span,
         }
@@ -1188,7 +1185,6 @@ impl Nonterminal {
             NtPat(..) => "pattern",
             NtExpr(..) => "expression",
             NtLiteral(..) => "literal",
-            NtTy(..) => "type",
             NtMeta(..) => "attribute",
             NtPath(..) => "path",
         }
@@ -1213,7 +1209,6 @@ impl fmt::Debug for Nonterminal {
             NtStmt(..) => f.pad("NtStmt(..)"),
             NtPat(..) => f.pad("NtPat(..)"),
             NtExpr(..) => f.pad("NtExpr(..)"),
-            NtTy(..) => f.pad("NtTy(..)"),
             NtLiteral(..) => f.pad("NtLiteral(..)"),
             NtMeta(..) => f.pad("NtMeta(..)"),
             NtPath(..) => f.pad("NtPath(..)"),
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 1b6d825a22c..1123ea3a449 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -469,7 +469,6 @@ impl TokenStream {
             }
             Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt),
             Nonterminal::NtPat(pat) => TokenStream::from_ast(pat),
-            Nonterminal::NtTy(ty) => TokenStream::from_ast(ty),
             Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr),
             Nonterminal::NtPath(path) => TokenStream::from_ast(path),
             Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 1723b47798b..fa0c2c7da78 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -322,6 +322,9 @@ pub(super) fn transcribe<'a>(
                             let kind = token::NtLifetime(*ident, *is_raw);
                             TokenTree::token_alone(kind, sp)
                         }
+                        MatchedSingle(ParseNtResult::Ty(ty)) => {
+                            mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty))
+                        }
                         MatchedSingle(ParseNtResult::Vis(vis)) => {
                             mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis))
                         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ecbc4e396ce..4b26100c46d 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -117,12 +117,16 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
     ($self: expr, $allow_qpath_recovery: expr) => {
         if $allow_qpath_recovery
             && $self.may_recover()
-            && $self.look_ahead(1, |t| t == &token::PathSep)
-            && let token::Interpolated(nt) = &$self.token.kind
-            && let token::NtTy(ty) = &**nt
+            && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq()
+            && $self.check_noexpect_past_close_delim(&token::PathSep)
         {
-            let ty = ty.clone();
-            $self.bump();
+            // Reparse the type, then move to recovery.
+            let ty = $self
+                .eat_metavar_seq(token::MetaVarKind::Ty, |this| {
+                    this.parse_ty_no_question_mark_recover()
+                })
+                .expect("metavar seq ty");
+
             return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
         }
     };
@@ -614,6 +618,24 @@ impl<'a> Parser<'a> {
         self.token == *tok
     }
 
+    // Check the first token after the delimiter that closes the current
+    // delimited sequence. (Panics if used in the outermost token stream, which
+    // has no delimiters.) It uses a clone of the relevant tree cursor to skip
+    // past the entire `TokenTree::Delimited` in a single step, avoiding the
+    // need for unbounded token lookahead.
+    //
+    // Primarily used when `self.token` matches
+    // `OpenDelim(Delimiter::Invisible(_))`, to look ahead through the current
+    // metavar expansion.
+    fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool {
+        let mut tree_cursor = self.token_cursor.stack.last().unwrap().clone();
+        tree_cursor.bump();
+        matches!(
+            tree_cursor.curr(),
+            Some(TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok
+        )
+    }
+
     /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
     ///
     /// the main purpose of this function is to reduce the cluttering of the suggestions list
@@ -1724,6 +1746,7 @@ pub enum ParseNtResult {
     Tt(TokenTree),
     Ident(Ident, IdentIsRaw),
     Lifetime(Ident, IdentIsRaw),
+    Ty(P<ast::Ty>),
     Vis(P<ast::Visibility>),
 
     /// This variant will eventually be removed, along with `Token::Interpolate`.
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index f102821adf7..e9cf8f1bbba 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -51,7 +51,6 @@ impl<'a> Parser<'a> {
                 NtStmt(_)
                 | NtPat(_)
                 | NtExpr(_)
-                | NtTy(_)
                 | NtLiteral(_) // `true`, `false`
                 | NtMeta(_)
                 | NtPath(_) => true,
@@ -100,7 +99,7 @@ impl<'a> Parser<'a> {
                 token::NtLifetime(..) => true,
                 token::Interpolated(nt) => match &**nt {
                     NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
-                    NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false,
+                    NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false,
                 },
                 token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
                     MetaVarKind::Block
@@ -187,7 +186,9 @@ impl<'a> Parser<'a> {
                 NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
             }
             NonterminalKind::Ty => {
-                NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
+                return Ok(ParseNtResult::Ty(
+                    self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
+                ));
             }
             // this could be handled like a token, since it is one
             NonterminalKind::Ident => {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b241aa892db..b68eb9c99f5 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -2,7 +2,7 @@ use std::mem;
 
 use ast::token::IdentIsRaw;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, MetaVarKind, Token, TokenKind};
 use rustc_ast::{
     self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
     AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
@@ -196,13 +196,14 @@ impl<'a> Parser<'a> {
 
         maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
 
-        if let token::Interpolated(nt) = &self.token.kind {
-            if let token::NtTy(ty) = &**nt {
-                if let ast::TyKind::Path(None, path) = &ty.kind {
-                    let path = path.clone();
-                    self.bump();
-                    return Ok(reject_generics_if_mod_style(self, path));
-                }
+        if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() {
+            let mut snapshot = self.create_snapshot_for_diagnostic();
+            let ty = snapshot
+                .eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover())
+                .expect("metavar seq ty");
+            if let ast::TyKind::Path(None, path) = ty.into_inner().kind {
+                self.restore_snapshot(snapshot);
+                return Ok(reject_generics_if_mod_style(self, path));
             }
         }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index dc5919b3630..c78c7bff9b5 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
@@ -18,7 +18,7 @@ use crate::errors::{
     HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
     NestedCVariadicType, ReturnTypesUseThinArrow,
 };
-use crate::{exp, maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
 
 /// Signals whether parsing a type should allow `+`.
 ///
@@ -183,7 +183,8 @@ impl<'a> Parser<'a> {
         )
     }
 
-    /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
+    /// Parse a type without recovering `:` as `->` to avoid breaking code such
+    /// as `where fn() : for<'a>`.
     pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
@@ -247,7 +248,12 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
-        maybe_whole!(self, NtTy, |ty| ty);
+
+        if let Some(ty) =
+            self.eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover())
+        {
+            return Ok(ty);
+        }
 
         let lo = self.token.span;
         let mut impl_dyn_multi = false;
diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs
index 9cc33d53f9c..048681f0477 100644
--- a/tests/ui/associated-consts/issue-93835.rs
+++ b/tests/ui/associated-consts/issue-93835.rs
@@ -3,9 +3,11 @@
 fn e() {
     type_ascribe!(p, a<p:p<e=6>>);
     //~^ ERROR cannot find type `a` in this scope
+    //~| ERROR path separator must be a double colon
     //~| ERROR cannot find value
     //~| ERROR associated const equality
-    //~| ERROR cannot find trait `p` in this scope
+    //~| ERROR associated const equality
+    //~| ERROR failed to resolve: use of unresolved module or unlinked crate `p`
 }
 
 fn main() {}
diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr
index dfe78b3d1f3..e154ae25de2 100644
--- a/tests/ui/associated-consts/issue-93835.stderr
+++ b/tests/ui/associated-consts/issue-93835.stderr
@@ -1,3 +1,15 @@
+error: path separator must be a double colon
+  --> $DIR/issue-93835.rs:4:25
+   |
+LL |     type_ascribe!(p, a<p:p<e=6>>);
+   |                         ^
+   |
+   = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
+help: use a double colon instead
+   |
+LL |     type_ascribe!(p, a<p::p<e=6>>);
+   |                          +
+
 error[E0425]: cannot find value `p` in this scope
   --> $DIR/issue-93835.rs:4:19
    |
@@ -10,11 +22,15 @@ error[E0412]: cannot find type `a` in this scope
 LL |     type_ascribe!(p, a<p:p<e=6>>);
    |                      ^ not found in this scope
 
-error[E0405]: cannot find trait `p` in this scope
-  --> $DIR/issue-93835.rs:4:26
+error[E0658]: associated const equality is incomplete
+  --> $DIR/issue-93835.rs:4:28
    |
 LL |     type_ascribe!(p, a<p:p<e=6>>);
-   |                          ^ not found in this scope
+   |                            ^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: associated const equality is incomplete
   --> $DIR/issue-93835.rs:4:28
@@ -25,8 +41,17 @@ LL |     type_ascribe!(p, a<p:p<e=6>>);
    = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p`
+  --> $DIR/issue-93835.rs:4:24
+   |
+LL |     type_ascribe!(p, a<p:p<e=6>>);
+   |                        ^ use of unresolved module or unlinked crate `p`
+   |
+   = help: you might be missing a crate named `p`
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0405, E0412, E0425, E0658.
-For more information about an error, try `rustc --explain E0405`.
+Some errors have detailed explanations: E0412, E0425, E0433, E0658.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs
index 48c1f19e777..b5d2322c805 100644
--- a/tests/ui/macros/macro-interpolation.rs
+++ b/tests/ui/macros/macro-interpolation.rs
@@ -19,7 +19,7 @@ macro_rules! qpath {
 
     (ty, <$type:ty as $trait:ty>::$name:ident) => {
         <$type as $trait>::$name
-        //~^ ERROR expected identifier, found `!`
+        //~^ ERROR expected identifier, found metavariable
     };
 }
 
diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr
index e6b39dfef85..bc24a158612 100644
--- a/tests/ui/macros/macro-interpolation.stderr
+++ b/tests/ui/macros/macro-interpolation.stderr
@@ -1,8 +1,8 @@
-error: expected identifier, found `!`
+error: expected identifier, found metavariable
   --> $DIR/macro-interpolation.rs:21:19
    |
 LL |         <$type as $trait>::$name
-   |                   ^^^^^^ expected identifier
+   |                   ^^^^^^ expected identifier, found metavariable
 ...
 LL |     let _: qpath!(ty, <str as !>::Owned);
    |            -----------------------------
diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs
index 016e4def284..6cf9d54e826 100644
--- a/tests/ui/macros/syntax-error-recovery.rs
+++ b/tests/ui/macros/syntax-error-recovery.rs
@@ -9,8 +9,8 @@ macro_rules! values {
         }
     };
 }
-//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)`
-//~| ERROR macro expansion ignores type `(String)` and any tokens following
+//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable
+//~| ERROR macro expansion ignores `ty` metavariable and any tokens following
 
 values!(STRING(1) as (String) => cfg(test),);
 //~^ ERROR expected one of `!` or `::`, found `<eof>`
diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr
index 3cfbd8ce82b..61758fb9d7d 100644
--- a/tests/ui/macros/syntax-error-recovery.stderr
+++ b/tests/ui/macros/syntax-error-recovery.stderr
@@ -1,4 +1,4 @@
-error: expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)`
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable
   --> $DIR/syntax-error-recovery.rs:7:26
    |
 LL |                 $token $($inner)? = $value,
@@ -10,7 +10,7 @@ LL | values!(STRING(1) as (String) => cfg(test),);
    = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
    = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: macro expansion ignores type `(String)` and any tokens following
+error: macro expansion ignores `ty` metavariable and any tokens following
   --> $DIR/syntax-error-recovery.rs:7:26
    |
 LL |                 $token $($inner)? = $value,
diff --git a/tests/ui/parser/macro/issue-37113.rs b/tests/ui/parser/macro/issue-37113.rs
index 0044aa5610f..e0957542f8f 100644
--- a/tests/ui/parser/macro/issue-37113.rs
+++ b/tests/ui/parser/macro/issue-37113.rs
@@ -1,7 +1,7 @@
 macro_rules! test_macro {
     ( $( $t:ty ),* $(),*) => {
         enum SomeEnum {
-            $( $t, )* //~ ERROR expected identifier, found `String`
+            $( $t, )* //~ ERROR expected identifier, found metavariable
         };
     };
 }
diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr
index 1f2fe23106a..560329df5cc 100644
--- a/tests/ui/parser/macro/issue-37113.stderr
+++ b/tests/ui/parser/macro/issue-37113.stderr
@@ -1,10 +1,10 @@
-error: expected identifier, found `String`
+error: expected identifier, found metavariable
   --> $DIR/issue-37113.rs:4:16
    |
 LL |         enum SomeEnum {
    |              -------- while parsing this enum
 LL |             $( $t, )*
-   |                ^^ expected identifier
+   |                ^^ expected identifier, found metavariable
 ...
 LL |     test_macro!(String,);
    |     -------------------- in this macro invocation
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs
index 560195977d0..d4ec199070e 100644
--- a/tests/ui/parser/macro/trait-object-macro-matcher.rs
+++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs
@@ -10,5 +10,6 @@ macro_rules! m {
 fn main() {
     m!('static);
     //~^ ERROR lifetime in trait object type must be followed by `+`
+    //~| ERROR lifetime in trait object type must be followed by `+`
     //~| ERROR at least one trait is required for an object type
 }
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr
index 40082564bad..81dca6f71c4 100644
--- a/tests/ui/parser/macro/trait-object-macro-matcher.stderr
+++ b/tests/ui/parser/macro/trait-object-macro-matcher.stderr
@@ -4,12 +4,20 @@ error: lifetime in trait object type must be followed by `+`
 LL |     m!('static);
    |        ^^^^^^^
 
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/trait-object-macro-matcher.rs:11:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0224]: at least one trait is required for an object type
   --> $DIR/trait-object-macro-matcher.rs:11:8
    |
 LL |     m!('static);
    |        ^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0224`.