diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/lexer/tokentrees.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 50 |
3 files changed, 68 insertions, 10 deletions
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index d35c9c7bae7..7b21ffacc84 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -43,11 +43,19 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { let mut buf = Vec::new(); loop { match self.token.kind { - token::OpenDelim(delim) => buf.push(match self.lex_token_tree_open_delim(delim) { - Ok(val) => val, - Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), - }), + token::OpenDelim(delim) => { + // Invisible delimiters cannot occur here because `TokenTreesReader` parses + // code directly from strings, with no macro expansion involved. + debug_assert!(!matches!(delim, Delimiter::Invisible(_))); + buf.push(match self.lex_token_tree_open_delim(delim) { + Ok(val) => val, + Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), + }) + } token::CloseDelim(delim) => { + // Invisible delimiters cannot occur here because `TokenTreesReader` parses + // code directly from strings, with no macro expansion involved. + debug_assert!(!matches!(delim, Delimiter::Invisible(_))); return ( open_spacing, TokenStream::new(buf), diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0012db471ef..b110d891c84 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3591,11 +3591,19 @@ impl<'a> Parser<'a> { && !self.token.is_reserved_ident() && self.look_ahead(1, |t| { AssocOp::from_token(t).is_some() - || matches!(t.kind, token::OpenDelim(_)) + || matches!( + t.kind, + token::OpenDelim( + Delimiter::Parenthesis + | Delimiter::Bracket + | Delimiter::Brace + ) + ) || *t == token::Dot }) { - // Looks like they tried to write a shorthand, complex expression. + // Looks like they tried to write a shorthand, complex expression, + // E.g.: `n + m`, `f(a)`, `a[i]`, `S { x: 3 }`, or `x.y`. e.span_suggestion_verbose( self.token.span.shrink_to_lo(), "try naming a field", diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 43c3de90d9d..8fb6f85d0dd 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -3,7 +3,9 @@ use rustc_ast::ptr::P; use rustc_ast::token::Nonterminal::*; use rustc_ast::token::NtExprKind::*; use rustc_ast::token::NtPatKind::*; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token, +}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; @@ -22,7 +24,28 @@ impl<'a> Parser<'a> { #[inline] pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. - fn may_be_ident(nt: &token::Nonterminal) -> bool { + fn may_be_ident(kind: MetaVarKind) -> bool { + match kind { + MetaVarKind::Stmt + | MetaVarKind::Pat(_) + | MetaVarKind::Expr { .. } + | MetaVarKind::Ty + | MetaVarKind::Literal // `true`, `false` + | MetaVarKind::Meta + | MetaVarKind::Path => true, + + MetaVarKind::Item + | MetaVarKind::Block + | MetaVarKind::Vis => false, + + MetaVarKind::Ident + | MetaVarKind::Lifetime + | MetaVarKind::TT => unreachable!(), + } + } + + /// Old variant of `may_be_ident`. Being phased out. + fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { NtStmt(_) | NtPat(_) @@ -69,7 +92,8 @@ impl<'a> Parser<'a> { | token::Ident(..) | token::NtIdent(..) | token::NtLifetime(..) - | token::Interpolated(_) => true, + | token::Interpolated(_) + | token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true, _ => token.can_begin_type(), }, NonterminalKind::Block => match &token.kind { @@ -79,11 +103,29 @@ impl<'a> Parser<'a> { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false, }, + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { + MetaVarKind::Block + | MetaVarKind::Stmt + | MetaVarKind::Expr { .. } + | MetaVarKind::Literal => true, + MetaVarKind::Item + | MetaVarKind::Pat(_) + | MetaVarKind::Ty + | MetaVarKind::Meta + | MetaVarKind::Path + | MetaVarKind::Vis => false, + MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => { + unreachable!() + } + }, _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::PathSep | token::Ident(..) | token::NtIdent(..) => true, - token::Interpolated(nt) => may_be_ident(nt), + token::Interpolated(nt) => nt_may_be_ident(nt), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { + may_be_ident(*kind) + } _ => false, }, NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind), |
