https://gcc.gnu.org/g:23f933b90bb7d5558eef4d956d2a76160beb0e12

commit 23f933b90bb7d5558eef4d956d2a76160beb0e12
Author: Owen Avery <powerboat9.ga...@gmail.com>
Date:   Wed Apr 30 21:54:53 2025 -0400

    Improve struct pattern compilation
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-pattern.cc
            (CompilePatternCheckExpr::visit): Fix GENERIC generation in
            light of enum layout changes since this code was written.
            (CompilePatternBindings::handle_struct_pattern_ident_pat):
            Delegate handling of child patterns to another
            CompilePatternBindings::Compile call.
            (CompilePatternBindings::make_struct_access): Make field name
            parameter const qualified.
            * backend/rust-compile-pattern.h
            (CompilePatternBindings::make_struct_access): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/torture/struct-pattern-match.rs: New test.
    
    Signed-off-by: Owen Avery <powerboat9.ga...@gmail.com>

Diff:
---
 gcc/rust/backend/rust-compile-pattern.cc           | 44 ++++++++--------------
 gcc/rust/backend/rust-compile-pattern.h            |  2 +-
 .../rust/execute/torture/struct-pattern-match.rs   | 13 +++++++
 3 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index 94844fed2e84..121749ad4662 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -209,6 +209,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
 
   rust_assert (adt->number_of_variants () > 0);
   TyTy::VariantDef *variant = nullptr;
+  tree variant_accesser_expr = nullptr;
   if (adt->is_enum ())
     {
       // lookup the variant
@@ -223,9 +224,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
 
       // find expected discriminant
       // // need to access qualifier the field, if we use QUAL_UNION_TYPE this
-      // // would be DECL_QUALIFIER i think. For now this will just access the
-      // // first record field and its respective qualifier because it will
-      // // always be set because this is all a big special union
+      // // would be DECL_QUALIFIER i think.
       HIR::Expr &discrim_expr = variant->get_discriminant ();
       tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
 
@@ -234,6 +233,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern 
&pattern)
        = Backend::struct_field_expression (match_scrutinee_expr, 0,
                                            pattern.get_path ().get_locus ());
 
+      // access variant data
+      tree scrutinee_union_expr
+       = Backend::struct_field_expression (match_scrutinee_expr, 1,
+                                           pattern.get_path ().get_locus ());
+      variant_accesser_expr
+       = Backend::struct_field_expression (scrutinee_union_expr, variant_index,
+                                           pattern.get_path ().get_locus ());
+
       check_expr
        = Backend::comparison_expression (ComparisonOperator::EQUAL,
                                          scrutinee_expr_qualifier_expr,
@@ -245,6 +252,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
   else
     {
       variant = adt->get_variants ().at (0);
+      variant_accesser_expr = match_scrutinee_expr;
       check_expr = boolean_true_node;
     }
 
@@ -268,11 +276,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern 
&pattern)
                                        nullptr, &offs);
            rust_assert (ok);
 
-           // we may be offsetting by + 1 here since the first field in the
-           // record is always the discriminator
-           offs += adt->is_enum ();
            tree field_expr
-             = Backend::struct_field_expression (match_scrutinee_expr, offs,
+             = Backend::struct_field_expression (variant_accesser_expr, offs,
                                                  ident.get_locus ());
 
            tree check_expr_sub
@@ -512,7 +517,7 @@ CompilePatternBindings::visit (HIR::TupleStructPattern 
&pattern)
 tree
 CompilePatternBindings::make_struct_access (TyTy::ADTType *adt,
                                            TyTy::VariantDef *variant,
-                                           Identifier &ident,
+                                           const Identifier &ident,
                                            int variant_index)
 {
   size_t offs = 0;
@@ -562,26 +567,9 @@ CompilePatternBindings::handle_struct_pattern_ident_pat (
 {
   auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat);
 
-  switch (pattern.get_pattern ().get_pattern_type ())
-    {
-      case HIR::Pattern::IDENTIFIER: {
-       auto &id
-         = static_cast<HIR::IdentifierPattern &> (pattern.get_pattern ());
-
-       CompilePatternBindings::Compile (id, match_scrutinee_expr, ctx);
-      }
-      break;
-    default:
-      rust_sorry_at (pat.get_locus (),
-                    "cannot handle non-identifier struct patterns");
-      return;
-    }
-
-  auto ident = pattern.get_identifier ();
-  tree binding = make_struct_access (adt, variant, ident, variant_index);
-
-  ctx->insert_pattern_binding (
-    pattern.get_pattern ().get_mappings ().get_hirid (), binding);
+  tree binding = make_struct_access (adt, variant, pattern.get_identifier (),
+                                    variant_index);
+  CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx);
 }
 
 void
diff --git a/gcc/rust/backend/rust-compile-pattern.h 
b/gcc/rust/backend/rust-compile-pattern.h
index 8ebc2755c490..32b6db225744 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -81,7 +81,7 @@ public:
   }
 
   tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant,
-                          Identifier &ident, int variant_index);
+                          const Identifier &ident, int variant_index);
 
   void handle_struct_pattern_ident (HIR::StructPatternField &pat,
                                    TyTy::ADTType *adt,
diff --git a/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs 
b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs
new file mode 100644
index 000000000000..6aec51f93fe0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs
@@ -0,0 +1,13 @@
+enum Foo {
+    A { x: i32 },
+    B { y: i32 }
+}
+
+fn main() -> i32 {
+    let x = Foo::A { x: 12 };
+    match x {
+        Foo::A { x: 10 } => 1,
+        Foo::B { y: 11 } => 2,
+        Foo::A { x: abc } => { abc - 12 }
+    }
+}

Reply via email to