diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 55 |
3 files changed, 28 insertions, 50 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 35435baea70..f2fcce5c226 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2,14 +2,13 @@ use super::ty::AllowPlus; use super::TokenType; use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType}; +use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Lit, LitKind, TokenKind}; use rustc_ast::util::parser::AssocOp; -use rustc_ast::{ - self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, - Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item, ItemKind, Mutability, Param, Pat, - PatKind, Path, PathSegment, QSelf, Ty, TyKind, -}; +use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec}; +use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item}; +use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err}; @@ -220,6 +219,7 @@ impl<'a> Parser<'a> { edible: &[TokenKind], inedible: &[TokenKind], ) -> PResult<'a, bool /* recovered */> { + debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible); fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); // This might be a sign we need a connect method on `Iterator`. @@ -245,6 +245,7 @@ impl<'a> Parser<'a> { .collect::<Vec<_>>(); expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); + let expect = tokens_to_string(&expected[..]); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { @@ -270,6 +271,16 @@ impl<'a> Parser<'a> { }; self.last_unexpected_token_span = Some(self.token.span); let mut err = self.struct_span_err(self.token.span, &msg_exp); + + // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens + // there are unclosed angle brackets + if self.unmatched_angle_bracket_count > 0 + && self.token.kind == TokenKind::Eq + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt))) + { + err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket"); + } + let sp = if self.token == token::Eof { // This is EOF; don't want to point at the following char, but rather the last token. self.prev_token.span diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c85b7a00732..d5e625a167c 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -272,7 +272,7 @@ impl TokenCursor { } } -#[derive(Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] enum TokenType { Token(TokenKind), Keyword(Symbol), diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index dd36122f6a1..4234740b2b1 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -185,7 +185,6 @@ impl<'a> Parser<'a> { pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; - let is_args_start = |token: &Token| { matches!( token.kind, @@ -420,7 +419,10 @@ impl<'a> Parser<'a> { match arg { Some(arg) => { if self.check(&token::Colon) | self.check(&token::Eq) { - let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?; + let (ident, gen_args) = match self.get_ident_from_generic_arg(arg) { + Ok(ident_gen_args) => ident_gen_args, + Err(arg) => return Ok(Some(AngleBracketedArg::Arg(arg))), + }; let kind = if self.eat(&token::Colon) { // Parse associated type constraint bound. @@ -561,50 +563,15 @@ impl<'a> Parser<'a> { fn get_ident_from_generic_arg( &self, gen_arg: GenericArg, - lo: Span, - ) -> PResult<'a, (Ident, Option<GenericArgs>)> { - let gen_arg_span = gen_arg.span(); - match gen_arg { - GenericArg::Type(t) => match t.into_inner().kind { - ast::TyKind::Path(qself, mut path) => { - if let Some(qself) = qself { - let mut err = self.struct_span_err( - gen_arg_span, - "qualified paths cannot be used in associated type constraints", - ); - err.span_label( - qself.path_span, - "not allowed in associated type constraints", - ); - return Err(err); - } - if path.segments.len() == 1 { - let path_seg = path.segments.remove(0); - let ident = path_seg.ident; - let gen_args = path_seg.args.map(|args| args.into_inner()); - return Ok((ident, gen_args)); - } - let err = self.struct_span_err( - path.span, - "paths with multiple segments cannot be used in associated type constraints", - ); - return Err(err); - } - _ => { - let span = lo.to(self.prev_token.span); - let err = self.struct_span_err( - span, - "only path types can be used in associated type constraints", - ); - return Err(err); + ) -> Result<(Ident, Option<GenericArgs>), GenericArg> { + if let GenericArg::Type(ty) = &gen_arg { + if let ast::TyKind::Path(qself, path) = &ty.kind { + if qself.is_none() && path.segments.len() == 1 { + let seg = &path.segments[0]; + return Ok((seg.ident, seg.args.as_deref().cloned())); } - }, - _ => { - let span = lo.to(self.prev_token.span); - let err = self - .struct_span_err(span, "only types can be used in associated type constraints"); - return Err(err); } } + Err(gen_arg) } } |
