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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/5b690de8dff339fb41563cfd7498ad5095ba9c5a

The commit has been mentioned in the following issue(s):
 - Rust-GCC/gccrs#4739: https://github.com/Rust-GCC/gccrs/issues/4739

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4817

 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 eac09e2d5..4fd9fbf8e 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 000000000..5abab5ce7
--- /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 63097582c..a4392957a 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" }
 }

base-commit: cd47eb1fd1c94e316693b6300d1f8282905c6553
-- 
2.56.0

Reply via email to