https://gcc.gnu.org/g:66e5e765530782f77c6934e1b6cf63fb31075e10
commit r17-5446-g66e5e765530782f77c6934e1b6cf63fb31075e10 Author: Utkarsh Bahuguna <[email protected]> Date: Wed Oct 7 18:01:40 2026 +0530 gccrs: Fix ICE with nested patterns in multi-field constructors PatStack::pop_head_constructor appended the sub-patterns of the head at the back of the row, while Matrix::specialize puts their types at the front of the column list. With a nested pattern that has fields inside a constructor with several fields, the patterns and their types ended up in different columns and split_constructors hit its ADT assertion. Insert the sub-patterns in front of the remaining columns instead. Fixes Rust-GCC/gccrs#4973 AI assistance for writing tests. Assisted-by: Claude (Opus 5.5) gcc/rust/ChangeLog: * checks/errors/rust-hir-pattern-analysis.cc (PatStack::pop_head_constructor): Insert the sub-patterns in front of the remaining columns. gcc/testsuite/ChangeLog: * rust/compile/exhaustiveness5.rs: New test. * rust/compile/issues/issue-4973.rs: New test. Signed-off-by: Utkarsh Bahuguna <[email protected]> Diff: --- .../checks/errors/rust-hir-pattern-analysis.cc | 5 +-- gcc/testsuite/rust/compile/exhaustiveness5.rs | 34 +++++++++++++++++++ gcc/testsuite/rust/compile/issues/issue-4973.rs | 39 ++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 456b3afb9b1f..3f4e35b3ada7 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -927,8 +927,9 @@ PatStack::pop_head_constructor (const Constructor &other_ctor, other_ctor.to_string ().c_str (), s.c_str ()); } pop_head (); - for (auto &pat : v) - pats.push_back (pat); + // The sub-patterns replace the head, in order, in front of the remaining + // columns, matching the order Matrix::specialize gives their types. + pats.insert (pats.begin (), v.begin (), v.end ()); } std::string diff --git a/gcc/testsuite/rust/compile/exhaustiveness5.rs b/gcc/testsuite/rust/compile/exhaustiveness5.rs new file mode 100644 index 000000000000..032f75744d83 --- /dev/null +++ b/gcc/testsuite/rust/compile/exhaustiveness5.rs @@ -0,0 +1,34 @@ +#![feature(no_core)] +#![no_core] + +// Adapted from rustc's tests/ui/pattern/issue-6449.rs, which used to crash +// the exhaustiveness check. The `..` rest patterns of the original are spelled +// out with wildcards here. + +enum Foo { + Bar(isize), + Baz, +} + +enum Other { + Other1(Foo), + Other2(Foo, Foo), +} + +fn main() { + match Foo::Baz { + crate::Foo::Bar(3) => {} + crate::Foo::Bar(_) if false => {} + crate::Foo::Bar(_) if false => {} + crate::Foo::Bar(_n) => {} + crate::Foo::Baz => {} + } + + match Other::Other1(Foo::Baz) { + crate::Other::Other1(crate::Foo::Baz) => {} + crate::Other::Other1(crate::Foo::Bar(_)) => {} + crate::Other::Other2(crate::Foo::Baz, crate::Foo::Bar(_)) => {} + crate::Other::Other2(crate::Foo::Bar(_), crate::Foo::Baz) => {} + crate::Other::Other2(_, _) => {} + } +} diff --git a/gcc/testsuite/rust/compile/issues/issue-4973.rs b/gcc/testsuite/rust/compile/issues/issue-4973.rs new file mode 100644 index 000000000000..5b9c4331b919 --- /dev/null +++ b/gcc/testsuite/rust/compile/issues/issue-4973.rs @@ -0,0 +1,39 @@ +#![feature(no_core)] +#![no_core] + +// Rust-GCC/gccrs#4973: a pattern with fields nested in a constructor with +// several fields used to put the sub-patterns and their types in different +// columns, and crashed. + +enum Foo { + Bar(isize), + Baz(), +} + +struct Pair(Foo, Foo); + +// This is a valid match +fn f(x: Pair) { + match x { + Pair(Foo::Bar(_), Foo::Bar(_)) => {} + Pair(_, _) => {} + } +} + +fn f2(x: Pair) { + match x { + // { dg-error "non-exhaustive patterns: 'Pair . 0: Foo::Bar..., 1: Foo::Bar... .' not covered" "" { target *-*-* } .-1 } + Pair(Foo::Bar(_), Foo::Baz()) => {} + Pair(Foo::Baz(), _) => {} + } +} + +fn f3(x: Pair) { + match x { + // { dg-error "non-exhaustive patterns: 'Pair . 0: Foo::Baz.., 1: Foo::Baz.. .' not covered" "" { target *-*-* } .-1 } + Pair(Foo::Baz(), Foo::Bar(_)) => {} + Pair(Foo::Bar(_), _) => {} + } +} + +fn main() {}
