diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-10-03 04:08:14 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-03 04:08:14 +0200 |
| commit | faf2e8087c54d2a778e293f093a34fa18f48f0f2 (patch) | |
| tree | d9e1ff20f5438bb7af5e302dfb19911b9742c1f2 /src/libsyntax/parse | |
| parent | 17b1fd1a8f1cdb9fbe1220aa5f7d8d568be6b4aa (diff) | |
| parent | 2537a8aa7a44d76b3345b98f394f6d2744f3a9cc (diff) | |
| download | rust-faf2e8087c54d2a778e293f093a34fa18f48f0f2.tar.gz rust-faf2e8087c54d2a778e293f093a34fa18f48f0f2.zip | |
Rollup merge of #64959 - davidtwco:issue-64252-self-type-help, r=Centril,estebank
syntax: improve parameter without type suggestions Fixes #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
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/diagnostics.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 1 |
2 files changed, 25 insertions, 8 deletions
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index e8d7b7663ed..4ad0bd06d99 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -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) @@ -1241,14 +1242,27 @@ 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", @@ -1256,7 +1270,9 @@ impl<'a> Parser<'a> { 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 diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 95f84d5cb33..d4a6e9f6c6b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1212,6 +1212,7 @@ impl<'a> Parser<'a> { &mut err, pat, is_name_required, + is_self_allowed, is_trait_item, ) { err.emit(); |
