about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-02-02 08:30:11 +0900
committerGitHub <noreply@github.com>2020-02-02 08:30:11 +0900
commitb18b26924c640211a358535f14e39695c48b0ec3 (patch)
tree2c7c8a6eb9c5078b81e04b0177348b9fb29072f5
parentbf68a057b39837ee8b9ccf00d902d1964e8ed326 (diff)
parent07ee472cd18925be45d424d9cfd59c441ea9c9a7 (diff)
downloadrust-b18b26924c640211a358535f14e39695c48b0ec3.tar.gz
rust-b18b26924c640211a358535f14e39695c48b0ec3.zip
Rollup merge of #68681 - bobrippling:fix-matched-angle-brackets, r=Centril
Suggest path separator for single-colon typos

This commit adds guidance for when a user means to type a path, but ends
up typing a single colon, such as `<<Impl as T>:Ty>`.

This change seemed pertinent as the current error message is
particularly misleading, emitting `error: unmatched angle bracket`,
despite the angle bracket being matched later on, leaving the user to
track down the typo'd colon.
-rw-r--r--src/librustc_parse/parser/path.rs37
-rw-r--r--src/test/ui/parser/qualified-path-in-turbofish.fixed19
-rw-r--r--src/test/ui/parser/qualified-path-in-turbofish.rs19
-rw-r--r--src/test/ui/parser/qualified-path-in-turbofish.stderr8
4 files changed, 82 insertions, 1 deletions
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 0358458c099..a09eb42dcfe 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -71,7 +71,9 @@ impl<'a> Parser<'a> {
             debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
         }
 
-        self.expect(&token::ModSep)?;
+        if !self.recover_colon_before_qpath_proj() {
+            self.expect(&token::ModSep)?;
+        }
 
         let qself = QSelf { ty, path_span, position: path.segments.len() };
         self.parse_path_segments(&mut path.segments, style)?;
@@ -79,6 +81,39 @@ impl<'a> Parser<'a> {
         Ok((qself, Path { segments: path.segments, span: lo.to(self.prev_span) }))
     }
 
+    /// Recover from an invalid single colon, when the user likely meant a qualified path.
+    /// We avoid emitting this if not followed by an identifier, as our assumption that the user
+    /// intended this to be a qualified path may not be correct.
+    ///
+    /// ```ignore (diagnostics)
+    /// <Bar as Baz<T>>:Qux
+    ///                ^ help: use double colon
+    /// ```
+    fn recover_colon_before_qpath_proj(&mut self) -> bool {
+        if self.token.kind != token::Colon
+            || self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident())
+        {
+            return false;
+        }
+
+        self.bump(); // colon
+
+        self.diagnostic()
+            .struct_span_err(
+                self.prev_span,
+                "found single colon before projection in qualified path",
+            )
+            .span_suggestion(
+                self.prev_span,
+                "use double colon",
+                "::".to_string(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
+
+        true
+    }
+
     /// Parses simple paths.
     ///
     /// `path = [::] segment+`
diff --git a/src/test/ui/parser/qualified-path-in-turbofish.fixed b/src/test/ui/parser/qualified-path-in-turbofish.fixed
new file mode 100644
index 00000000000..404d2f7762d
--- /dev/null
+++ b/src/test/ui/parser/qualified-path-in-turbofish.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+trait T {
+    type Ty;
+}
+
+struct Impl;
+
+impl T for Impl {
+    type Ty = u32;
+}
+
+fn template<T>() -> i64 {
+    3
+}
+
+fn main() {
+    template::<<Impl as T>::Ty>();
+    //~^ ERROR found single colon before projection in qualified path
+}
diff --git a/src/test/ui/parser/qualified-path-in-turbofish.rs b/src/test/ui/parser/qualified-path-in-turbofish.rs
new file mode 100644
index 00000000000..2f4b2ed348b
--- /dev/null
+++ b/src/test/ui/parser/qualified-path-in-turbofish.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+trait T {
+    type Ty;
+}
+
+struct Impl;
+
+impl T for Impl {
+    type Ty = u32;
+}
+
+fn template<T>() -> i64 {
+    3
+}
+
+fn main() {
+    template::<<Impl as T>:Ty>();
+    //~^ ERROR found single colon before projection in qualified path
+}
diff --git a/src/test/ui/parser/qualified-path-in-turbofish.stderr b/src/test/ui/parser/qualified-path-in-turbofish.stderr
new file mode 100644
index 00000000000..8857d2ef30c
--- /dev/null
+++ b/src/test/ui/parser/qualified-path-in-turbofish.stderr
@@ -0,0 +1,8 @@
+error: found single colon before projection in qualified path
+  --> $DIR/qualified-path-in-turbofish.rs:17:27
+   |
+LL |     template::<<Impl as T>:Ty>();
+   |                           ^ help: use double colon: `::`
+
+error: aborting due to previous error
+