From 76b04437be91069260c72a6d59d130a4e127a9a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 13:17:44 +1000 Subject: [PATCH] Remove `NtTy`. Notes about tests: - tests/ui/parser/macro/trait-object-macro-matcher.rs: the syntax error is duplicated, because it occurs now when parsing the decl macro input, and also when parsing the expanded decl macro. But this won't show up for normal users due to error de-duplication. - tests/ui/associated-consts/issue-93835.rs: similar, plus there are some additional errors about this very broken code. - The changes to metavariable descriptions in #132629 are now visible in error message for several tests. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 7 +-- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ compiler/rustc_parse/src/parser/mod.rs | 33 +++++++++++--- .../rustc_parse/src/parser/nonterminal.rs | 7 +-- compiler/rustc_parse/src/parser/path.rs | 17 ++++---- compiler/rustc_parse/src/parser/ty.rs | 14 ++++-- tests/ui/associated-consts/issue-93835.rs | 4 +- tests/ui/associated-consts/issue-93835.stderr | 43 +++++++++++++++---- tests/ui/macros/macro-interpolation.rs | 2 +- tests/ui/macros/macro-interpolation.stderr | 4 +- tests/ui/macros/syntax-error-recovery.rs | 4 +- tests/ui/macros/syntax-error-recovery.stderr | 4 +- tests/ui/parser/macro/issue-37113.rs | 2 +- tests/ui/parser/macro/issue-37113.stderr | 4 +- .../macro/trait-object-macro-matcher.rs | 1 + .../macro/trait-object-macro-matcher.stderr | 10 ++++- 19 files changed, 112 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index a2923d6448ae..346edc87c86b 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -203,7 +203,6 @@ fn tokens(&self) -> Option<&LazyAttrTokenStream> { 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 @@ fn tokens_mut(&mut self) -> Option<&mut Option> { 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 47cf77cefa7b..40b29fdba250 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -907,7 +907,6 @@ fn visit_nonterminal(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 661f2c3eca24..8ac6dc3b4d8c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -659,7 +659,6 @@ pub fn can_begin_pattern(&self, pat_kind: NtPatKind) -> bool { | NtMeta(..) | NtPat(..) | NtPath(..) - | NtTy(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | @@ -688,7 +687,7 @@ pub fn can_begin_type(&self) -> bool { 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), NtPat(P), NtExpr(P), - NtTy(P), NtLiteral(P), /// Stuff inside brackets for attributes NtMeta(P), @@ -1174,7 +1172,6 @@ pub fn use_span(&self) -> Span { 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 @@ pub fn descr(&self) -> &'static str { NtPat(..) => "pattern", NtExpr(..) => "expression", NtLiteral(..) => "literal", - NtTy(..) => "type", NtMeta(..) => "attribute", NtPath(..) => "path", } @@ -1213,7 +1209,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 1b6d825a22c8..1123ea3a449b 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -469,7 +469,6 @@ pub fn from_nonterminal_ast(nt: &Nonterminal) -> 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 1723b47798b0..fa0c2c7da781 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 ecbc4e396cee..4b26100c46de 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 @@ fn check_noexpect(&self, tok: &TokenKind) -> bool { 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), Vis(P), /// 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 f102821adf7c..e9cf8f1bbba9 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -51,7 +51,6 @@ fn nt_may_be_ident(nt: &Nonterminal) -> bool { NtStmt(_) | NtPat(_) | NtExpr(_) - | NtTy(_) | NtLiteral(_) // `true`, `false` | NtMeta(_) | NtPath(_) => true, @@ -100,7 +99,7 @@ fn nt_may_be_ident(nt: &Nonterminal) -> bool { 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 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN 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 b241aa892db9..b68eb9c99f52 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -2,7 +2,7 @@ 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 @@ pub(super) fn parse_path_inner( 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 dc5919b3630c..c78c7bff9b57 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 @@ 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 @@ pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P> ) } - /// 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> { self.parse_ty_common( AllowPlus::Yes, @@ -247,7 +248,12 @@ fn parse_ty_common( ) -> PResult<'a, P> { 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 9cc33d53f9cd..048681f04778 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>); //~^ 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 dfe78b3d1f38..e154ae25de26 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>); + | ^ + | + = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 +help: use a double colon instead + | +LL | type_ascribe!(p, a>); + | + + error[E0425]: cannot find value `p` in this scope --> $DIR/issue-93835.rs:4:19 | @@ -10,12 +22,6 @@ error[E0412]: cannot find type `a` in this scope LL | type_ascribe!(p, a>); | ^ not found in this scope -error[E0405]: cannot find trait `p` in this scope - --> $DIR/issue-93835.rs:4:26 - | -LL | type_ascribe!(p, a>); - | ^ not found in this scope - error[E0658]: associated const equality is incomplete --> $DIR/issue-93835.rs:4:28 | @@ -26,7 +32,26 @@ LL | type_ascribe!(p, a>); = 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: aborting due to 4 previous errors +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 + | +LL | type_ascribe!(p, a>); + | ^^^ + | + = note: see issue #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` -Some errors have detailed explanations: E0405, E0412, E0425, E0658. -For more information about an error, try `rustc --explain E0405`. +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p` + --> $DIR/issue-93835.rs:4:24 + | +LL | type_ascribe!(p, a>); + | ^ use of unresolved module or unlinked crate `p` + | + = help: you might be missing a crate named `p` + +error: aborting due to 6 previous errors + +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 48c1f19e777f..b5d2322c8052 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 e6b39dfef858..bc24a1586129 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, ::Owned); | ----------------------------- diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index 016e4def2849..6cf9d54e8263 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -9,8 +9,8 @@ pub enum TokenKind { } }; } -//~^^^^^ 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 `` diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 3cfbd8ce82b5..61758fb9d7dc 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 = `, `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 0044aa5610f5..e0957542f8f1 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 1f2fe23106ae..560329df5ccb 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 560195977d03..d4ec199070e7 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 40082564bad4..81dca6f71c43 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`.