diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index 1a271b0adef92..8ca7d5f925df4 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -45,7 +45,7 @@ impl AstLike for crate::token::Nonterminal { match self { Nonterminal::NtItem(item) => item.attrs(), Nonterminal::NtStmt(stmt) => stmt.attrs(), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.attrs(), + Nonterminal::NtLiteral(expr) => expr.attrs(), Nonterminal::NtPat(_) | Nonterminal::NtTy(_) | Nonterminal::NtMeta(_) @@ -60,7 +60,7 @@ impl AstLike for crate::token::Nonterminal { match self { Nonterminal::NtItem(item) => item.visit_attrs(f), Nonterminal::NtStmt(stmt) => stmt.visit_attrs(f), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.visit_attrs(f), + Nonterminal::NtLiteral(expr) => expr.visit_attrs(f), Nonterminal::NtPat(_) | Nonterminal::NtTy(_) | Nonterminal::NtMeta(_) @@ -75,7 +75,7 @@ impl AstLike for crate::token::Nonterminal { match self { Nonterminal::NtItem(item) => item.tokens_mut(), Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), + 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(), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index b425b5e2cca52..a21dbbc918729 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -776,7 +776,6 @@ pub fn visit_nonterminal(nt: &mut token::Nonterminal, vis: &mut T }) }), token::NtPat(pat) => vis.visit_pat(pat), - token::NtExpr(expr) => vis.visit_expr(expr), token::NtTy(ty) => vis.visit_ty(ty), token::NtIdent(ident, _is_raw) => vis.visit_ident(ident), token::NtLifetime(ident) => vis.visit_ident(ident), diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 6a21d6e159d33..5d444595ca32c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -379,7 +379,7 @@ impl Token { match self.uninterpolate().kind { Ident(name, is_raw) => ident_can_begin_expr(name, self.span, is_raw), // value name or keyword - OpenDelim(..) | // tuple, array or block + OpenDelim(..) | // tuple, array, block, or macro output Literal(..) | // literal Not | // operator not BinOp(Minus) | // unary minus @@ -394,7 +394,6 @@ impl Token { Lifetime(..) | // labeled loop Pound => true, // expression attributes Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | - NtExpr(..) | NtBlock(..) | NtPath(..)), _ => false, @@ -424,8 +423,8 @@ impl Token { /// Returns `true` if the token can appear at the start of a const param. pub fn can_begin_const_arg(&self) -> bool { match self.kind { - OpenDelim(Delimiter::Brace) => true, - Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + OpenDelim(Delimiter::Brace | Delimiter::Invisible { .. }) => true, + Interpolated(ref nt) => matches!(**nt, NtBlock(..) | NtLiteral(..)), _ => self.can_begin_literal_maybe_minus(), } } @@ -454,17 +453,8 @@ impl Token { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - ast::ExprKind::Unary(ast::UnOp::Neg, e) => { - matches!(&e.kind, ast::ExprKind::Lit(_)) - } - _ => false, - }, - _ => false, - }, + OpenDelim(Delimiter::Invisible { .. }) => true, + Interpolated(ref nt) => matches!(**nt, NtLiteral(_)), _ => false, } } @@ -541,9 +531,10 @@ impl Token { /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`? /// That is, is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? + // njn: need to do anything with this? pub fn is_whole_expr(&self) -> bool { if let Interpolated(ref nt) = self.kind - && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt + && let NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt { return true; } @@ -699,7 +690,6 @@ pub enum Nonterminal { NtBlock(P), NtStmt(P), NtPat(P), - NtExpr(P), NtTy(P), NtIdent(Ident, /* is_raw */ bool), NtLifetime(Ident), @@ -799,7 +789,7 @@ impl Nonterminal { NtBlock(block) => block.span, NtStmt(stmt) => stmt.span, NtPat(pat) => pat.span, - NtExpr(expr) | NtLiteral(expr) => expr.span, + NtLiteral(expr) => expr.span, NtTy(ty) => ty.span, NtIdent(ident, _) | NtLifetime(ident) => ident.span, NtMeta(attr_item) => attr_item.span(), @@ -832,7 +822,6 @@ impl fmt::Debug for Nonterminal { NtBlock(..) => f.pad("NtBlock(..)"), NtStmt(..) => f.pad("NtStmt(..)"), NtPat(..) => f.pad("NtPat(..)"), - NtExpr(..) => f.pad("NtExpr(..)"), NtTy(..) => f.pad("NtTy(..)"), NtIdent(..) => f.pad("NtIdent(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 9c18f55c03b4d..7e4c54b9a8b52 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -215,6 +215,8 @@ impl Lit { /// Converts arbitrary token into an AST literal. /// /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation. + // njn: need to do something here? It's hard to keep in sync with + // can_begin_literal_or_bool when a literal can span 3 tokens: `«`, `lit`, `»` pub fn from_token(token: &Token) -> Result { let lit = match token.uninterpolate().kind { token::Ident(name, false) if name.is_bool_lit() => { @@ -222,7 +224,7 @@ impl Lit { } token::Literal(lit) => lit, token::Interpolated(ref nt) => { - if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt + if let token::NtLiteral(expr) = &**nt && let ast::ExprKind::Lit(lit) = &expr.kind { return Ok(lit.clone()); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3805623a29f98..2d5e0b1214270 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -727,7 +727,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere fn nonterminal_to_string(&self, nt: &Nonterminal) -> String { match *nt { - token::NtExpr(ref e) => self.expr_to_string(e), token::NtMeta(ref e) => self.attr_item_to_string(e), token::NtTy(ref e) => self.ty_to_string(e), token::NtPath(ref e) => self.path_to_string(e), diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 7637bf7edc825..24ce602a1d1a2 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -173,13 +173,7 @@ impl CfgEval<'_, '_> { } _ => unreachable!(), }; - let nt = annotatable.into_nonterminal(); - - let mut orig_tokens = rustc_parse::nt_to_tokenstream( - &nt, - &self.cfg.sess.parse_sess, - CanSynthesizeMissingTokens::No, - ); + let mut orig_tokens = annotatable.into_tokens(&self.cfg.sess.parse_sess); // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) // to `None`-delimited groups containing the corresponding tokens. This diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 2b30ec601a0ce..8512f38b828f9 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; -use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; +use rustc_parse::{self, expr_to_tokenstream, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; @@ -119,8 +119,8 @@ impl Annotatable { token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) } Annotatable::Stmt(stmt) => token::NtStmt(stmt), - Annotatable::Expr(expr) => token::NtExpr(expr), - Annotatable::Arm(..) + Annotatable::Expr(..) + | Annotatable::Arm(..) | Annotatable::ExprField(..) | Annotatable::PatField(..) | Annotatable::GenericParam(..) @@ -131,8 +131,11 @@ impl Annotatable { } } - crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { - nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No) + pub fn into_tokens(self, sess: &ParseSess) -> TokenStream { + match self { + Annotatable::Expr(expr) => expr_to_tokenstream(&expr, sess, CanSynthesizeMissingTokens::No), + _ => nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No), + } } pub fn expect_item(self) -> P { diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 8f260e1cdb5c8..31eab3665601b 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -75,6 +75,7 @@ crate use ParseResult::*; use crate::mbe::{KleeneOp, TokenTree}; +use rustc_ast as ast; use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token}; use rustc_parse::parser::{NtOrTt, Parser}; use rustc_span::symbol::MacroRulesNormalizedIdent; @@ -344,6 +345,9 @@ crate enum NamedMatch { // A metavar match of type `tt`. MatchedTokenTree(rustc_ast::tokenstream::TokenTree), + // njn: comment + MatchedExpr(ast::ptr::P), // njn: quals + // A metavar match of any type other than `tt`. MatchedNonterminal(Lrc), } @@ -624,6 +628,7 @@ impl TtParser { let m = match nt { NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), NtOrTt::Tt(tt) => MatchedTokenTree(tt), + NtOrTt::Expr(e) => MatchedExpr(e), }; mp.push_match(next_metavar, seq_depth, m); mp.idx += 1; diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index fdd8dc93fc1a5..d414fa7e58545 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,12 +1,14 @@ use crate::base::ExtCtxt; -use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch}; +use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*}; use crate::mbe::{self, MetaVarExpr}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; +use rustc_ast::tokenstream::CanSynthesizeMissingTokens; +use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree, TreeAndSpacing}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, PResult}; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_parse::expr_to_tokenstream; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::Span; @@ -230,13 +232,31 @@ pub(super) fn transcribe<'a>( result.push(token.into()); } MatchedNonterminal(ref nt) => { + // njn: update comment // Other variables are emitted into the output stream as groups with // `Delimiter::Invisible` to maintain parsing priorities. // `Interpolated` is currently used for such groups in rustc parser. marker.visit_span(&mut sp); - let token = TokenTree::token(token::Interpolated(nt.clone()), sp); + let token = + TokenTree::token(token::Interpolated(nt.clone()), sp); result.push(token.into()); } + MatchedExpr(ref e) => { + // njn: update comment + let tts = expr_to_tokenstream( + e, + &cx.sess.parse_sess, + CanSynthesizeMissingTokens::No, + ); + marker.visit_span(&mut sp); + let tt = TokenTree::Delimited( + DelimSpan::from_single(sp), + // njn: `skip: false`! + Delimiter::Invisible { skip: false }, + tts, + ); + result.push((tt, Spacing::Alone)); + } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. return Err(cx.struct_span_err( @@ -306,7 +326,7 @@ fn lookup_cur_matched<'a>( let mut matched = matched; for &(idx, _) in repeats { match matched { - MatchedTokenTree(_) | MatchedNonterminal(_) => break, + MatchedTokenTree(_) | MatchedNonterminal(_) | MatchedExpr(_) => break, MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(), } } @@ -396,7 +416,7 @@ fn lockstep_iter_size( let name = MacroRulesNormalizedIdent::new(name); match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match matched { - MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained, + MatchedTokenTree(_) | MatchedNonterminal(_) | MatchedExpr(_) => LockstepIterSize::Unconstrained, MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name), }, _ => LockstepIterSize::Unconstrained, @@ -443,7 +463,8 @@ fn count_repetitions<'a>( sp: &DelimSpan, ) -> PResult<'a, usize> { match matched { - MatchedTokenTree(_) | MatchedNonterminal(_) => { + // njn: flip order of these arms, and in similar matches above + MatchedTokenTree(_) | MatchedNonterminal(_) | MatchedExpr(_) => { if declared_lhs_depth == 0 { return Err(cx.struct_span_err( sp.entire(), diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 28c2a63db27f8..41bc2d2fc2fb9 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -290,15 +290,15 @@ pub fn nt_to_tokenstream( Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()), Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()), Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()), - Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => { + Nonterminal::NtLiteral(ref expr) => { prepend_attrs(&expr.attrs, expr.tokens.as_ref()) } }; if let Some(tokens) = tokens { - return tokens; + tokens } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) { - return fake_token_stream(sess, nt); + fake_token_stream(sess, nt) } else { panic!( "Missing tokens for nt {:?} at {:?}: {:?}", @@ -309,6 +309,26 @@ pub fn nt_to_tokenstream( } } +// njn: comments +pub fn expr_to_tokenstream( + expr: &ast::Expr, + sess: &ParseSess, + synthesize_tokens: CanSynthesizeMissingTokens, +) -> TokenStream { + if let Some(tokens) = prepend_attrs(&expr.attrs, expr.tokens.as_ref()) { + tokens + } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) { + fake_token_stream_expr(sess, expr) + } else { + panic!( + "Missing tokens for expr {:?} at {:?}: {:?}", + expr, + expr.span, + pprust::expr_to_string(expr) + ); + } +} + fn prepend_attrs(attrs: &[Attribute], tokens: Option<&LazyTokenStream>) -> Option { let tokens = tokens?; if attrs.is_empty() { @@ -328,6 +348,12 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream { parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } +pub fn fake_token_stream_expr(sess: &ParseSess, expr: &ast::Expr) -> TokenStream { + let source = pprust::expr_to_string(expr); + let filename = FileName::macro_expansion_source_code(&source); + parse_stream_from_source_str(filename, source, sess, Some(expr.span)) +} + pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream { let source = pprust::crate_to_string_for_macros(krate); let filename = FileName::macro_expansion_source_code(&source); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6114e7aaa7bd7..f468e0f0a6002 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -34,7 +34,7 @@ macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = &$p.token.kind { match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { + token::NtLiteral(e) => { let e = e.clone(); $p.bump(); return Ok(e); @@ -652,7 +652,7 @@ impl<'a> Parser<'a> { // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), token::Literal(..) | token::Pound => true, - _ => t.is_whole_expr(), + _ => t.is_whole_expr(), // njn: ? }; self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) } @@ -1165,6 +1165,11 @@ impl<'a> Parser<'a> { let open_paren = self.token.span; let mut seq = self.parse_paren_expr_seq().map(|args| { + // njn: this is assuming that the function name is in a single + // token, and that `pref_token.span` covers that. But if the + // function name was expanded from a macro, it could have the form + // `«`, ident, `»`, and so prev_token.span doesn't go back far + // enough self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new()) }); if let Some(expr) = @@ -1305,6 +1310,8 @@ impl<'a> Parser<'a> { self.parse_lit_expr(attrs) } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { self.parse_tuple_parens_expr(attrs) + } else if self.check(&token::OpenDelim(Delimiter::Invisible { skip: false })) { + self.parse_invisibles_expr() } else if self.check(&token::OpenDelim(Delimiter::Brace)) { self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs) } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { @@ -1447,6 +1454,14 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + fn parse_invisibles_expr(&mut self) -> PResult<'a, P> { + // njn: reasonable? + self.expect(&token::OpenDelim(Delimiter::Invisible { skip: false }))?; + let expr = self.parse_expr()?; + self.expect(&token::CloseDelim(Delimiter::Invisible { skip: false }))?; + self.maybe_recover_from_bad_qpath(expr, true) + } + fn parse_array_or_repeat_expr( &mut self, attrs: AttrVec, @@ -1715,7 +1730,6 @@ impl<'a> Parser<'a> { self.parse_opt_lit().ok_or_else(|| { if let token::Interpolated(inner) = &self.token.kind { let expr = match inner.as_ref() { - token::NtExpr(expr) => Some(expr), token::NtLiteral(expr) => Some(expr), _ => None, }; @@ -1760,6 +1774,8 @@ impl<'a> Parser<'a> { } let token = recovered.as_ref().unwrap_or(&self.token); + // njn: this doesn't work if the token is `«`, causes the + // extern-abi-from-mac-literal-frag.rs failure, also my x.rs test match Lit::from_token(token) { Ok(lit) => { self.bump(); @@ -1929,6 +1945,15 @@ impl<'a> Parser<'a> { pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); + // njn: kind of weird to allow arbitrary expressions here! needed for + // macros, there are various checks later that will fail if it's not a + // literal + // njn: or could it be made more restrictive? E.g. allow invisibles + // around + if self.check(&token::OpenDelim(Delimiter::Invisible { skip: false })) { + return self.parse_invisibles_expr(); + } + let lo = self.token.span; let minus_present = self.eat(&token::BinOp(token::Minus)); let lit = self.parse_lit()?; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 543d889e798ec..8db5673fd732e 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -262,9 +262,6 @@ impl TokenCursor { #[inline(always)] fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) { loop { - // FIXME: we currently don't return `Delimiter` open/close delims. To fix #67062 we will - // need to, whereupon the `delim != Delimiter::Invisible` conditions below can be - // removed. if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing_ref() { match tree { &TokenTree::Token(ref token) => match (desugar_doc_comments, token) { @@ -1477,8 +1474,10 @@ pub enum FlatToken { Empty, } +// njn: rename #[derive(Debug)] pub enum NtOrTt { Nt(Nonterminal), Tt(TokenTree), + Expr(P), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 6974f318f9498..6d3681d3c31c2 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -101,8 +101,8 @@ impl<'a> Parser<'a> { /// site. #[inline] pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { - // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`) - // needs to have them force-captured here. + // Any `NonterminalKind` which stores its tokens (currently `Item` and + // `Expr`) needs to have them force-captured here. // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, @@ -110,6 +110,7 @@ impl<'a> Parser<'a> { let mut nt = match kind { // Note that TT is treated differently to all the others. NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())), + NonterminalKind::Expr => return Ok(NtOrTt::Expr(self.parse_expr_force_collect()?)), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => token::NtItem(item), None => { @@ -140,7 +141,6 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes token::NtLiteral( diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 57e5ab42f79d3..f18dc4763b0a8 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -87,81 +87,81 @@ fn test_block() { #[test] fn test_expr() { // ExprKind::Box - assert_eq!(stringify_expr!(box expr), "box expr"); + assert_eq!(stringify_expr!(box expr), "/*«*/ box expr /*»*/"); // ExprKind::Array - assert_eq!(stringify_expr!([]), "[]"); - assert_eq!(stringify_expr!([true]), "[true]"); - assert_eq!(stringify_expr!([true,]), "[true]"); - assert_eq!(stringify_expr!([true, true]), "[true, true]"); + assert_eq!(stringify_expr!([]), "/*«*/ [] /*»*/"); + assert_eq!(stringify_expr!([true]), "/*«*/ [true] /*»*/"); + assert_eq!(stringify_expr!([true,]), "/*«*/ [true,] /*»*/"); + assert_eq!(stringify_expr!([true, true]), "/*«*/ [true, true] /*»*/"); // ExprKind::Call - assert_eq!(stringify_expr!(f()), "f()"); - assert_eq!(stringify_expr!(f::()), "f::()"); - assert_eq!(stringify_expr!(f::<1>()), "f::<1>()"); - assert_eq!(stringify_expr!(f::<'a, u8, 1>()), "f::<'a, u8, 1>()"); - assert_eq!(stringify_expr!(f(true)), "f(true)"); - assert_eq!(stringify_expr!(f(true,)), "f(true)"); - assert_eq!(stringify_expr!(()()), "()()"); + assert_eq!(stringify_expr!(f()), "/*«*/ f() /*»*/"); + assert_eq!(stringify_expr!(f::()), "/*«*/ f :: < u8 > () /*»*/"); + assert_eq!(stringify_expr!(f::<1>()), "/*«*/ f :: < 1 > () /*»*/"); + assert_eq!(stringify_expr!(f::<'a, u8, 1>()), "/*«*/ f :: < 'a, u8, 1 > () /*»*/"); + assert_eq!(stringify_expr!(f(true)), "/*«*/ f(true) /*»*/"); + assert_eq!(stringify_expr!(f(true,)), "/*«*/ f(true,) /*»*/"); + assert_eq!(stringify_expr!(()()), "/*«*/ () () /*»*/"); // ExprKind::MethodCall - assert_eq!(stringify_expr!(x.f()), "x.f()"); - assert_eq!(stringify_expr!(x.f::()), "x.f::()"); + assert_eq!(stringify_expr!(x.f()), "/*«*/ x.f() /*»*/"); + assert_eq!(stringify_expr!(x.f::()), "/*«*/ x.f :: < u8 > () /*»*/"); // ExprKind::Tup - assert_eq!(stringify_expr!(()), "()"); - assert_eq!(stringify_expr!((true,)), "(true,)"); - assert_eq!(stringify_expr!((true, false)), "(true, false)"); - assert_eq!(stringify_expr!((true, false,)), "(true, false)"); + assert_eq!(stringify_expr!(()), "/*«*/ () /*»*/"); + assert_eq!(stringify_expr!((true,)), "/*«*/ (true,) /*»*/"); + assert_eq!(stringify_expr!((true, false)), "/*«*/ (true, false) /*»*/"); + assert_eq!(stringify_expr!((true, false,)), "/*«*/ (true, false,) /*»*/"); // ExprKind::Binary - assert_eq!(stringify_expr!(true || false), "true || false"); - assert_eq!(stringify_expr!(true || false && false), "true || false && false"); + assert_eq!(stringify_expr!(true || false), "/*«*/ true || false /*»*/"); + assert_eq!(stringify_expr!(true || false && false), "/*«*/ true || false && false /*»*/"); // ExprKind::Unary - assert_eq!(stringify_expr!(*expr), "*expr"); - assert_eq!(stringify_expr!(!expr), "!expr"); - assert_eq!(stringify_expr!(-expr), "-expr"); + assert_eq!(stringify_expr!(*expr), "/*«*/ * expr /*»*/"); + assert_eq!(stringify_expr!(!expr), "/*«*/ ! expr /*»*/"); + assert_eq!(stringify_expr!(-expr), "/*«*/ - expr /*»*/"); // ExprKind::Lit - assert_eq!(stringify_expr!('x'), "'x'"); - assert_eq!(stringify_expr!(1_000_i8), "1_000_i8"); - assert_eq!(stringify_expr!(1.00000000000000001), "1.00000000000000001"); + assert_eq!(stringify_expr!('x'), "/*«*/ 'x' /*»*/"); + assert_eq!(stringify_expr!(1_000_i8), "/*«*/ 1_000_i8 /*»*/"); + assert_eq!(stringify_expr!(1.00000000000000001), "/*«*/ 1.00000000000000001 /*»*/"); // ExprKind::Cast - assert_eq!(stringify_expr!(expr as T), "expr as T"); - assert_eq!(stringify_expr!(expr as T), "expr as T"); + assert_eq!(stringify_expr!(expr as T), "/*«*/ expr as T /*»*/"); + assert_eq!(stringify_expr!(expr as T), "/*«*/ expr as T < u8 > /*»*/"); // ExprKind::Type - assert_eq!(stringify_expr!(expr: T), "expr: T"); - assert_eq!(stringify_expr!(expr: T), "expr: T"); + assert_eq!(stringify_expr!(expr: T), "/*«*/ expr : T /*»*/"); + assert_eq!(stringify_expr!(expr: T), "/*«*/ expr : T < u8 > /*»*/"); // ExprKind::If - assert_eq!(stringify_expr!(if true {}), "if true {}"); + assert_eq!(stringify_expr!(if true {}), "/*«*/ if true {} /*»*/"); assert_eq!( stringify_expr!(if true { } else { }), - "if true {} else {}", + "/*«*/ if true {} else {} /*»*/", ); assert_eq!( stringify_expr!(if let true = true { } else { }), - "if let true = true {} else {}", + "/*«*/ if let true = true {} else {} /*»*/", ); assert_eq!( stringify_expr!(if true { } else if false { }), - "if true {} else if false {}", + "/*«*/ if true {} else if false {} /*»*/", ); assert_eq!( stringify_expr!(if true { } else if false { } else { }), - "if true {} else if false {} else {}", + "/*«*/ if true {} else if false {} else {} /*»*/", ); assert_eq!( stringify_expr!(if true { @@ -171,71 +171,71 @@ fn test_expr() { } else { 0 }), - "if true { return; } else if false { 0 } else { 0 }", + "/*«*/ if true { return ; } else if false { 0 } else { 0 } /*»*/", ); // ExprKind::While - assert_eq!(stringify_expr!(while true {}), "while true {}"); - assert_eq!(stringify_expr!('a: while true {}), "'a: while true {}"); - assert_eq!(stringify_expr!(while let true = true {}), "while let true = true {}"); + assert_eq!(stringify_expr!(while true {}), "/*«*/ while true {} /*»*/"); + assert_eq!(stringify_expr!('a: while true {}), "/*«*/ 'a : while true {} /*»*/"); + assert_eq!(stringify_expr!(while let true = true {}), "/*«*/ while let true = true {} /*»*/"); // ExprKind::ForLoop - assert_eq!(stringify_expr!(for _ in x {}), "for _ in x {}"); - assert_eq!(stringify_expr!('a: for _ in x {}), "'a: for _ in x {}"); + assert_eq!(stringify_expr!(for _ in x {}), "/*«*/ for _ in x {} /*»*/"); + assert_eq!(stringify_expr!('a: for _ in x {}), "/*«*/ 'a : for _ in x {} /*»*/"); // ExprKind::Loop - assert_eq!(stringify_expr!(loop {}), "loop {}"); - assert_eq!(stringify_expr!('a: loop {}), "'a: loop {}"); + assert_eq!(stringify_expr!(loop {}), "/*«*/ loop {} /*»*/"); + assert_eq!(stringify_expr!('a: loop {}), "/*«*/ 'a : loop {} /*»*/"); // ExprKind::Match - assert_eq!(stringify_expr!(match self {}), "match self {}"); + assert_eq!(stringify_expr!(match self {}), "/*«*/ match self {} /*»*/"); assert_eq!( stringify_expr!(match self { Ok => 1, }), - "match self { Ok => 1, }", + "/*«*/ match self { Ok => 1, } /*»*/", ); assert_eq!( stringify_expr!(match self { Ok => 1, Err => 0, }), - "match self { Ok => 1, Err => 0, }", + "/*«*/ match self { Ok => 1, Err => 0, } /*»*/", ); // ExprKind::Closure - assert_eq!(stringify_expr!(|| {}), "|| {}"); - assert_eq!(stringify_expr!(|x| {}), "|x| {}"); - assert_eq!(stringify_expr!(|x: u8| {}), "|x: u8| {}"); - assert_eq!(stringify_expr!(|| ()), "|| ()"); - assert_eq!(stringify_expr!(move || self), "move || self"); - assert_eq!(stringify_expr!(async || self), "async || self"); - assert_eq!(stringify_expr!(async move || self), "async move || self"); - assert_eq!(stringify_expr!(static || self), "static || self"); - assert_eq!(stringify_expr!(static move || self), "static move || self"); + assert_eq!(stringify_expr!(|| {}), "/*«*/ || {} /*»*/"); + assert_eq!(stringify_expr!(|x| {}), "/*«*/ | x | {} /*»*/"); + assert_eq!(stringify_expr!(|x: u8| {}), "/*«*/ | x : u8 | {} /*»*/"); + assert_eq!(stringify_expr!(|| ()), "/*«*/ || () /*»*/"); + assert_eq!(stringify_expr!(move || self), "/*«*/ move || self /*»*/"); + assert_eq!(stringify_expr!(async || self), "/*«*/ async || self /*»*/"); + assert_eq!(stringify_expr!(async move || self), "/*«*/ async move || self /*»*/"); + assert_eq!(stringify_expr!(static || self), "/*«*/ static || self /*»*/"); + assert_eq!(stringify_expr!(static move || self), "/*«*/ static move || self /*»*/"); #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5149 assert_eq!( stringify_expr!(static async || self), - "static async || self", + "/*«*/ static async || self /*»*/", ); #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5149 assert_eq!( stringify_expr!(static async move || self), - "static async move || self", + "/*«*/ static async move || self /*»*/", ); - assert_eq!(stringify_expr!(|| -> u8 { self }), "|| -> u8 { self }"); - assert_eq!(stringify_expr!(1 + || {}), "1 + (|| {})"); // ?? + assert_eq!(stringify_expr!(|| -> u8 { self }), "/*«*/ || -> u8 { self } /*»*/"); + assert_eq!(stringify_expr!(1 + || {}), "/*«*/ 1 + || {} /*»*/"); // ExprKind::Block - assert_eq!(stringify_expr!({}), "{}"); - assert_eq!(stringify_expr!(unsafe {}), "unsafe {}"); - assert_eq!(stringify_expr!('a: {}), "'a: {}"); + assert_eq!(stringify_expr!({}), "/*«*/ {} /*»*/"); + assert_eq!(stringify_expr!(unsafe {}), "/*«*/ unsafe {} /*»*/"); + assert_eq!(stringify_expr!('a: {}), "/*«*/ 'a : {} /*»*/"); assert_eq!( stringify_expr!( #[attr] {} ), - "#[attr] {}", + "/*«*/ #[attr] {} /*»*/", ); assert_eq!( stringify_expr!( @@ -243,102 +243,100 @@ fn test_expr() { #![attr] } ), - "{\n\ - \x20 #![attr]\n\ - }", + "/*«*/ { #! [attr] } /*»*/", ); // ExprKind::Async - assert_eq!(stringify_expr!(async {}), "async {}"); - assert_eq!(stringify_expr!(async move {}), "async move {}"); + assert_eq!(stringify_expr!(async {}), "/*«*/ async {} /*»*/"); + assert_eq!(stringify_expr!(async move {}), "/*«*/ async move {} /*»*/"); // ExprKind::Await - assert_eq!(stringify_expr!(expr.await), "expr.await"); + assert_eq!(stringify_expr!(expr.await), "/*«*/ expr.await /*»*/"); // ExprKind::TryBlock - assert_eq!(stringify_expr!(try {}), "try {}"); + assert_eq!(stringify_expr!(try {}), "/*«*/ try {} /*»*/"); // ExprKind::Assign - assert_eq!(stringify_expr!(expr = true), "expr = true"); + assert_eq!(stringify_expr!(expr = true), "/*«*/ expr = true /*»*/"); // ExprKind::AssignOp - assert_eq!(stringify_expr!(expr += true), "expr += true"); + assert_eq!(stringify_expr!(expr += true), "/*«*/ expr += true /*»*/"); // ExprKind::Field - assert_eq!(stringify_expr!(expr.field), "expr.field"); - assert_eq!(stringify_expr!(expr.0), "expr.0"); + assert_eq!(stringify_expr!(expr.field), "/*«*/ expr.field /*»*/"); + assert_eq!(stringify_expr!(expr.0), "/*«*/ expr.0 /*»*/"); // ExprKind::Index - assert_eq!(stringify_expr!(expr[true]), "expr[true]"); + assert_eq!(stringify_expr!(expr[true]), "/*«*/ expr [true] /*»*/"); // ExprKind::Range - assert_eq!(stringify_expr!(..), ".."); - assert_eq!(stringify_expr!(..hi), "..hi"); - assert_eq!(stringify_expr!(lo..), "lo.."); - assert_eq!(stringify_expr!(lo..hi), "lo..hi"); - assert_eq!(stringify_expr!(..=hi), "..=hi"); - assert_eq!(stringify_expr!(lo..=hi), "lo..=hi"); - assert_eq!(stringify_expr!(-2..=-1), "-2..=-1"); + assert_eq!(stringify_expr!(..), "/*«*/ .. /*»*/"); + assert_eq!(stringify_expr!(..hi), "/*«*/ .. hi /*»*/"); + assert_eq!(stringify_expr!(lo..), "/*«*/ lo .. /*»*/"); + assert_eq!(stringify_expr!(lo..hi), "/*«*/ lo .. hi /*»*/"); + assert_eq!(stringify_expr!(..=hi), "/*«*/ ..= hi /*»*/"); + assert_eq!(stringify_expr!(lo..=hi), "/*«*/ lo ..= hi /*»*/"); + assert_eq!(stringify_expr!(-2..=-1), "/*«*/ - 2 ..= - 1 /*»*/"); // ExprKind::Path - assert_eq!(stringify_expr!(thing), "thing"); - assert_eq!(stringify_expr!(m::thing), "m::thing"); - assert_eq!(stringify_expr!(self::thing), "self::thing"); - assert_eq!(stringify_expr!(crate::thing), "crate::thing"); - assert_eq!(stringify_expr!(Self::thing), "Self::thing"); - assert_eq!(stringify_expr!(::thing), "::thing"); - assert_eq!(stringify_expr!(Self::<'static>), "Self::<'static>"); + assert_eq!(stringify_expr!(thing), "/*«*/ thing /*»*/"); + assert_eq!(stringify_expr!(m::thing), "/*«*/ m :: thing /*»*/"); + assert_eq!(stringify_expr!(self::thing), "/*«*/ self :: thing /*»*/"); + assert_eq!(stringify_expr!(crate::thing), "/*«*/ crate :: thing /*»*/"); + assert_eq!(stringify_expr!(Self::thing), "/*«*/ Self :: thing /*»*/"); + assert_eq!(stringify_expr!(::thing), "/*«*/ < Self as T > :: thing /*»*/"); + assert_eq!(stringify_expr!(Self::<'static>), "/*«*/ Self :: < 'static > /*»*/"); // ExprKind::AddrOf - assert_eq!(stringify_expr!(&expr), "&expr"); - assert_eq!(stringify_expr!(&mut expr), "&mut expr"); - assert_eq!(stringify_expr!(&raw const expr), "&raw const expr"); - assert_eq!(stringify_expr!(&raw mut expr), "&raw mut expr"); + assert_eq!(stringify_expr!(&expr), "/*«*/ & expr /*»*/"); + assert_eq!(stringify_expr!(&mut expr), "/*«*/ & mut expr /*»*/"); + assert_eq!(stringify_expr!(&raw const expr), "/*«*/ & raw const expr /*»*/"); + assert_eq!(stringify_expr!(&raw mut expr), "/*«*/ & raw mut expr /*»*/"); // ExprKind::Break - assert_eq!(stringify_expr!(break), "break"); - assert_eq!(stringify_expr!(break 'a), "break 'a"); - assert_eq!(stringify_expr!(break true), "break true"); - assert_eq!(stringify_expr!(break 'a true), "break 'a true"); + assert_eq!(stringify_expr!(break), "/*«*/ break /*»*/"); + assert_eq!(stringify_expr!(break 'a), "/*«*/ break 'a /*»*/"); + assert_eq!(stringify_expr!(break true), "/*«*/ break true /*»*/"); + assert_eq!(stringify_expr!(break 'a true), "/*«*/ break 'a true /*»*/"); // ExprKind::Continue - assert_eq!(stringify_expr!(continue), "continue"); - assert_eq!(stringify_expr!(continue 'a), "continue 'a"); + assert_eq!(stringify_expr!(continue), "/*«*/ continue /*»*/"); + assert_eq!(stringify_expr!(continue 'a), "/*«*/ continue 'a /*»*/"); // ExprKind::Ret - assert_eq!(stringify_expr!(return), "return"); - assert_eq!(stringify_expr!(return true), "return true"); + assert_eq!(stringify_expr!(return), "/*«*/ return /*»*/"); + assert_eq!(stringify_expr!(return true), "/*«*/ return true /*»*/"); // ExprKind::MacCall - assert_eq!(stringify_expr!(mac!(...)), "mac!(...)"); - assert_eq!(stringify_expr!(mac![...]), "mac![...]"); - assert_eq!(stringify_expr!(mac! { ... }), "mac! { ... }"); + assert_eq!(stringify_expr!(mac!(...)), "/*«*/ mac! (...) /*»*/"); + assert_eq!(stringify_expr!(mac![...]), "/*«*/ mac! [...] /*»*/"); + assert_eq!(stringify_expr!(mac! { ... }), "/*«*/ mac! { ... } /*»*/"); // ExprKind::Struct - assert_eq!(stringify_expr!(Struct {}), "Struct {}"); + assert_eq!(stringify_expr!(Struct {}), "/*«*/ Struct {} /*»*/"); #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151 - assert_eq!(stringify_expr!(::Type {}), "::Type {}"); - assert_eq!(stringify_expr!(Struct { .. }), "Struct { .. }"); - assert_eq!(stringify_expr!(Struct { ..base }), "Struct { ..base }"); - assert_eq!(stringify_expr!(Struct { x }), "Struct { x }"); - assert_eq!(stringify_expr!(Struct { x, .. }), "Struct { x, .. }"); - assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct { x, ..base }"); - assert_eq!(stringify_expr!(Struct { x: true }), "Struct { x: true }"); - assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct { x: true, .. }"); - assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct { x: true, ..base }"); + assert_eq!(stringify_expr!(::Type {}), "/*«*/ < Struct as Trait > :: Type {} /*»*/"); + assert_eq!(stringify_expr!(Struct { .. }), "/*«*/ Struct { .. } /*»*/"); + assert_eq!(stringify_expr!(Struct { ..base }), "/*«*/ Struct { .. base } /*»*/"); + assert_eq!(stringify_expr!(Struct { x }), "/*«*/ Struct { x } /*»*/"); + assert_eq!(stringify_expr!(Struct { x, .. }), "/*«*/ Struct { x, .. } /*»*/"); + assert_eq!(stringify_expr!(Struct { x, ..base }), "/*«*/ Struct { x, .. base } /*»*/"); + assert_eq!(stringify_expr!(Struct { x: true }), "/*«*/ Struct { x : true } /*»*/"); + assert_eq!(stringify_expr!(Struct { x: true, .. }), "/*«*/ Struct { x : true, .. } /*»*/"); + assert_eq!(stringify_expr!(Struct { x: true, ..base }), "/*«*/ Struct { x : true, .. base } /*»*/"); // ExprKind::Repeat - assert_eq!(stringify_expr!([(); 0]), "[(); 0]"); + assert_eq!(stringify_expr!([(); 0]), "/*«*/ [() ; 0] /*»*/"); // ExprKind::Paren - assert_eq!(stringify_expr!((expr)), "(expr)"); + assert_eq!(stringify_expr!((expr)), "/*«*/ (expr) /*»*/"); // ExprKind::Try - assert_eq!(stringify_expr!(expr?), "expr?"); + assert_eq!(stringify_expr!(expr?), "/*«*/ expr ? /*»*/"); // ExprKind::Yield - assert_eq!(stringify_expr!(yield), "yield"); - assert_eq!(stringify_expr!(yield true), "yield true"); + assert_eq!(stringify_expr!(yield), "/*«*/ yield /*»*/"); + assert_eq!(stringify_expr!(yield true), "/*«*/ yield true /*»*/"); } #[test] diff --git a/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs index aed428bfc2a79..c9c7aecd27854 100644 --- a/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs +++ b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs @@ -11,4 +11,4 @@ fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` -//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` +//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `/*«*/`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr index 6cbab855c7636..3366541533670 100644 --- a/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr +++ b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr @@ -4,7 +4,7 @@ error: expected one of `,` or `:`, found `(` LL | fn f() { |[](* } | ^ expected one of `,` or `:` -error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` +error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `/*«*/`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 | LL | fn f() { |[](* } diff --git a/src/test/ui/parser/issues/issue-90993.rs b/src/test/ui/parser/issues/issue-90993.rs index 40e6fc748760a..de24857cd29c0 100644 --- a/src/test/ui/parser/issues/issue-90993.rs +++ b/src/test/ui/parser/issues/issue-90993.rs @@ -2,5 +2,5 @@ fn main() { ...=. //~^ ERROR: unexpected token: `...` //~| ERROR: unexpected `=` after inclusive range - //~| ERROR: expected one of `-`, `;`, `}`, or path, found `.` + //~| ERROR: expected one of `-`, `/*«*/`, `;`, `}`, or path, found `.` } diff --git a/src/test/ui/parser/issues/issue-90993.stderr b/src/test/ui/parser/issues/issue-90993.stderr index ab6bce410e6cc..9d0bf6fde267f 100644 --- a/src/test/ui/parser/issues/issue-90993.stderr +++ b/src/test/ui/parser/issues/issue-90993.stderr @@ -21,11 +21,11 @@ LL | ...=. | = note: inclusive ranges end with a single equals sign (`..=`) -error: expected one of `-`, `;`, `}`, or path, found `.` +error: expected one of `-`, `/*«*/`, `;`, `}`, or path, found `.` --> $DIR/issue-90993.rs:2:9 | LL | ...=. - | ^ expected one of `-`, `;`, `}`, or path + | ^ expected one of `-`, `/*«*/`, `;`, `}`, or path error: aborting due to 3 previous errors diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs index 71e5065a87a88..95a30d619f72a 100644 --- a/src/test/ui/proc-macro/parent-source-spans.rs +++ b/src/test/ui/proc-macro/parent-source-spans.rs @@ -8,14 +8,14 @@ use parent_source_spans::parent_source_spans; macro one($a:expr, $b:expr) { two!($a, $b); - //~^ ERROR first parent: /*«*/ "hello" /*»*/ - //~| ERROR second parent: /*«*/ "world" /*»*/ + //~^ ERROR first parent: /*«*/ /*«*/ "hello" /*»*/ /*»*/ + //~| ERROR second parent: /*«*/ /*«*/ "world" /*»*/ /*»*/ } macro two($a:expr, $b:expr) { three!($a, $b); - //~^ ERROR first final: /*«*/ "hello" /*»*/ - //~| ERROR second final: /*«*/ "world" /*»*/ + //~^ ERROR first final: /*«*/ /*«*/ "hello" /*»*/ /*»*/ + //~| ERROR second final: /*«*/ /*«*/ "world" /*»*/ /*»*/ //~| ERROR first final: /*«*/ "yay" /*»*/ //~| ERROR second final: /*«*/ "rust" /*»*/ } @@ -34,10 +34,10 @@ macro four($($tokens:tt)*) { fn main() { one!("hello", "world"); - //~^ ERROR first grandparent: /*«*/ "hello" /*»*/ - //~| ERROR second grandparent: /*«*/ "world" /*»*/ - //~| ERROR first source: /*«*/ "hello" /*»*/ - //~| ERROR second source: /*«*/ "world" /*»*/ + //~^ ERROR first grandparent: /*«*/ /*«*/ "hello" /*»*/ /*»*/ + //~| ERROR second grandparent: /*«*/ /*«*/ "world" /*»*/ /*»*/ + //~| ERROR first source: /*«*/ /*«*/ "hello" /*»*/ /*»*/ + //~| ERROR second source: /*«*/ /*«*/ "world" /*»*/ /*»*/ two!("yay", "rust"); //~^ ERROR first parent: /*«*/ "yay" /*»*/ diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr index e42218ea70117..c64526cbc88a3 100644 --- a/src/test/ui/proc-macro/parent-source-spans.stderr +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -1,4 +1,4 @@ -error: first final: /*«*/ "hello" /*»*/ +error: first final: /*«*/ /*«*/ "hello" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:16:12 | LL | three!($a, $b); @@ -9,7 +9,7 @@ LL | one!("hello", "world"); | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) -error: second final: /*«*/ "world" /*»*/ +error: second final: /*«*/ /*«*/ "world" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:16:16 | LL | three!($a, $b); @@ -20,7 +20,7 @@ LL | one!("hello", "world"); | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) -error: first parent: /*«*/ "hello" /*»*/ +error: first parent: /*«*/ /*«*/ "hello" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:10:5 | LL | two!($a, $b); @@ -31,7 +31,7 @@ LL | one!("hello", "world"); | = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) -error: second parent: /*«*/ "world" /*»*/ +error: second parent: /*«*/ /*«*/ "world" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:10:5 | LL | two!($a, $b); @@ -42,25 +42,25 @@ LL | one!("hello", "world"); | = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) -error: first grandparent: /*«*/ "hello" /*»*/ +error: first grandparent: /*«*/ /*«*/ "hello" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^ -error: second grandparent: /*«*/ "world" /*»*/ +error: second grandparent: /*«*/ /*«*/ "world" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^ -error: first source: /*«*/ "hello" /*»*/ +error: first source: /*«*/ /*«*/ "hello" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^ -error: second source: /*«*/ "world" /*»*/ +error: second source: /*«*/ /*«*/ "world" /*»*/ /*»*/ --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world");