Skip to content

Commit

Permalink
Give a better diagnostic for missing parens in Fn* bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed Oct 27, 2023
1 parent 9d6d5d4 commit a2d48a4
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 0 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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_trait}` 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}`
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,30 @@ pub(crate) struct FnPtrWithGenericsSugg {
pub for_param_list_exists: bool,
}

pub(crate) struct FnTraitMissingParen {
pub span: Span,
pub fn_trait: Symbol,
}

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.set_arg("fn_trait", self.fn_trait);
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
diag.span_suggestion_short(
self.span.shrink_to_hi(),
crate::fluent_generated::parse_add_paren,
"()",
Applicability::MachineApplicable,
);
}
}

#[derive(Diagnostic)]
#[diag(parse_unexpected_if_with_if)]
pub(crate) struct UnexpectedIfWithIf(
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2278,6 +2278,19 @@ 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 -> () {}
let prev = self.prev_token.clone();
if self.eat_noexpect(&token::RArrow)
&& let Some(t) = [sym::FnOnce, sym::FnMut, sym::Fn]
.into_iter()
.find(|s| prev.is_ident_named(*s))
{
err.subdiagnostic(errors::FnTraitMissingParen {
span: prev.span,
fn_trait: t,
});
}
return Err(err);
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ symbols! {
Error,
File,
FileType,
Fn,
FnMut,
FnOnce,
FormatSpec,
Formatter,
From,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// run-rustfix

pub fn handle<F>() where F: FnOnce() -> () {}
//~^ ERROR expected one of
//~| NOTE expected one of
//~| NOTE `FnOnce` bounds require arguments in parentheses

fn main() {}
8 changes: 8 additions & 0 deletions tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// run-rustfix

pub fn handle<F>() where F: FnOnce -> () {}
//~^ ERROR expected one of
//~| NOTE expected one of
//~| NOTE `FnOnce` bounds require arguments in parentheses

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
--> $DIR/issue-108109-fn-trait-missing-paren.rs:3:36
|
LL | pub fn handle<F>() where F: FnOnce -> () {}
| -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
| | |
| | help: try adding parentheses
| `FnOnce` bounds require arguments in parentheses

error: aborting due to previous error

0 comments on commit a2d48a4

Please sign in to comment.