From: Liam Naddell <liam.nadd...@mail.utoronto.ca>

gcc/rust/ChangeLog:
        * typecheck/rust-hir-type-check-pattern.cc:
        Emit E0532 when trying to reference a Tuple or Struct variant
        using a non Tuple or Struct pattern.

gcc/testsuite/ChangeLog:
        * rust/compile/issue-2324-1.rs:
        add test for E0532 with tuple enum variant
        * rust/compile/issue-2324-2.rs:
        add test for E0532 with struct enum variant

Signed-off-by: Liam Naddell <liam.nadd...@mail.utoronto.ca>
---
 .../typecheck/rust-hir-type-check-pattern.cc  | 25 +++++++++++++++++++
 gcc/testsuite/rust/compile/issue-2324-1.rs    | 19 ++++++++++++++
 gcc/testsuite/rust/compile/issue-2324-2.rs    | 19 ++++++++++++++
 3 files changed, 63 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2324-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-2324-2.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc 
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index c469f6095d8..1a3d0ecd185 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -44,6 +44,31 @@ void
 TypeCheckPattern::visit (HIR::PathInExpression &pattern)
 {
   infered = TypeCheckExpr::Resolve (&pattern);
+
+  /*
+   * We are compiling a PathInExpression, which can't be a Struct or Tuple
+   * pattern. We should check that the declaration we are referencing IS NOT a
+   * struct pattern or tuple with values.
+   */
+
+  rust_assert (infered->get_kind () == TyTy::TypeKind::ADT);
+  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
+
+  HirId variant_id = UNKNOWN_HIRID;
+  bool ok
+    = context->lookup_variant_definition (pattern.get_mappings ().get_hirid (),
+                                         &variant_id);
+  rust_assert (ok);
+
+  TyTy::VariantDef *variant = nullptr;
+  ok = adt->lookup_variant_by_id (variant_id, &variant);
+
+  TyTy::VariantDef::VariantType vty = variant->get_variant_type ();
+
+  if (vty != TyTy::VariantDef::VariantType::NUM)
+    rust_error_at (
+      pattern.get_final_segment ().get_locus (), ErrorCode::E0532,
+      "expected unit struct, unit variant or constant, found tuple variant");
 }
 
 void
diff --git a/gcc/testsuite/rust/compile/issue-2324-1.rs 
b/gcc/testsuite/rust/compile/issue-2324-1.rs
new file mode 100644
index 00000000000..afce1f3b570
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2324-1.rs
@@ -0,0 +1,19 @@
+enum State {
+    Succeeded,
+    Failed(u32),
+}
+
+fn print_on_failure(state: &State) {
+    match *state {
+        State::Succeeded => (),
+        State::Failed => (), // { dg-error "expected unit struct, unit variant 
or constant, found tuple variant" }
+        _ => ()
+    }
+}
+
+fn main() {
+    let b = State::Failed(1);
+
+    print_on_failure(&b);
+
+}
diff --git a/gcc/testsuite/rust/compile/issue-2324-2.rs 
b/gcc/testsuite/rust/compile/issue-2324-2.rs
new file mode 100644
index 00000000000..5ef40147961
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2324-2.rs
@@ -0,0 +1,19 @@
+enum State {
+    Succeeded,
+    Failed { x: u32 },
+}
+
+fn print_on_failure(state: &State) {
+    match *state {
+        State::Succeeded => (),
+        State::Failed => (), // { dg-error "expected unit struct, unit variant 
or constant, found tuple variant" }
+        _ => ()
+    }
+}
+
+fn main() {
+    let b = State::Failed{x: 1};
+
+    print_on_failure(&b);
+
+}
-- 
2.45.2

Reply via email to