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