about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-06 03:28:15 +0100
committerGitHub <noreply@github.com>2019-11-06 03:28:15 +0100
commit409b2bf941b2724a028f65518c64f799f205a186 (patch)
tree18d029fe26855d648607d80090acb0a28048f5fe /src
parent7d66a09a29342d520a3a17ae3b4f6233c97948f4 (diff)
parenta8ccbf5f2fa75007ce0effe58caef4e342859a4f (diff)
downloadrust-409b2bf941b2724a028f65518c64f799f205a186.tar.gz
rust-409b2bf941b2724a028f65518c64f799f205a186.zip
Rollup merge of #66098 - estebank:path-asciption-typo, r=Centril
Detect `::` -> `:` typo when involving turbofish

Fix #65569.
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/parse/parser/diagnostics.rs15
-rw-r--r--src/libsyntax/parse/parser/stmt.rs1
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.rs5
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr13
4 files changed, 30 insertions, 4 deletions
diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs
index fcf3b4c0aa8..453ef5963be 100644
--- a/src/libsyntax/parse/parser/diagnostics.rs
+++ b/src/libsyntax/parse/parser/diagnostics.rs
@@ -360,11 +360,11 @@ impl<'a> Parser<'a> {
     }
 
     pub fn maybe_annotate_with_ascription(
-        &self,
+        &mut self,
         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());
@@ -1088,8 +1088,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/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs
index 4f51fefe66f..12c530f3cbb 100644
--- a/src/libsyntax/parse/parser/stmt.rs
+++ b/src/libsyntax/parse/parser/stmt.rs
@@ -397,6 +397,7 @@ impl<'a> Parser<'a> {
             }
             let stmt = match self.parse_full_stmt(false) {
                 Err(mut err) => {
+                    self.maybe_annotate_with_ascription(&mut err, false);
                     err.emit();
                     self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                     Some(Stmt {
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs
new file mode 100644
index 00000000000..220fd1eebda
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs
@@ -0,0 +1,5 @@
+fn main() -> Result<(), ()> {
+    vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+    //~^ ERROR expected `::`, found `(`
+    Ok(())
+}
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
new file mode 100644
index 00000000000..db793c84cf8
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
@@ -0,0 +1,13 @@
+error: expected `::`, found `(`
+  --> $DIR/type-ascription-instead-of-path-2.rs:2:55
+   |
+LL |     vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+   |                                    -                  ^ expected `::`
+   |                                    |
+   |                                    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
+
+error: aborting due to previous error
+