about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
authorb-naber <bn263@gmx.de>2020-12-15 17:43:24 +0100
committerb-naber <bn263@gmx.de>2021-01-22 17:07:27 +0100
commit728d257839ad2397e34c71f8ceda151fa579242d (patch)
treeb0ccbe0df018d19e954c0c3df0f3b126603125e9 /compiler/rustc_parse/src
parentf2de221b0063261140a336c448bf1421170c9a74 (diff)
downloadrust-728d257839ad2397e34c71f8ceda151fa579242d.tar.gz
rust-728d257839ad2397e34c71f8ceda151fa579242d.zip
improve diagnostics for angle args
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs21
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs55
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)
     }
 }