Give a better diagnostic for missing parens in Fn* bounds

This commit is contained in:
clubby789 2023-10-27 19:51:51 +00:00
parent 9d6d5d4894
commit 904aceec7d
7 changed files with 73 additions and 0 deletions

View File

@ -270,6 +270,9 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
*[false] a *[false] a
} `for` parameter list } `for` parameter list
parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses
.add_paren = add the missing parentheses
parse_forgot_paren = perhaps you forgot parentheses? parse_forgot_paren = perhaps you forgot parentheses?
parse_found_expr_would_be_stmt = expected expression, found `{$token}` parse_found_expr_would_be_stmt = expected expression, found `{$token}`

View File

@ -1370,6 +1370,34 @@ pub(crate) struct FnPtrWithGenericsSugg {
pub for_param_list_exists: bool, pub for_param_list_exists: bool,
} }
pub(crate) struct FnTraitMissingParen {
pub span: Span,
pub machine_applicable: bool,
}
impl AddToDiagnostic for FnTraitMissingParen {
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
where
F: Fn(
&mut rustc_errors::Diagnostic,
rustc_errors::SubdiagnosticMessage,
) -> rustc_errors::SubdiagnosticMessage,
{
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
let applicability = if self.machine_applicable {
Applicability::MachineApplicable
} else {
Applicability::MaybeIncorrect
};
diag.span_suggestion_short(
self.span.shrink_to_hi(),
crate::fluent_generated::parse_add_paren,
"()",
applicability,
);
}
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(parse_unexpected_if_with_if)] #[diag(parse_unexpected_if_with_if)]
pub(crate) struct UnexpectedIfWithIf( pub(crate) struct UnexpectedIfWithIf(

View File

@ -2278,6 +2278,18 @@ fn parse_fn_body(
err.span_label(ident.span, "while parsing this `fn`"); err.span_label(ident.span, "while parsing this `fn`");
err.emit(); err.emit();
} else { } else {
// check for typo'd Fn* trait bounds such as
// fn foo<F>() where F: FnOnce -> () {}
if self.token.kind == token::RArrow {
let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn]
.into_iter()
.any(|s| self.prev_token.is_ident_named(s));
err.subdiagnostic(errors::FnTraitMissingParen {
span: self.prev_token.span,
machine_applicable,
});
}
return Err(err); return Err(err);
} }
} }

View File

@ -193,6 +193,9 @@
Error, Error,
File, File,
FileType, FileType,
Fn,
FnMut,
FnOnce,
FormatSpec, FormatSpec,
Formatter, Formatter,
From, From,

View File

@ -0,0 +1,8 @@
// run-rustfix
pub fn func<F>() where F: FnOnce() -> () {}
//~^ ERROR expected one of
//~| NOTE expected one of
//~| NOTE `Fn` bounds require arguments in parentheses
fn main() {}

View File

@ -0,0 +1,8 @@
// run-rustfix
pub fn func<F>() where F: FnOnce -> () {}
//~^ ERROR expected one of
//~| NOTE expected one of
//~| NOTE `Fn` bounds require arguments in parentheses
fn main() {}

View File

@ -0,0 +1,11 @@
error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
--> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34
|
LL | pub fn func<F>() where F: FnOnce -> () {}
| -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
| | |
| | help: try adding parentheses
| `Fn` bounds require arguments in parentheses
error: aborting due to previous error