1
Fork 0

Fix bad diagnostics for anon params with ref

This commit is contained in:
Yuki Okushi 2021-03-05 04:19:15 +09:00
parent f5d8117c33
commit ea355bc6be
4 changed files with 96 additions and 35 deletions

View file

@ -1613,42 +1613,65 @@ impl<'a> Parser<'a> {
Applicability::HasPlaceholders, Applicability::HasPlaceholders,
); );
return Some(ident); return Some(ident);
} else if let PatKind::Ident(_, ident, _) = pat.kind { } else if require_name
if require_name && (self.token == token::Comma
&& (self.token == token::Comma || self.token == token::Lt
|| self.token == token::Lt || self.token == token::CloseDelim(token::Paren))
|| self.token == token::CloseDelim(token::Paren)) {
{ let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}` PatKind::Ident(_, ident, _) => (
if first_param { ident,
err.span_suggestion( format!("self: {}", ident),
pat.span, format!("{}: TypeName", ident),
"if this is a `self` type, give it a parameter name", format!("_: {}", ident),
format!("self: {}", ident), ),
Applicability::MaybeIncorrect, // Also catches `fn foo(&a)`.
); PatKind::Ref(ref pat, mutab) => {
} if let PatKind::Ident(_, ident, _) = pat.clone().into_inner().kind {
// Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to let mutab = mutab.prefix_str();
// `fn foo(HashMap: TypeName<u32>)`. (
if self.token != token::Lt { ident,
err.span_suggestion( format!("self: &{}{}", mutab, ident),
pat.span, format!("{}: &{}TypeName", ident, mutab),
"if this is a parameter name, give it a type", format!("_: &{}{}", mutab, ident),
format!("{}: TypeName", ident), )
Applicability::HasPlaceholders, } else {
); return None;
}
} }
// Ignore other `PatKind`.
_ => return None,
};
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
if first_param {
err.span_suggestion( err.span_suggestion(
pat.span, pat.span,
"if this is a type, explicitly ignore the parameter name", "if this is a `self` type, give it a parameter name",
format!("_: {}", ident), self_sugg,
Applicability::MachineApplicable, Applicability::MaybeIncorrect,
); );
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
return if self.token == token::Lt { None } else { Some(ident) };
} }
// Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
// `fn foo(HashMap: TypeName<u32>)`.
if self.token != token::Lt {
err.span_suggestion(
pat.span,
"if this is a parameter name, give it a type",
param_sugg,
Applicability::HasPlaceholders,
);
}
err.span_suggestion(
pat.span,
"if this is a type, explicitly ignore the parameter name",
type_sugg,
Applicability::MachineApplicable,
);
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
return if self.token == token::Lt { None } else { Some(ident) };
} }
None None
} }

View file

@ -5,6 +5,10 @@
trait T { trait T {
fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)` fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)`
// Also checks with `&`
fn foo_with_ref(&mut i32);
//~^ ERROR expected one of `:`, `@`, or `|`, found `)`
fn bar_with_default_impl(String, String) {} fn bar_with_default_impl(String, String) {}
//~^ ERROR expected one of `:` //~^ ERROR expected one of `:`
//~| ERROR expected one of `:` //~| ERROR expected one of `:`

View file

@ -18,8 +18,28 @@ help: if this is a type, explicitly ignore the parameter name
LL | fn foo(_: i32); LL | fn foo(_: i32);
| ^^^^^^ | ^^^^^^
error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:9:29
|
LL | fn foo_with_ref(&mut i32);
| ^ 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_with_ref(self: &mut i32);
| ^^^^^^^^^^^^^^
help: if this is a parameter name, give it a type
|
LL | fn foo_with_ref(i32: &mut TypeName);
| ^^^^^^^^^^^^^^^^^^
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo_with_ref(_: &mut i32);
| ^^^^^^^^^^^
error: expected one of `:`, `@`, or `|`, found `,` error: expected one of `:`, `@`, or `|`, found `,`
--> $DIR/anon-params-denied-2018.rs:8:36 --> $DIR/anon-params-denied-2018.rs:12:36
| |
LL | fn bar_with_default_impl(String, String) {} LL | fn bar_with_default_impl(String, String) {}
| ^ expected one of `:`, `@`, or `|` | ^ expected one of `:`, `@`, or `|`
@ -39,7 +59,7 @@ LL | fn bar_with_default_impl(_: String, String) {}
| ^^^^^^^^^ | ^^^^^^^^^
error: expected one of `:`, `@`, or `|`, found `)` error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:8:44 --> $DIR/anon-params-denied-2018.rs:12:44
| |
LL | fn bar_with_default_impl(String, String) {} LL | fn bar_with_default_impl(String, String) {}
| ^ expected one of `:`, `@`, or `|` | ^ expected one of `:`, `@`, or `|`
@ -55,7 +75,7 @@ LL | fn bar_with_default_impl(String, _: String) {}
| ^^^^^^^^^ | ^^^^^^^^^
error: expected one of `:`, `@`, or `|`, found `,` error: expected one of `:`, `@`, or `|`, found `,`
--> $DIR/anon-params-denied-2018.rs:13:22 --> $DIR/anon-params-denied-2018.rs:17:22
| |
LL | fn baz(a:usize, b, c: usize) -> usize { LL | fn baz(a:usize, b, c: usize) -> usize {
| ^ expected one of `:`, `@`, or `|` | ^ expected one of `:`, `@`, or `|`
@ -70,5 +90,5 @@ help: if this is a type, explicitly ignore the parameter name
LL | fn baz(a:usize, _: b, c: usize) -> usize { LL | fn baz(a:usize, _: b, c: usize) -> usize {
| ^^^^ | ^^^^
error: aborting due to 4 previous errors error: aborting due to 5 previous errors

View file

@ -9,6 +9,20 @@ error: expected one of `:`, `@`, or `|`, found `)`
| |
LL | fn test(&'a str) { LL | fn test(&'a str) {
| ^ expected one of `:`, `@`, or `|` | ^ 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 test(self: &str) {
| ^^^^^^^^^^
help: if this is a parameter name, give it a type
|
LL | fn test(str: &TypeName) {
| ^^^^^^^^^^^^^^
help: if this is a type, explicitly ignore the parameter name
|
LL | fn test(_: &str) {
| ^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors