Skip to content

Commit

Permalink
Recover from missing param list in function definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed Oct 27, 2023
1 parent 10143e7 commit 0c8ef4c
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 15 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ parse_missing_fn_for_function_definition = missing `fn` for function definition
parse_missing_fn_for_method_definition = missing `fn` for method definition
.suggestion = add `fn` here to parse `{$ident}` as a public method
parse_missing_fn_params = missing parameters for function definition
.suggestion = add a parameter list
parse_missing_for_in_trait_impl = missing `for` in a trait impl
.suggestion = add `for` here
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,14 @@ pub(crate) enum AmbiguousMissingKwForItemSub {
HelpMacro,
}

#[derive(Diagnostic)]
#[diag(parse_missing_fn_params)]
pub(crate) struct MissingFnParams {
#[primary_span]
#[suggestion(code = "()", applicability = "machine-applicable", style = "short")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_missing_trait_in_trait_impl)]
pub(crate) struct MissingTraitInTraitImpl {
Expand Down
26 changes: 24 additions & 2 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2492,7 +2492,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
let mut first_param = true;
// Parse the arguments, starting out with `self` being allowed...
let (mut params, _) = self.parse_paren_comma_seq(|p| {
let parsed = self.parse_paren_comma_seq(|p| {
p.recover_diff_marker();
let param = p.parse_param_general(req_name, first_param).or_else(|mut e| {
e.emit();
Expand All @@ -2505,7 +2505,29 @@ impl<'a> Parser<'a> {
// ...now that we've parsed the first argument, `self` is no longer allowed.
first_param = false;
param
})?;
});
let mut params = match parsed {
Ok((p, _)) => p,
Err(e) => {
// some error while parsing params
if self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis) ||
// removed syntax, handled elsewhere
self.token.kind == TokenKind::Tilde ||
// might be typo'd trait impl, handled elsewhere
self.token.is_keyword(kw::For)
{
return Err(e);
} else {
// recover from missing argument list, e.g. `fn main -> () {}`
e.cancel();
self.sess.emit_err(errors::MissingFnParams {
span: self.prev_token.span.shrink_to_hi(),
});
return Ok(ThinVec::new());
}
}
};

// Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
self.deduplicate_recovered_params_names(&mut params);
Ok(params)
Expand Down
6 changes: 0 additions & 6 deletions tests/ui/mismatched_types/recovered-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,4 @@ pub fn foo() -> Foo {
}
//~^^ ERROR missing `struct` for struct definition

pub fn bar() -> Foo {
fn
Foo { text: "".to_string() }
}
//~^^ ERROR expected one of `(` or `<`, found `{`

fn main() {}
8 changes: 1 addition & 7 deletions tests/ui/mismatched_types/recovered-block.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,5 @@ help: add `struct` here to parse `Foo` as a public struct
LL | pub struct Foo { text }
| ++++++

error: expected one of `(` or `<`, found `{`
--> $DIR/recovered-block.rs:17:9
|
LL | Foo { text: "".to_string() }
| ^ expected one of `(` or `<`

error: aborting due to 2 previous errors
error: aborting due to previous error

9 changes: 9 additions & 0 deletions tests/ui/parser/issues/issue-108109-fn-missing-params.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// run-rustfix

pub fn missing() -> () {}
//~^ ERROR missing parameters for function definition

pub fn missing2() {}
//~^ ERROR missing parameters for function definition

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

pub fn missing -> () {}
//~^ ERROR missing parameters for function definition

pub fn missing2 {}
//~^ ERROR missing parameters for function definition

fn main() {}
14 changes: 14 additions & 0 deletions tests/ui/parser/issues/issue-108109-fn-missing-params.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: missing parameters for function definition
--> $DIR/issue-108109-fn-missing-params.rs:3:15
|
LL | pub fn missing -> () {}
| ^ help: add a parameter list

error: missing parameters for function definition
--> $DIR/issue-108109-fn-missing-params.rs:6:16
|
LL | pub fn missing2 {}
| ^ help: add a parameter list

error: aborting due to 2 previous errors

0 comments on commit 0c8ef4c

Please sign in to comment.