diff options
| author | David Wood <david@davidtw.co> | 2019-10-01 15:17:50 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2019-10-02 09:51:27 +0100 |
| commit | 2537a8aa7a44d76b3345b98f394f6d2744f3a9cc (patch) | |
| tree | ee4189157d797893692099a1220c87a74b7973cc /src/libsyntax/parse/diagnostics.rs | |
| parent | ff191b54cc8a95e3bfc7ae5f8f9984f934758165 (diff) | |
| download | rust-2537a8aa7a44d76b3345b98f394f6d2744f3a9cc.tar.gz rust-2537a8aa7a44d76b3345b98f394f6d2744f3a9cc.zip | |
syntax: improve parameter without type suggestions
This commit 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 `:`. Signed-off-by: David Wood <david@davidtw.co>
Diffstat (limited to 'src/libsyntax/parse/diagnostics.rs')
| -rw-r--r-- | src/libsyntax/parse/diagnostics.rs | 32 |
1 files changed, 24 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 |
