Auto merge of #117297 - clubby789:fn-trait-missing-paren, r=TaKO8Ki

Give a better diagnostic for missing parens in Fn* bounds

Fixes #108109

It would be nice to try and recover here, but I'm not sure it's worth the effort, especially as the bounds on the recovered function would be incorrect.
This commit is contained in:
bors 2023-11-07 13:04:56 +00:00
commit 187d1afa9d
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
} `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_found_expr_would_be_stmt = expected expression, found `{$token}`

View File

@ -1378,6 +1378,34 @@ pub(crate) struct FnPtrWithGenericsSugg {
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)]
#[diag(parse_unexpected_if_with_if)]
pub(crate) struct UnexpectedIfWithIf(

View File

@ -2278,6 +2278,18 @@ impl<'a> Parser<'a> {
err.span_label(ident.span, "while parsing this `fn`");
err.emit();
} 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);
}
}

View File

@ -194,6 +194,9 @@ symbols! {
Error,
File,
FileType,
Fn,
FnMut,
FnOnce,
FormatSpec,
Formatter,
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