about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-11-05 10:29:54 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-11-05 10:29:54 -0800
commita8ccbf5f2fa75007ce0effe58caef4e342859a4f (patch)
treede4a7862c55287076de8397f19102ff9a8860e19
parent3bbfc7320ba0f23541f94a84cf5281a210a546cd (diff)
downloadrust-a8ccbf5f2fa75007ce0effe58caef4e342859a4f.tar.gz
rust-a8ccbf5f2fa75007ce0effe58caef4e342859a4f.zip
Account for typo in turbofish and suggest `::`
-rw-r--r--src/libsyntax/parse/parser/diagnostics.rs14
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr2
2 files changed, 11 insertions, 5 deletions
diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs
index ad479e6278b..fc2b10f2260 100644
--- a/src/libsyntax/parse/parser/diagnostics.rs
+++ b/src/libsyntax/parse/parser/diagnostics.rs
@@ -358,7 +358,7 @@ impl<'a> Parser<'a> {
         err: &mut DiagnosticBuilder<'_>,
         maybe_expected_semicolon: bool,
     ) {
-        if let Some((sp, likely_path)) = self.last_type_ascription {
+        if let Some((sp, likely_path)) = self.last_type_ascription.take() {
             let sm = self.sess.source_map();
             let next_pos = sm.lookup_char_pos(self.token.span.lo());
             let op_pos = sm.lookup_char_pos(sp.hi());
@@ -395,7 +395,6 @@ impl<'a> Parser<'a> {
                 err.note("for more information, see \
                           https://github.com/rust-lang/rust/issues/23416");
             }
-            self.last_type_ascription = None;
         }
     }
 
@@ -1083,8 +1082,15 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
-        self.token.is_ident() &&
-            if let ast::ExprKind::Path(..) = node { true } else { false } &&
+        (self.token == token::Lt && // `foo:<bar`, likely a typoed turbofish.
+            self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
+        ) ||
+            self.token.is_ident() &&
+            match node {
+                // `foo::` → `foo:` or `foo.bar::` → `foo.bar:`
+                ast::ExprKind::Path(..) | ast::ExprKind::Field(..) => true,
+                _ => false,
+            } &&
             !self.token.is_reserved_ident() &&           // v `foo:bar(baz)`
             self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
             self.look_ahead(1, |t| t == &token::Lt) &&     // `foo:bar<baz`
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
index 191c4f631c4..db793c84cf8 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
@@ -4,7 +4,7 @@ error: expected `::`, found `(`
 LL |     vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
    |                                    -                  ^ expected `::`
    |                                    |
-   |                                    tried to parse a type due to this type ascription
+   |                                    help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: for more information, see https://github.com/rust-lang/rust/issues/23416