Skip to content

Commit 049c728

Browse files
committed
Suggests turbofish in patterns
1 parent b969b83 commit 049c728

18 files changed

+101
-50
lines changed

compiler/rustc_parse/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
270270
parse_function_body_equals_expr = function body cannot be `= expression;`
271271
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
272272
273+
parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax
274+
273275
parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
274276
.suggestion = surround the type parameters with angle brackets
275277

compiler/rustc_parse/src/errors.rs

+14
Original file line numberDiff line numberDiff line change
@@ -2731,3 +2731,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg {
27312731
#[suggestion_part(code = "")]
27322732
pub right: Span,
27332733
}
2734+
2735+
#[derive(Diagnostic)]
2736+
#[diag(parse_generic_args_in_pat_require_turbofish_syntax)]
2737+
pub(crate) struct GenericArgsInPatRequireTurbofishSyntax {
2738+
#[primary_span]
2739+
pub span: Span,
2740+
#[suggestion(
2741+
parse_sugg_turbofish_syntax,
2742+
style = "verbose",
2743+
code = "::",
2744+
applicability = "maybe-incorrect"
2745+
)]
2746+
pub suggest_turbofish: Span,
2747+
}

compiler/rustc_parse/src/parser/pat.rs

+1
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,7 @@ impl<'a> Parser<'a> {
805805
| token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
806806
| token::ModSep // A tuple / struct variant pattern.
807807
| token::Not)) // A macro expanding to a pattern.
808+
&& !(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.
808809
}
809810

810811
/// Parses `ident` or `ident @ pat`.

compiler/rustc_parse/src/parser/path.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
22
use super::{Parser, Restrictions, TokenType};
3-
use crate::errors::PathSingleColon;
3+
use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon};
44
use crate::{errors, maybe_whole};
55
use rustc_ast::ptr::P;
66
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@@ -382,6 +382,14 @@ impl<'a> Parser<'a> {
382382
};
383383

