From ca1bcb64667410c7f59ec5745e012601eea3d65f Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 27 Oct 2023 20:12:45 +0000 Subject: [PATCH] Recover from missing param list in function definitions --- compiler/rustc_parse/messages.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 8 ++++++++ compiler/rustc_parse/src/parser/item.rs | 10 ++++++++++ tests/ui/mismatched_types/recovered-block.rs | 6 ------ tests/ui/mismatched_types/recovered-block.stderr | 8 +------- .../issues/issue-108109-fn-missing-params.fixed | 9 +++++++++ .../issues/issue-108109-fn-missing-params.rs | 9 +++++++++ .../issues/issue-108109-fn-missing-params.stderr | 14 ++++++++++++++ tests/ui/parser/removed-syntax-fn-sigil.rs | 3 ++- tests/ui/parser/removed-syntax-fn-sigil.stderr | 14 +++++++++----- 10 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 tests/ui/parser/issues/issue-108109-fn-missing-params.fixed create mode 100644 tests/ui/parser/issues/issue-108109-fn-missing-params.rs create mode 100644 tests/ui/parser/issues/issue-108109-fn-missing-params.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e0778f72bfe6e..6e0d44bd00e42 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -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 diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index aeb4fd0a304aa..f22d70ec809f8 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -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 { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 982f601c0d5a2..d4f7083c397f0 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2492,6 +2492,16 @@ impl<'a> Parser<'a> { pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... + if self.token.kind != TokenKind::OpenDelim(Delimiter::Parenthesis) + // might be typo'd trait impl, handled elsewhere + && !self.token.is_keyword(kw::For) + { + // recover from missing argument list, e.g. `fn main -> () {}` + self.sess + .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() }); + return Ok(ThinVec::new()); + } + let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_diff_marker(); let param = p.parse_param_general(req_name, first_param).or_else(|mut e| { diff --git a/tests/ui/mismatched_types/recovered-block.rs b/tests/ui/mismatched_types/recovered-block.rs index b230b47d35d37..a91bbe7083bc2 100644 --- a/tests/ui/mismatched_types/recovered-block.rs +++ b/tests/ui/mismatched_types/recovered-block.rs @@ -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() {} diff --git a/tests/ui/mismatched_types/recovered-block.stderr b/tests/ui/mismatched_types/recovered-block.stderr index f275321abe5eb..88d625456564f 100644 --- a/tests/ui/mismatched_types/recovered-block.stderr +++ b/tests/ui/mismatched_types/recovered-block.stderr @@ -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 diff --git a/tests/ui/parser/issues/issue-108109-fn-missing-params.fixed b/tests/ui/parser/issues/issue-108109-fn-missing-params.fixed new file mode 100644 index 0000000000000..b819aa810cb77 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-missing-params.fixed @@ -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() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-missing-params.rs b/tests/ui/parser/issues/issue-108109-fn-missing-params.rs new file mode 100644 index 0000000000000..01efe728081f3 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-missing-params.rs @@ -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() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-missing-params.stderr b/tests/ui/parser/issues/issue-108109-fn-missing-params.stderr new file mode 100644 index 0000000000000..86d3449cc33b6 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-missing-params.stderr @@ -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 + diff --git a/tests/ui/parser/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax-fn-sigil.rs index 725843429c003..d55a032d1f278 100644 --- a/tests/ui/parser/removed-syntax-fn-sigil.rs +++ b/tests/ui/parser/removed-syntax-fn-sigil.rs @@ -1,3 +1,4 @@ fn main() { - let x: fn~() = || (); //~ ERROR expected `(`, found `~` + let x: fn~() = || (); //~ ERROR missing parameters for function definition + //~| ERROR expected one of `->`, `;`, or `=`, found `~` } diff --git a/tests/ui/parser/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax-fn-sigil.stderr index 196a5af472938..0d37741670066 100644 --- a/tests/ui/parser/removed-syntax-fn-sigil.stderr +++ b/tests/ui/parser/removed-syntax-fn-sigil.stderr @@ -1,10 +1,14 @@ -error: expected `(`, found `~` +error: missing parameters for function definition --> $DIR/removed-syntax-fn-sigil.rs:2:14 | LL | let x: fn~() = || (); - | - ^ expected `(` - | | - | while parsing the type for `x` + | ^ help: add a parameter list -error: aborting due to previous error +error: expected one of `->`, `;`, or `=`, found `~` + --> $DIR/removed-syntax-fn-sigil.rs:2:14 + | +LL | let x: fn~() = || (); + | ^ expected one of `->`, `;`, or `=` + +error: aborting due to 2 previous errors