From e9b890b7b934a9233ae057f4b3d3be3fc654d473 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 9 Sep 2026 05:02:14 +0900 Subject: [PATCH] avoid ICEs when recovering malformed function parameters --- .../rustc_parse/src/parser/diagnostics.rs | 31 +++++++++++++------ .../recover-invalid-fn-trait-bound-pattern.rs | 5 +++ ...over-invalid-fn-trait-bound-pattern.stderr | 20 ++++++++++++ ...over-invalid-function-parameter-pattern.rs | 6 ++++ ...-invalid-function-parameter-pattern.stderr | 28 +++++++++++++++++ 5 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 6d4a0215eb7b3..38f129919dfe8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2374,15 +2374,28 @@ impl<'a> Parser<'a> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; - self.dcx().emit_err(PatternMethodParamWithoutBody { - span: pat.span, - target: match context { - FnContext::Trait => "methods without bodies", - FnContext::FunctionPtrType => "function pointer types", - FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"), - FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"), - }, - }); + match context { + FnContext::Trait | FnContext::FunctionPtrType => { + self.dcx().emit_err(PatternMethodParamWithoutBody { + span: pat.span, + target: if context == FnContext::Trait { + "methods without bodies" + } else { + "function pointer types" + }, + }); + } + FnContext::Free | FnContext::Impl => { + self.dcx().span_delayed_bug( + pat.span, + if context == FnContext::Free { + "This method is not called in free functions, as patterns are always allowed there" + } else { + "This method is not called in impls, as patterns are always allowed there" + }, + ); + } + } // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID }); diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs new file mode 100644 index 0000000000000..abbff103bb2be --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs @@ -0,0 +1,5 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +struct Baz where U : fn(() : bool) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected `{` after struct name, found `` diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr new file mode 100644 index 0000000000000..02ec950b3a365 --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:22 + | +LL | struct Baz where U : fn(() : bool) + | ^^ + | +help: use `Fn` to refer to the trait (notice the capitalization) + | +LL - struct Baz where U : fn(() : bool) +LL + struct Baz where U : Fn(() : bool) + | + +error: expected `{` after struct name, found `` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:34 + | +LL | struct Baz where U : fn(() : bool) + | ^ expected `{` after struct name + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs new file mode 100644 index 0000000000000..a9e6a5578486f --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs @@ -0,0 +1,6 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +fn main(... : ...) +//~^ ERROR unexpected `...` +//~| ERROR unexpected `...` +//~| ERROR expected one of `->`, `where`, or `{`, found `` diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr new file mode 100644 index 0000000000000..d4b78db29dba9 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr @@ -0,0 +1,28 @@ +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:9 + | +LL | fn main(... : ...) + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - fn main(... : ...) +LL + fn main(.. : ...) + | + +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:15 + | +LL | fn main(... : ...) + | ^^^ + | + = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:18 + | +LL | fn main(... : ...) + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 3 previous errors +