384384
PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID }
385+
} else if style == PathStyle::Pat
386+
&& self.check_noexpect(&token::Lt)
387+
&& self.look_ahead(1, |t| t.can_begin_type())
388+
{
389+
return Err(self.sess.create_err(GenericArgsInPatRequireTurbofishSyntax {
390+
span: self.token.span,
391+
suggest_turbofish: self.token.span.shrink_to_lo(),
392+
}));
385393
} else {
386394
// Generic arguments are not found.
387395
PathSegment::from_ident(ident)

tests/ui/did_you_mean/issue-114112.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
enum E<T> {
2+
A(T)
3+
}
4+
5+
fn main() {
6+
match E::<i32>::A(1) {
7+
E<i32>::A(v) => { //~ ERROR generic args in patterns require the turbofish syntax
8+
println!("{v:?}");
9+
},
10+
}
11+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: generic args in patterns require the turbofish syntax
2+
--> $DIR/issue-114112.rs:7:10
3+
|
4+
LL | E<i32>::A(v) => {
5+
| ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
8+
|
9+
LL | E::<i32>::A(v) => {
10+
| ++
11+
12+
error: aborting due to previous error
13+

tests/ui/parser/issues/issue-22647.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn main() {
2-
let caller<F> = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
2+
let caller<F> = |f: F| //~ ERROR generic args in patterns require the turbofish syntax
33
where F: Fn() -> i32
44
{
55
let x = f();
+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/issue-22647.rs:2:15
33
|
44
LL | let caller<F> = |f: F|
5-
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
5+
| ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
8+
|
9+
LL | let caller::<F> = |f: F|
10+
| ++
611

712
error: aborting due to previous error
813

tests/ui/parser/issues/issue-22712.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ struct Foo<B> {
33
}
44

55
fn bar() {
6-
let Foo<Vec<u8>> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
6+
let Foo<Vec<u8>> //~ ERROR generic args in patterns require the turbofish syntax
77
}
88

99
fn main() {}
+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/issue-22712.rs:6:12
33
|
44
LL | let Foo<Vec<u8>>
5-
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
5+
| ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
8+
|
9+
LL | let Foo::<Vec<u8>>
10+
| ++
611

712
error: aborting due to previous error
813

tests/ui/parser/pat-lt-bracket-3.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ struct Foo<T>(T, T);
33
impl<T> Foo<T> {
44
fn foo(&self) {
55
match *self {
6-
Foo<T>(x, y) => {
7-
//~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
6+
Foo<T>(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax
87
println!("Goodbye, World!")
98
}
109
}
+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
error: expected one of `=>`, `@`, `if`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/pat-lt-bracket-3.rs:6:16
33
|
44
LL | Foo<T>(x, y) => {
5-
| ^ expected one of `=>`, `@`, `if`, or `|`
5+
| ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
8+
|
9+
LL | Foo::<T>(x, y) => {
10+
| ++
611

712
error: aborting due to previous error
813

tests/ui/parser/pat-lt-bracket-4.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ enum BtNode {
55

66
fn main() {
77
let y = match 10 {
8-
Foo<T>::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
8+
Foo<T>::A(value) => value, //~ ERROR generic args in patterns require the turbofish syntax
99
Foo<T>::B => 7,
1010
};
1111
}
+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
error: expected one of `=>`, `@`, `if`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/pat-lt-bracket-4.rs:8:12
33
|
44
LL | Foo<T>::A(value) => value,
5-
| ^ expected one of `=>`, `@`, `if`, or `|`
5+
| ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
8+
|
9+
LL | Foo::<T>::A(value) => value,
10+
| ++
611

712
error: aborting due to previous error
813

tests/ui/span/issue-34264.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn foo(Option<i32>, String) {} //~ ERROR expected one of
2-
//~^ ERROR expected one of
2+
//~^ ERROR generic args in patterns require the turbofish syntax
33
fn bar(x, y: usize) {} //~ ERROR expected one of
44

55
fn main() {

tests/ui/span/issue-34264.stderr

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
error: expected one of `:`, `@`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/issue-34264.rs:1:14
33
|
44
LL | fn foo(Option<i32>, String) {}
5-
| ^ expected one of `:`, `@`, or `|`
5+
| ^
66
|
7-
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8-
help: if this is a `self` type, give it a parameter name
9-
|
10-
LL | fn foo(self: Option<i32>, String) {}
11-
| +++++
12-
help: if this is a type, explicitly ignore the parameter name
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
138
|
14-
LL | fn foo(_: Option<i32>, String) {}
15-
| ++
9+
LL | fn foo(Option::<i32>, String) {}
10+
| ++
1611

1712
error: expected one of `:`, `@`, or `|`, found `)`
1813
--> $DIR/issue-34264.rs:1:27
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
// This test checks that a suggestion to add a `self: ` parameter name is provided
22
// to functions where this is applicable.
33

4-
pub fn foo(Box<Self>) { }
5-
//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
4+
pub fn foo(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
65

76
struct Bar;
87

98
impl Bar {
10-
fn bar(Box<Self>) { }
11-
//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
9+
fn bar(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
1210
}
1311

1412
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,24 @@
1-
error: expected one of `:`, `@`, or `|`, found `<`
1+
error: generic args in patterns require the turbofish syntax
22
--> $DIR/issue-64252-self-type.rs:4:15
33
|
44
LL | pub fn foo(Box<Self>) { }
5-
| ^ expected one of `:`, `@`, or `|`
5+
| ^
66
|
7-
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8-
help: if this is a `self` type, give it a parameter name
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
98
|
10-
LL | pub fn foo(self: Box<Self>) { }
11-
| +++++
12-
help: if this is a type, explicitly ignore the parameter name
13-
|
14-
LL | pub fn foo(_: Box<Self>) { }
15-
| ++
9+
LL | pub fn foo(Box::<Self>) { }
10+
| ++
1611

17-
error: expected one of `:`, `@`, or `|`, found `<`
18-
--> $DIR/issue-64252-self-type.rs:10:15
12+
error: generic args in patterns require the turbofish syntax
13+
--> $DIR/issue-64252-self-type.rs:9:15
1914
|
2015
LL | fn bar(Box<Self>) { }
21-
| ^ expected one of `:`, `@`, or `|`
22-
|
23-
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
24-
help: if this is a `self` type, give it a parameter name
16+
| ^
2517
|
26-
LL | fn bar(self: Box<Self>) { }
27-
| +++++
28-
help: if this is a type, explicitly ignore the parameter name
18+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
2919
|
30-
LL | fn bar(_: Box<Self>) { }
31-
| ++
20+
LL | fn bar(Box::<Self>) { }
21+
| ++
3222

3323
error: aborting due to 2 previous errors
3424

0 commit comments

Comments
 (0)