From c7981d64117a4e1228e94ddc47a16d171a011c0b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 12:17:09 +1000 Subject: Remove `NtVis`. We now use invisible delimiters for expanded `vis` fragments, instead of `Token::Interpolated`. --- compiler/rustc_parse/src/parser/mod.rs | 46 ++++++++++++++++++++++++-- compiler/rustc_parse/src/parser/nonterminal.rs | 13 ++++---- 2 files changed, 50 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1de452dcf39..ecbc4e396ce 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -721,6 +721,43 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) } } + /// Consume a sequence produced by a metavar expansion, if present. + fn eat_metavar_seq( + &mut self, + mv_kind: MetaVarKind, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f) + } + + /// A slightly more general form of `eat_metavar_seq`, for use with the + /// `MetaVarKind` variants that have parameters, where an exact match isn't + /// desired. + fn eat_metavar_seq_with_matcher( + &mut self, + match_mv_kind: impl Fn(MetaVarKind) -> bool, + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + if let token::OpenDelim(delim) = self.token.kind + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + let res = f(self).expect("failed to reparse {mv_kind:?}"); + if let token::CloseDelim(delim) = self.token.kind + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + Some(res) + } else { + panic!("no close delim when reparsing {mv_kind:?}"); + } + } else { + None + } + } + /// Is the given keyword `kw` followed by a non-reserved identifier? fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) @@ -1455,7 +1492,11 @@ impl<'a> Parser<'a> { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - maybe_whole!(self, NtVis, |vis| vis.into_inner()); + if let Some(vis) = self + .eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes)) + { + return Ok(vis); + } if !self.eat_keyword(exp!(Pub)) { // We need a span for our `Spanned`, but there's inherently no @@ -1683,7 +1724,8 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Vis(P), - /// This case will eventually be removed, along with `Token::Interpolate`. + /// This variant will eventually be removed, along with `Token::Interpolate`. Nt(Arc), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index eefdb641da2..f102821adf7 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -56,9 +56,7 @@ impl<'a> Parser<'a> { | NtMeta(_) | NtPath(_) => true, - NtItem(_) - | NtBlock(_) - | NtVis(_) => false, + NtItem(_) | NtBlock(_) => false, } } @@ -88,7 +86,7 @@ impl<'a> Parser<'a> { NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), NonterminalKind::Vis => match token.kind { - // The follow-set of :vis + "priv" keyword + interpolated + // The follow-set of :vis + "priv" keyword + interpolated/metavar-expansion. token::Comma | token::Ident(..) | token::NtIdent(..) @@ -102,7 +100,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false, + NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -208,8 +206,9 @@ impl<'a> Parser<'a> { } NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)), NonterminalKind::Vis => { - NtVis(P(self - .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) + return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { + this.parse_visibility(FollowedByType::Yes) + })?))); } NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still -- cgit 1.4.1-3-g733a5 From 76b04437be91069260c72a6d59d130a4e127a9a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 13:17:44 +1000 Subject: 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 ++++++++++++++++--- compiler/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 | 37 ++++++++++++++++++---- 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 +-- .../ui/parser/macro/trait-object-macro-matcher.rs | 1 + .../parser/macro/trait-object-macro-matcher.stderr | 10 +++++- 19 files changed, 109 insertions(+), 48 deletions(-) (limited to 'compiler/rustc_parse/src/parser') 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(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), NtPat(P), NtExpr(P), - NtTy(P), NtLiteral(P), /// Stuff inside brackets for attributes NtMeta(P), @@ -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), 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 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> { self.parse_ty_common( AllowPlus::Yes, @@ -247,7 +248,12 @@ impl<'a> Parser<'a> { ) -> 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 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>); //~^ 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>); + | ^ + | + = 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,11 +22,15 @@ 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 +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 | LL | type_ascribe!(p, a>); - | ^ not found in this scope + | ^^^ + | + = 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 error[E0658]: associated const equality is incomplete --> $DIR/issue-93835.rs:4:28 @@ -25,8 +41,17 @@ 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` + +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 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, ::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 `` 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 = `, `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`. -- cgit 1.4.1-3-g733a5 From 0f490b040af82820e423a7e71e0e2e1f6ca7ab57 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Feb 2025 16:47:07 +1100 Subject: Avoid snapshotting the parser in `parse_path_inner`. --- compiler/rustc_ast/src/token.rs | 10 ++++++---- compiler/rustc_expand/src/mbe/transcribe.rs | 5 +++-- compiler/rustc_parse/src/parser/mod.rs | 7 +++---- compiler/rustc_parse/src/parser/nonterminal.rs | 4 ++-- compiler/rustc_parse/src/parser/path.rs | 15 ++++++--------- compiler/rustc_parse/src/parser/ty.rs | 7 ++++--- 6 files changed, 24 insertions(+), 24 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 8ac6dc3b4d8..97d121909f8 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -84,7 +84,9 @@ pub enum MetaVarKind { // This field is needed for `Token::can_begin_string_literal`. can_begin_string_literal: bool, }, - Ty, + Ty { + is_path: bool, + }, Ident, Lifetime, Literal, @@ -104,7 +106,7 @@ impl fmt::Display for MetaVarKind { MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param, MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr, MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021, - MetaVarKind::Ty => sym::ty, + MetaVarKind::Ty { .. } => sym::ty, MetaVarKind::Ident => sym::ident, MetaVarKind::Lifetime => sym::lifetime, MetaVarKind::Literal => sym::literal, @@ -666,7 +668,7 @@ impl Token { MetaVarKind::Meta | MetaVarKind::Pat(_) | MetaVarKind::Path | - MetaVarKind::Ty + MetaVarKind::Ty { .. } ))) => true, _ => false, } @@ -689,7 +691,7 @@ impl Token { PathSep => true, // global path Interpolated(ref nt) => matches!(&**nt, NtPath(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - MetaVarKind::Ty | + MetaVarKind::Ty { .. } | MetaVarKind::Path ))) => true, // For anonymous structs or unions, which only appear in specific positions diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index fa0c2c7da78..721798b0ce4 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,13 +1,13 @@ use std::mem; use std::sync::Arc; -use rustc_ast::ExprKind; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; +use rustc_ast::{ExprKind, TyKind}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; @@ -323,7 +323,8 @@ pub(super) fn transcribe<'a>( TokenTree::token_alone(kind, sp) } MatchedSingle(ParseNtResult::Ty(ty)) => { - mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) + let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); + mk_delimited(MetaVarKind::Ty { is_path }, 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 4b26100c46d..bbd73dec2e4 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -117,14 +117,13 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq() + && let Some(mv_kind) = $self.token.is_metavar_seq() + && let token::MetaVarKind::Ty { .. } = mv_kind && $self.check_noexpect_past_close_delim(&token::PathSep) { // Reparse the type, then move to recovery. let ty = $self - .eat_metavar_seq(token::MetaVarKind::Ty, |this| { - this.parse_ty_no_question_mark_recover() - }) + .eat_metavar_seq(mv_kind, |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); diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index e9cf8f1bbba..f202f85752e 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -30,7 +30,7 @@ impl<'a> Parser<'a> { MetaVarKind::Stmt | MetaVarKind::Pat(_) | MetaVarKind::Expr { .. } - | MetaVarKind::Ty + | MetaVarKind::Ty { .. } | MetaVarKind::Literal // `true`, `false` | MetaVarKind::Meta | MetaVarKind::Path => true, @@ -108,7 +108,7 @@ impl<'a> Parser<'a> { | MetaVarKind::Literal => true, MetaVarKind::Item | MetaVarKind::Pat(_) - | MetaVarKind::Ty + | MetaVarKind::Ty { .. } | MetaVarKind::Meta | MetaVarKind::Path | MetaVarKind::Vis => false, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index b68eb9c99f5..c24305ea9a8 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -196,15 +196,12 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner())); - 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)); - } + // If we have a `ty` metavar in the form of a path, reparse it directly as a path, instead + // of reparsing it as a `ty` and then extracting the path. + if let Some(path) = self.eat_metavar_seq(MetaVarKind::Ty { is_path: true }, |this| { + this.parse_path(PathStyle::Type) + }) { + return Ok(reject_generics_if_mod_style(self, path)); } let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c78c7bff9b5..18af0a1c79a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -249,9 +249,10 @@ impl<'a> Parser<'a> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - if let Some(ty) = - self.eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) - { + if let Some(ty) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }), + |this| this.parse_ty_no_question_mark_recover(), + ) { return Ok(ty); } -- cgit 1.4.1-3-g733a5