about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMu001999 <mu001999@outlook.com>2023-08-01 23:30:40 +0800
committerMu001999 <mu001999@outlook.com>2023-08-01 23:30:40 +0800
commit049c728c60f7c950b7185f0f277609694a8e2a16 (patch)
tree95022ce32d4e04211a3456dd11121e97302137b2
parentb969b830aa8cac0ded5cced9e4a47e124183a6ee (diff)
downloadrust-049c728c60f7c950b7185f0f277609694a8e2a16.tar.gz
rust-049c728c60f7c950b7185f0f277609694a8e2a16.zip
Suggests turbofish in patterns
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs14
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs1
-rw-r--r--compiler/rustc_parse/src/parser/path.rs10
-rw-r--r--tests/ui/did_you_mean/issue-114112.rs11
-rw-r--r--tests/ui/did_you_mean/issue-114112.stderr13
-rw-r--r--tests/ui/parser/issues/issue-22647.rs2
-rw-r--r--tests/ui/parser/issues/issue-22647.stderr9
-rw-r--r--tests/ui/parser/issues/issue-22712.rs2
-rw-r--r--tests/ui/parser/issues/issue-22712.stderr9
-rw-r--r--tests/ui/parser/pat-lt-bracket-3.rs3
-rw-r--r--tests/ui/parser/pat-lt-bracket-3.stderr9
-rw-r--r--tests/ui/parser/pat-lt-bracket-4.rs2
-rw-r--r--tests/ui/parser/pat-lt-bracket-4.stderr9
-rw-r--r--tests/ui/span/issue-34264.rs2
-rw-r--r--tests/ui/span/issue-34264.stderr15
-rw-r--r--tests/ui/suggestions/issue-64252-self-type.rs6
-rw-r--r--tests/ui/suggestions/issue-64252-self-type.stderr32
18 files changed, 101 insertions, 50 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 83d96ad8e76..6a9a5a239e4 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -270,6 +270,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
 parse_function_body_equals_expr = function body cannot be `= expression;`
     .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
 
+parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax
+
 parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
     .suggestion = surround the type parameters with angle brackets
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 06c09960727..3184ca777ce 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2731,3 +2731,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg {
     #[suggestion_part(code = "")]
     pub right: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_generic_args_in_pat_require_turbofish_syntax)]
+pub(crate) struct GenericArgsInPatRequireTurbofishSyntax {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(
+        parse_sugg_turbofish_syntax,
+        style = "verbose",
+        code = "::",
+        applicability = "maybe-incorrect"
+    )]
+    pub suggest_turbofish: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 14891c45d81..e0539c4ac04 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -805,6 +805,7 @@ impl<'a> Parser<'a> {
             | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
             | token::ModSep // A tuple / struct variant pattern.
             | token::Not)) // A macro expanding to a pattern.
+        && !(self.look_ahead(1, |t| t.kind == token::Lt) && self.look_ahead(2, |t| t.can_begin_type())) // May suggest the turbofish syntax for generics, only valid for recoveries.
     }
 
     /// Parses `ident` or `ident @ pat`.
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index feb7e829caf..4fe8a5aa626 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,6 +1,6 @@
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
-use crate::errors::PathSingleColon;
+use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon};
 use crate::{errors, maybe_whole};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@@ -382,6 +382,14 @@ impl<'a> Parser<'a> {
                 };
 
                 PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID }
