about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-09-30 12:36:44 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-10-03 11:55:18 -0700
commitd7dceaa0c57759d37a48b5a0aa1064b7c89f957b (patch)
treec791f12a94ff10558875a77b484d20320108290c /src/libsyntax/parse
parent6c9f298a8bee9b1716b2e6fcdb8305c3f4874fc6 (diff)
downloadrust-d7dceaa0c57759d37a48b5a0aa1064b7c89f957b.tar.gz
rust-d7dceaa0c57759d37a48b5a0aa1064b7c89f957b.zip
Account for missing turbofish in paths too
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/diagnostics.rs47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 584c7c2ded5..4fbd36cfefc 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -585,12 +585,51 @@ impl<'a> Parser<'a> {
                         let early_return = vec![token::Eof];
                         self.consume_tts(1, &modifiers[..], &early_return[..]);
 
-                        if self.token.kind != token::OpenDelim(token::Paren) {
-                            // We don't have `foo< bar >(`, so we rewind the parser and bail out.
+                        if !&[
+                            token::OpenDelim(token::Paren),
+                            token::ModSep,
+                        ].contains(&self.token.kind) {
+                            // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
+                            // parser and bail out.
                             mem::replace(self, snapshot.clone());
                         }
                     }
-                    if self.token.kind == token::OpenDelim(token::Paren) {
+                    if token::ModSep == self.token.kind {
+                        // We have some certainty that this was a bad turbofish at this point.
+                        // `foo< bar >::`
+                        err.span_suggestion(
+                            op_span.shrink_to_lo(),
+                            msg,
+                            "::".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+
+                        let snapshot = self.clone();
+
+                        self.bump(); // `::`
+                        // Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
+                        match self.parse_expr() {
+                            Ok(_) => {
+                                // 99% certain that the suggestion is correct, continue parsing.
+                                err.emit();
+                                // FIXME: actually check that the two expressions in the binop are
+                                // paths and resynthesize new fn call expression instead of using
+                                // `ExprKind::Err` placeholder.
+                                return Ok(Some(self.mk_expr(
+                                    lhs.span.to(self.prev_span),
+                                    ExprKind::Err,
+                                    ThinVec::new(),
+                                )));
+                            }
+                            Err(mut err) => {
+                                err.cancel();
+                                // Not entirely sure now, but we bubble the error up with the
+                                // suggestion.
+                                mem::replace(self, snapshot);
+                                return Err(err);
+                            }
+                        }
+                    } else if token::OpenDelim(token::Paren) == self.token.kind {
                         // We have high certainty that this was a bad turbofish at this point.
                         // `foo< bar >(`
                         err.span_suggestion(
@@ -601,6 +640,7 @@ impl<'a> Parser<'a> {
                         );
 
                         let snapshot = self.clone();
+                        self.bump(); // `(`
 
                         // Consume the fn call arguments.
                         let modifiers = vec![
@@ -608,7 +648,6 @@ impl<'a> Parser<'a> {
                             (token::CloseDelim(token::Paren), -1),
                         ];
                         let early_return = vec![token::Eof];
-                        self.bump(); // `(`
                         self.consume_tts(1, &modifiers[..], &early_return[..]);
 
                         if self.token.kind == token::Eof {