Skip to content

Commit

Permalink
Rollup merge of rust-lang#64959 - davidtwco:issue-64252-self-type-hel…
Browse files Browse the repository at this point in the history
…p, r=Centril,estebank

syntax: improve parameter without type suggestions

Fixes rust-lang#64252.

This PR improves the suggestions provided when function parameters
do not have types:

- A new suggestion is added for arbitrary self types, which suggests
adding `self: ` before the type.

- Existing suggestions are now provided when a `<` is found where a `:`
was expected (previously only `,` and `)` or trait items), this gives
suggestions in the case where the unnamed parameter type is generic
in a free function.

- The suggestion that a type name be provided (e.g. `fn foo(HashMap<u32>)`
-> `fn foo(HashMap: TypeName<u32>)`) will no longer occur when a `<` was
found instead of `:`.

- The ident will not be used for recovery when a `<` was found instead
of `:`.

r? @Centril
cc @estebank @yoshuawuyts
  • Loading branch information
Centril authored Oct 3, 2019
2 parents 17b1fd1 + 2537a8a commit faf2e80
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 8 deletions.
32 changes: 24 additions & 8 deletions src/libsyntax/parse/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,7 @@ impl<'a> Parser<'a> {
err: &mut DiagnosticBuilder<'_>,
pat: P<ast::Pat>,
require_name: bool,
is_self_allowed: bool,
is_trait_item: bool,
) -> Option<Ident> {
// If we find a pattern followed by an identifier, it could be an (incorrect)
Expand All @@ -1241,22 +1242,37 @@ impl<'a> Parser<'a> {
if require_name && (
is_trait_item ||
self.token == token::Comma ||
self.token == token::Lt ||
self.token == token::CloseDelim(token::Paren)
) { // `fn foo(a, b) {}` or `fn foo(usize, usize) {}`
err.span_suggestion(
pat.span,
"if this was a parameter name, give it a type",
format!("{}: TypeName", ident),
Applicability::HasPlaceholders,
);
) { // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
if is_self_allowed {
err.span_suggestion(
pat.span,
"if this is a `self` type, give it a parameter name",
format!("self: {}", ident),
Applicability::MaybeIncorrect,
);
}
// 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 was a parameter name, give it a type",
format!("{}: TypeName", ident),
Applicability::HasPlaceholders,
);
}
err.span_suggestion(
pat.span,
"if this is a type, explicitly ignore the parameter name",
format!("_: {}", ident),
Applicability::MachineApplicable,
);
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
return Some(ident);

// 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
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,7 @@ impl<'a> Parser<'a> {
&mut err,
pat,
is_name_required,
is_self_allowed,
is_trait_item,
) {
err.emit();
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/anon-params-denied-2018.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | fn foo(i32);
| ^ expected one of `:`, `@`, or `|` here
|
= 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: i32);
| ^^^^^^^^^
help: if this was a parameter name, give it a type
|
LL | fn foo(i32: TypeName);
Expand All @@ -21,6 +25,10 @@ LL | fn bar_with_default_impl(String, String) {}
| ^ expected one of `:`, `@`, or `|` here
|
= 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_with_default_impl(self: String, String) {}
| ^^^^^^^^^^^^
help: if this was a parameter name, give it a type
|
LL | fn bar_with_default_impl(String: TypeName, String) {}
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/parser/pat-lt-bracket-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
LL | fn a(B<) {}
| ^ expected one of `:`, `@`, or `|` here
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a type, explicitly ignore the parameter name
|
LL | fn a(_: B<) {}
| ^^^^

error: aborting due to previous error

4 changes: 4 additions & 0 deletions src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | trait Trait2015 { fn foo(#[allow(C)] i32); }
| ^ expected one of `:`, `@`, or `|` here
|
= 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 | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
| ^^^^^^^^^
help: if this was a parameter name, give it a type
|
LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/span/issue-34264.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
LL | fn foo(Option<i32>, String) {}
| ^ expected one of `:`, `@`, or `|` here
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(_: Option<i32>, String) {}
| ^^^^^^^^^

error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/issue-34264.rs:1:27
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/suggestions/issue-64252-self-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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 `<`

struct Bar;

impl Bar {
fn bar(Box<Self>) { }
//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
}

fn main() { }
30 changes: 30 additions & 0 deletions src/test/ui/suggestions/issue-64252-self-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error: expected one of `:`, `@`, or `|`, found `<`
--> $DIR/issue-64252-self-type.rs:4:15
|
LL | pub fn foo(Box<Self>) { }
| ^ expected one of `:`, `@`, or `|` here
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a type, explicitly ignore the parameter name
|
LL | pub fn foo(_: Box<Self>) { }
| ^^^^^^

error: expected one of `:`, `@`, or `|`, found `<`
--> $DIR/issue-64252-self-type.rs:10:15
|
LL | fn bar(Box<Self>) { }
| ^ expected one of `:`, `@`, or `|` here
|
= 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
|
LL | fn bar(_: Box<Self>) { }
| ^^^^^^

error: aborting due to 2 previous errors

0 comments on commit faf2e80

Please sign in to comment.