+            } else if style == PathStyle::Pat
+                && self.check_noexpect(&token::Lt)
+                && self.look_ahead(1, |t| t.can_begin_type())
+            {
+                return Err(self.sess.create_err(GenericArgsInPatRequireTurbofishSyntax {
+                    span: self.token.span,
+                    suggest_turbofish: self.token.span.shrink_to_lo(),
+                }));
             } else {
                 // Generic arguments are not found.
                 PathSegment::from_ident(ident)
diff --git a/tests/ui/did_you_mean/issue-114112.rs b/tests/ui/did_you_mean/issue-114112.rs
new file mode 100644
index 00000000000..0fde12ecd78
--- /dev/null
+++ b/tests/ui/did_you_mean/issue-114112.rs
@@ -0,0 +1,11 @@
+enum E<T> {
+    A(T)
+}
+
+fn main() {
+    match E::<i32>::A(1) {
+        E<i32>::A(v) => { //~ ERROR generic args in patterns require the turbofish syntax
+            println!("{v:?}");
+        },
+    }
+}
diff --git a/tests/ui/did_you_mean/issue-114112.stderr b/tests/ui/did_you_mean/issue-114112.stderr
new file mode 100644
index 00000000000..d76b5f72e30
--- /dev/null
+++ b/tests/ui/did_you_mean/issue-114112.stderr
@@ -0,0 +1,13 @@
+error: generic args in patterns require the turbofish syntax
+  --> $DIR/issue-114112.rs:7:10
+   |
+LL |         E<i32>::A(v) => {
+   |          ^
+   |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   |
+LL |         E::<i32>::A(v) => {
+   |          ++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issues/issue-22647.rs b/tests/ui/parser/issues/issue-22647.rs
index a6861410682..163cbc69ddd 100644
--- a/tests/ui/parser/issues/issue-22647.rs
+++ b/tests/ui/parser/issues/issue-22647.rs
@@ -1,5 +1,5 @@
 fn main() {
-    let caller<F> = |f: F|  //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
+    let caller<F> = |f: F|  //~ ERROR generic args in patterns require the turbofish syntax
     where F: Fn() -> i32
     {
         let x = f();
diff --git a/tests/ui/parser/issues/issue-22647.stderr b/tests/ui/parser/issues/issue-22647.stderr
index 89b454d1973..585e7026661 100644
--- a/tests/ui/parser/issues/issue-22647.stderr
+++ b/tests/ui/parser/issues/issue-22647.stderr
@@ -1,8 +1,13 @@
-error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/issue-22647.rs:2:15
    |
 LL |     let caller<F> = |f: F|
-   |               ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |               ^
+   |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   |
+LL |     let caller::<F> = |f: F|
+   |               ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-22712.rs b/tests/ui/parser/issues/issue-22712.rs
index 774de9c7e64..92b12b8e193 100644
--- a/tests/ui/parser/issues/issue-22712.rs
+++ b/tests/ui/parser/issues/issue-22712.rs
@@ -3,7 +3,7 @@ struct Foo<B> {
 }
 
 fn bar() {
-    let Foo<Vec<u8>>  //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
+    let Foo<Vec<u8>> //~ ERROR generic args in patterns require the turbofish syntax
 }
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-22712.stderr b/tests/ui/parser/issues/issue-22712.stderr
index 30fabac6564..7f9d99d8edf 100644
--- a/tests/ui/parser/issues/issue-22712.stderr
+++ b/tests/ui/parser/issues/issue-22712.stderr
@@ -1,8 +1,13 @@
-error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/issue-22712.rs:6:12
    |
 LL |     let Foo<Vec<u8>>
-   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |            ^
+   |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   |
+LL |     let Foo::<Vec<u8>>
+   |            ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/pat-lt-bracket-3.rs b/tests/ui/parser/pat-lt-bracket-3.rs
index a8bdfd3fa18..bd83fe8db4b 100644
--- a/tests/ui/parser/pat-lt-bracket-3.rs
+++ b/tests/ui/parser/pat-lt-bracket-3.rs
@@ -3,8 +3,7 @@ struct Foo<T>(T, T);
 impl<T> Foo<T> {
     fn foo(&self) {
         match *self {
-            Foo<T>(x, y) => {
-            //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+            Foo<T>(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax
               println!("Goodbye, World!")
             }
         }
diff --git a/tests/ui/parser/pat-lt-bracket-3.stderr b/tests/ui/parser/pat-lt-bracket-3.stderr
index bacf868e3c4..afdf1e9a557 100644
--- a/tests/ui/parser/pat-lt-bracket-3.stderr
+++ b/tests/ui/parser/pat-lt-bracket-3.stderr
@@ -1,8 +1,13 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/pat-lt-bracket-3.rs:6:16
    |
 LL |             Foo<T>(x, y) => {
-   |                ^ expected one of `=>`, `@`, `if`, or `|`
+   |                ^
+   |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   |
+LL |             Foo::<T>(x, y) => {
+   |                ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/pat-lt-bracket-4.rs b/tests/ui/parser/pat-lt-bracket-4.rs
index de314f6c641..6d348b68cd6 100644
--- a/tests/ui/parser/pat-lt-bracket-4.rs
+++ b/tests/ui/parser/pat-lt-bracket-4.rs
@@ -5,7 +5,7 @@ enum BtNode {
 
 fn main() {
     let y = match 10 {
-        Foo<T>::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+        Foo<T>::A(value) => value, //~ ERROR generic args in patterns require the turbofish syntax
         Foo<T>::B => 7,
     };
 }
diff --git a/tests/ui/parser/pat-lt-bracket-4.stderr b/tests/ui/parser/pat-lt-bracket-4.stderr
index 911c276b931..b71a5ad939e 100644
--- a/tests/ui/parser/pat-lt-bracket-4.stderr
+++ b/tests/ui/parser/pat-lt-bracket-4.stderr
@@ -1,8 +1,13 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/pat-lt-bracket-4.rs:8:12
    |
 LL |         Foo<T>::A(value) => value,
-   |            ^ expected one of `=>`, `@`, `if`, or `|`
+   |            ^
+   |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   |
+LL |         Foo::<T>::A(value) => value,
+   |            ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs
index 9227ee482df..c7a8440f284 100644
--- a/tests/ui/span/issue-34264.rs
+++ b/tests/ui/span/issue-34264.rs
@@ -1,5 +1,5 @@
 fn foo(Option<i32>, String) {} //~ ERROR expected one of
-//~^ ERROR expected one of
+//~^ ERROR generic args in patterns require the turbofish syntax
 fn bar(x, y: usize) {} //~ ERROR expected one of
 
 fn main() {
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
index f0dea66f612..1874d7f8533 100644
--- a/tests/ui/span/issue-34264.stderr
+++ b/tests/ui/span/issue-34264.stderr
@@ -1,18 +1,13 @@
-error: expected one of `:`, `@`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/issue-34264.rs:1:14
    |
 LL | fn foo(Option<i32>, String) {}
-   |              ^ expected one of `:`, `@`, or `|`
+   |              ^
    |
-   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this is a `self` type, give it a parameter name
-   |
-LL | fn foo(self: Option<i32>, String) {}
-   |        +++++
-help: if this is a type, explicitly ignore the parameter name
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
    |
-LL | fn foo(_: Option<i32>, String) {}
-   |        ++
+LL | fn foo(Option::<i32>, String) {}
+   |              ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/issue-34264.rs:1:27
diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs
index 128d5e85c22..ad25d334507 100644
--- a/tests/ui/suggestions/issue-64252-self-type.rs
+++ b/tests/ui/suggestions/issue-64252-self-type.rs
@@ -1,14 +1,12 @@
 // This test checks that a suggestion to add a `self: ` parameter name is provided
 // to functions where this is applicable.
 
-pub fn foo(Box<Self>) { }
-//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
+pub fn foo(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
 
 struct Bar;
 
 impl Bar {
-    fn bar(Box<Self>) { }
-    //~^ ERROR expected one of `:`, `@`, or `|`, found `<`
+    fn bar(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
 }
 
 fn main() { }
diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr
index c3418dab0e8..ba5c2da2415 100644
--- a/tests/ui/suggestions/issue-64252-self-type.stderr
+++ b/tests/ui/suggestions/issue-64252-self-type.stderr
@@ -1,34 +1,24 @@
-error: expected one of `:`, `@`, or `|`, found `<`
+error: generic args in patterns require the turbofish syntax
   --> $DIR/issue-64252-self-type.rs:4:15
    |
 LL | pub fn foo(Box<Self>) { }
-   |               ^ expected one of `:`, `@`, or `|`
+   |               ^
    |
-   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this is a `self` type, give it a parameter name
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
    |
-LL | pub fn foo(self: Box<Self>) { }
-   |            +++++
-help: if this is a type, explicitly ignore the parameter name
-   |
-LL | pub fn foo(_: Box<Self>) { }
-   |            ++
+LL | pub fn foo(Box::<Self>) { }
+   |               ++
 
-error: expected one of `:`, `@`, or `|`, found `<`
-  --> $DIR/issue-64252-self-type.rs:10:15
+error: generic args in patterns require the turbofish syntax
+  --> $DIR/issue-64252-self-type.rs:9:15
    |
 LL |     fn bar(Box<Self>) { }
-   |               ^ expected one of `:`, `@`, or `|`
-   |
-   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this is a `self` type, give it a parameter name
+   |               ^
    |
-LL |     fn bar(self: Box<Self>) { }
-   |            +++++
-help: if this is a type, explicitly ignore the parameter name
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
    |
-LL |     fn bar(_: Box<Self>) { }
-   |            ++
+LL |     fn bar(Box::<Self>) { }
+   |               ++
 
 error: aborting due to 2 previous errors