Suggests turbofish in patterns
This commit is contained in:
parent
b969b830aa
commit
049c728c60
18 changed files with 101 additions and 50 deletions
|
@ -270,6 +270,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
|
||||||
parse_function_body_equals_expr = function body cannot be `= expression;`
|
parse_function_body_equals_expr = function body cannot be `= expression;`
|
||||||
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
.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
|
parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
|
||||||
.suggestion = surround the type parameters with angle brackets
|
.suggestion = surround the type parameters with angle brackets
|
||||||
|
|
||||||
|
|
|
@ -2731,3 +2731,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg {
|
||||||
#[suggestion_part(code = "")]
|
#[suggestion_part(code = "")]
|
||||||
pub right: Span,
|
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,
|
||||||
|
}
|
||||||
|
|
|
@ -805,6 +805,7 @@ impl<'a> Parser<'a> {
|
||||||
| token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
|
| token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
|
||||||
| token::ModSep // A tuple / struct variant pattern.
|
| token::ModSep // A tuple / struct variant pattern.
|
||||||
| token::Not)) // A macro expanding to a 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`.
|
/// Parses `ident` or `ident @ pat`.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||||
use super::{Parser, Restrictions, TokenType};
|
use super::{Parser, Restrictions, TokenType};
|
||||||
use crate::errors::PathSingleColon;
|
use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon};
|
||||||
use crate::{errors, maybe_whole};
|
use crate::{errors, maybe_whole};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
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 }
|
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 {
|
} else {
|
||||||
// Generic arguments are not found.
|
// Generic arguments are not found.
|
||||||
PathSegment::from_ident(ident)
|
PathSegment::from_ident(ident)
|
||||||
|
|
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
|
@ -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:?}");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
|
@ -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
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fn main() {
|
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
|
where F: Fn() -> i32
|
||||||
{
|
{
|
||||||
let x = f();
|
let x = f();
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-22647.rs:2:15
|
||||||
|
|
|
|
||||||
LL | let caller<F> = |f: F|
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ struct Foo<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() {
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-22712.rs:6:12
|
||||||
|
|
|
|
||||||
LL | let Foo<Vec<u8>>
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@ struct Foo<T>(T, T);
|
||||||
impl<T> Foo<T> {
|
impl<T> Foo<T> {
|
||||||
fn foo(&self) {
|
fn foo(&self) {
|
||||||
match *self {
|
match *self {
|
||||||
Foo<T>(x, y) => {
|
Foo<T>(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
//~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
|
||||||
println!("Goodbye, World!")
|
println!("Goodbye, World!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
--> $DIR/pat-lt-bracket-3.rs:6:16
|
||||||
|
|
|
|
||||||
LL | Foo<T>(x, y) => {
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ enum BtNode {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let y = match 10 {
|
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,
|
Foo<T>::B => 7,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
--> $DIR/pat-lt-bracket-4.rs:8:12
|
||||||
|
|
|
|
||||||
LL | Foo<T>::A(value) => value,
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fn foo(Option<i32>, String) {} //~ ERROR expected one of
|
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 bar(x, y: usize) {} //~ ERROR expected one of
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
error: expected one of `:`, `@`, or `|`, found `<`
|
error: generic args in patterns require the turbofish syntax
|
||||||
--> $DIR/issue-34264.rs:1:14
|
--> $DIR/issue-34264.rs:1:14
|
||||||
|
|
|
|
||||||
LL | fn foo(Option<i32>, String) {}
|
LL | fn foo(Option<i32>, String) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^
|
||||||
|
|
|
|
||||||
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
help: if this is a `self` type, give it a parameter name
|
|
||||||
|
|
|
|
||||||
LL | fn foo(self: Option<i32>, String) {}
|
LL | fn foo(Option::<i32>, String) {}
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
|
||||||
|
|
|
||||||
LL | fn foo(_: Option<i32>, String) {}
|
|
||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: expected one of `:`, `@`, or `|`, found `)`
|
error: expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// This test checks that a suggestion to add a `self: ` parameter name is provided
|
// This test checks that a suggestion to add a `self: ` parameter name is provided
|
||||||
// to functions where this is applicable.
|
// to functions where this is applicable.
|
||||||
|
|
||||||
pub fn foo(Box<Self>) { }
|
pub fn foo(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
|
|
||||||
|
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl Bar {
|
impl Bar {
|
||||||
fn bar(Box<Self>) { }
|
fn bar(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -1,33 +1,23 @@
|
||||||
error: expected one of `:`, `@`, or `|`, found `<`
|
error: generic args in patterns require the turbofish syntax
|
||||||
--> $DIR/issue-64252-self-type.rs:4:15
|
--> $DIR/issue-64252-self-type.rs:4:15
|
||||||
|
|
|
|
||||||
LL | pub fn foo(Box<Self>) { }
|
LL | pub fn foo(Box<Self>) { }
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^
|
||||||
|
|
|
|
||||||
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
help: if this is a `self` type, give it a parameter name
|
|
||||||
|
|
|
|
||||||
LL | pub fn foo(self: Box<Self>) { }
|
LL | pub fn foo(Box::<Self>) { }
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
|
||||||
|
|
|
||||||
LL | pub fn foo(_: Box<Self>) { }
|
|
||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: expected one of `:`, `@`, or `|`, found `<`
|
error: generic args in patterns require the turbofish syntax
|
||||||
--> $DIR/issue-64252-self-type.rs:10:15
|
--> $DIR/issue-64252-self-type.rs:9:15
|
||||||
|
|
|
|
||||||
LL | fn bar(Box<Self>) { }
|
LL | fn bar(Box<Self>) { }
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^
|
||||||
|
|
|
|
||||||
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
help: if this is a `self` type, give it a parameter name
|
|
||||||
|
|
|
|
||||||
LL | fn bar(self: Box<Self>) { }
|
LL | fn bar(Box::<Self>) { }
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
|
||||||
|
|
|
||||||
LL | fn bar(_: Box<Self>) { }
|
|
||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue