Skip to content

Commit 187d1af

Browse files
committed
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.
2 parents 61a3eea + 904acee commit 187d1af

File tree

7 files changed

+73
-0
lines changed

7 files changed

+73
-0
lines changed

compiler/rustc_parse/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
270270
*[false] a
271271
} `for` parameter list
272272
273+
parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses
274+
.add_paren = add the missing parentheses
275+
273276
parse_forgot_paren = perhaps you forgot parentheses?
274277
275278
parse_found_expr_would_be_stmt = expected expression, found `{$token}`

compiler/rustc_parse/src/errors.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,34 @@ pub(crate) struct FnPtrWithGenericsSugg {
13781378
pub for_param_list_exists: bool,
13791379
}
13801380

1381+
pub(crate) struct FnTraitMissingParen {
1382+
pub span: Span,
1383+
pub machine_applicable: bool,
1384+
}
1385+
1386+
impl AddToDiagnostic for FnTraitMissingParen {
1387+
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
1388+
where
1389+
F: Fn(
1390+
&mut rustc_errors::Diagnostic,
1391+
rustc_errors::SubdiagnosticMessage,
1392+
) -> rustc_errors::SubdiagnosticMessage,
1393+
{
1394+
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
1395+
let applicability = if self.machine_applicable {
1396+
Applicability::MachineApplicable
1397+
} else {
1398+
Applicability::MaybeIncorrect
1399+
};
1400+
diag.span_suggestion_short(
1401+
self.span.shrink_to_hi(),
1402+
crate::fluent_generated::parse_add_paren,
1403+
"()",
1404+
applicability,
1405+
);
1406+
}
1407+
}
1408+
13811409
#[derive(Diagnostic)]
13821410
#[diag(parse_unexpected_if_with_if)]
13831411
pub(crate) struct UnexpectedIfWithIf(

compiler/rustc_parse/src/parser/item.rs

+12
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,18 @@ impl<'a> Parser<'a> {
22782278
err.span_label(ident.span, "while parsing this `fn`");
22792279
err.emit();
22802280
} else {
2281+
// check for typo'd Fn* trait bounds such as
2282+
// fn foo<F>() where F: FnOnce -> () {}
2283+
if self.token.kind == token::RArrow {
2284+
let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn]
2285+
.into_iter()
2286+
.any(|s| self.prev_token.is_ident_named(s));
2287+
2288+
err.subdiagnostic(errors::FnTraitMissingParen {
2289+
span: self.prev_token.span,
2290+
machine_applicable,
2291+
});
2292+
}
22812293
return Err(err);
22822294
}
22832295
}

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ symbols! {
194194
Error,
195195
File,
196196
FileType,
197+
Fn,
198+
FnMut,
199+
FnOnce,
197200
FormatSpec,
198201
Formatter,
199202
From,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
3+
pub fn func<F>() where F: FnOnce() -> () {}
4+
//~^ ERROR expected one of
5+
//~| NOTE expected one of
6+
//~| NOTE `Fn` bounds require arguments in parentheses
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
3+
pub fn func<F>() where F: FnOnce -> () {}
4+
//~^ ERROR expected one of
5+
//~| NOTE expected one of
6+
//~| NOTE `Fn` bounds require arguments in parentheses
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
2+
--> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34
3+
|
4+
LL | pub fn func<F>() where F: FnOnce -> () {}
5+
| -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
6+
| | |
7+
| | help: try adding parentheses
8+
| `Fn` bounds require arguments in parentheses
9+
10+
error: aborting due to previous error
11+

0 commit comments

Comments
 (0)