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() {}

Reply via email to