about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-07-23 16:25:39 -0700
committerEsteban Küber <esteban@kuber.com.ar>2020-07-23 16:25:39 -0700
commitd090e5ed3327a24c17754be7e224b5f2345aa622 (patch)
treec780c177db862f2b6395bcb496c0bc155cb79a91
parent20f4e5d9c24809031fd6631436f0a7a5b075fe40 (diff)
downloadrust-d090e5ed3327a24c17754be7e224b5f2345aa622.tar.gz
rust-d090e5ed3327a24c17754be7e224b5f2345aa622.zip
Account for trailing closing angle brackets
-rw-r--r--src/librustc_parse/parser/diagnostics.rs57
-rw-r--r--src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs6
-rw-r--r--src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr35
3 files changed, 75 insertions, 23 deletions
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index f84f54054ac..609a0c961e9 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,9 +1,9 @@
 use super::ty::AllowPlus;
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
-use rustc_ast::ast::{self, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Item, Param};
 use rustc_ast::ast::{
-    AngleBracketedArgs, AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
+    self, AngleBracketedArgs, AttrVec, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind,
+    Item, ItemKind, Mutability, Param, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
 };
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Lit, LitKind, TokenKind};
@@ -498,29 +498,42 @@ impl<'a> Parser<'a> {
             self.bump();
             let lo = self.token.span;
             match self.parse_angle_args() {
-                Ok(args) if self.token.kind == token::OpenDelim(token::Paren) => {
-                    // Recover from bad turbofish: `foo.collect::Vec<_>()`.
+                Ok(args) => {
                     let span = lo.to(self.prev_token.span);
-                    let args = AngleBracketedArgs { args, span }.into();
-                    segment.args = args;
-                    self.struct_span_err(
-                        span,
-                        "generic parameters without surrounding angle brackets",
-                    )
-                    .multipart_suggestion(
-                        "surround the type parameters with angle brackets",
-                        vec![
-                            (span.shrink_to_lo(), "<".to_string()),
-                            (span.shrink_to_hi(), ">".to_string()),
-                        ],
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
-                }
-                Ok(_) => {
-                    *self = snapshot;
+                    // Detect trailing `>` like in `x.collect::Vec<_>>()`.
+                    let mut trailing_span = self.prev_token.span.shrink_to_hi();
+                    while self.token.kind == token::BinOp(token::Shr)
+                        || self.token.kind == token::Gt
+                    {
+                        trailing_span = trailing_span.to(self.token.span);
+                        self.bump();
+                    }
+                    if self.token.kind == token::OpenDelim(token::Paren) {
+                        // Recover from bad turbofish: `foo.collect::Vec<_>()`.
+                        let args = AngleBracketedArgs { args, span }.into();
+                        segment.args = args;
+
+                        self.struct_span_err(
+                            span,
+                            "generic parameters without surrounding angle brackets",
+                        )
+                        .multipart_suggestion(
+                            "surround the type parameters with angle brackets",
+                            vec![
+                                (span.shrink_to_lo(), "<".to_string()),
+                                (trailing_span, ">".to_string()),
+                            ],
+                            Applicability::MachineApplicable,
+                        )
+                        .emit();
+                    } else {
+                        // This doesn't look like an invalid turbofish, can't recover parse state.
+                        *self = snapshot;
+                    }
                 }
                 Err(mut err) => {
+                    // We could't parse generic parameters, unlikely to be a turbofish. Rely on
+                    // generic parse error instead.
                     err.cancel();
                     *self = snapshot;
                 }
diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
index 63fbee9f0f5..333dce39046 100644
--- a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
+++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
@@ -1,4 +1,10 @@
 fn main() {
     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
     //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
 }
diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
index ad48a0c7a5c..981f95749d3 100644
--- a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
+++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
@@ -9,5 +9,38 @@ help: surround the type parameters with angle brackets
 LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
    |                                                ^      ^
 
-error: aborting due to previous error
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: aborting due to 4 previous errors