From: Utkarsh Bahuguna <[email protected]>

StructPattern::is_refutable asserted that the ADT was not an enum, so
struct patterns naming enum variants hit the assert. Return true for
multi-variant enums and continue with the existing field checks for
single-variant enums.

Fixes Rust-GCC/gccrs#4739

gcc/rust/ChangeLog:

        * hir/tree/rust-hir-pattern-abstract.cc (StructPattern::is_refutable):
        Handle enum patterns with multiple variants.

gcc/testsuite/ChangeLog:

        * rust/compile/irrefutable-struct-variant.rs: New test.
        * rust/compile/refutable-struct.rs: Add regression tests for enum
        variant patterns in function parameters and let bindings.

Signed-off-by: Utkarsh Bahuguna <[email protected]>

Tested on x86_64-pc-linux-gnu.

---
 gcc/rust/hir/tree/rust-hir-pattern-abstract.cc   |  5 ++++-
 .../rust/compile/irrefutable-struct-variant.rs   | 16 ++++++++++++++++
 gcc/testsuite/rust/compile/refutable-struct.rs   |  5 +++++
 3 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/irrefutable-struct-variant.rs

diff --git a/gcc/rust/hir/tree/rust-hir-pattern-abstract.cc 
b/gcc/rust/hir/tree/rust-hir-pattern-abstract.cc
index eac09e2d585..4fd9fbf8e25 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern-abstract.cc
+++ b/gcc/rust/hir/tree/rust-hir-pattern-abstract.cc
@@ -298,7 +298,10 @@ StructPattern::is_refutable (const TyTy::BaseType 
&scrutinee) const
   const auto *inner = scrutinee.destructure ();
   rust_assert (inner->get_kind () == TyTy::TypeKind::ADT);
   const auto &adt = static_cast<const TyTy::ADTType &> (*inner);
-  rust_assert (!adt.is_enum ());
+  // A struct pattern corresponding to an enum with multiple variants is
+  // always refutable; otherwise variant 0 is the only variant.
+  if (adt.is_enum () && adt.number_of_variants () > 1)
+    return true;
   TyTy::VariantDef *variant = adt.get_variants ().at (0);
 
   for (const auto &field : elems.get_struct_pattern_fields ())
diff --git a/gcc/testsuite/rust/compile/irrefutable-struct-variant.rs 
b/gcc/testsuite/rust/compile/irrefutable-struct-variant.rs
new file mode 100644
index 00000000000..5abab5ce702
--- /dev/null
+++ b/gcc/testsuite/rust/compile/irrefutable-struct-variant.rs
@@ -0,0 +1,16 @@
+#![feature(no_core)]
+#![no_core]
+enum E {
+    S { x: i32 },
+}
+enum T {
+    T(i32, i32),
+}
+fn _a(E::S { x }: E) {}
+fn _b(E::S { x: _y }: E) {}
+fn _c(T::T { 0: _y, 1: _z }: T) {}
+fn main() {
+    let E::S { x }: E;
+    let E::S { x: _y }: E;
+    let T::T { 0: _y, 1: _z }: T;
+}
diff --git a/gcc/testsuite/rust/compile/refutable-struct.rs 
b/gcc/testsuite/rust/compile/refutable-struct.rs
index 63097582c0c..a4392957acc 100644
--- a/gcc/testsuite/rust/compile/refutable-struct.rs
+++ b/gcc/testsuite/rust/compile/refutable-struct.rs
@@ -8,16 +8,21 @@ struct T(i32, i32);
 enum E {
     T(i32, i32),
     U(i32),
+    V { x: i32 },
 }
 fn a(S { x, y: 1 }: S) {} // { dg-error "refutable pattern" }
 fn b(S { x: 1, y: _ }: S) {} // { dg-error "refutable pattern" }
 fn c(T(1, _): T) {} // { dg-error "refutable pattern" }
 fn d(T(1, ..): T) {} // { dg-error "refutable pattern" }
 fn e(E::T(_, _): E) {} // { dg-error "refutable pattern" }
+fn f(E::V { x }: E) {} // { dg-error "refutable pattern" }
+fn g(E::V { x: _ }: E) {} // { dg-error "refutable pattern" }
 fn main() {
     let S { x, y: 1 }: S; // { dg-error "refutable pattern" }
     let S { x: 1, y: _ }: S; // { dg-error "refutable pattern" }
     let T(1, _): T; // { dg-error "refutable pattern" }
     let T(1, ..): T; // { dg-error "refutable pattern" }
     let E::T(_, _): E; // { dg-error "refutable pattern" }
+    let E::V { x }: E; // { dg-error "refutable pattern" }
+    let E::V { x: _ }: E; // { dg-error "refutable pattern" }
 }
-- 
2.55.0

Reply via email to