https://gcc.gnu.org/g:4cbbaa71c1a2d438c9ac534ef6b2bf6c1887bf8e

commit r15-8636-g4cbbaa71c1a2d438c9ac534ef6b2bf6c1887bf8e
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Thu Jan 2 10:59:33 2025 +0000

    gccrs: derive(Clone): Add deriving of simple enum variants
    
    gcc/rust/ChangeLog:
    
            * expand/rust-derive-clone.cc: Clone enum identifier variants 
properly
            * expand/rust-derive-clone.h: Declare new functions used.

Diff:
---
 gcc/rust/expand/rust-derive-clone.cc | 52 ++++++++++++++++++++++++++++++++++--
 gcc/rust/expand/rust-derive-clone.h  |  3 +++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/expand/rust-derive-clone.cc 
b/gcc/rust/expand/rust-derive-clone.cc
index b8c92dcc6feb..e4702d8a8183 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -20,6 +20,7 @@
 #include "rust-ast.h"
 #include "rust-ast-dump.h"
 #include "rust-item.h"
+#include "rust-path.h"
 
 namespace Rust {
 namespace AST {
@@ -235,11 +236,58 @@ DeriveClone::visit_struct (StructStruct &item)
                         item.get_generic_params ());
 }
 
+MatchCase
+DeriveClone::clone_enum_identifier (Enum &item,
+                                   const std::unique_ptr<EnumItem> &variant)
+{
+  auto variant_path = PathInExpression (
+    {builder.path_segment (item.get_identifier ().as_string ()),
+     builder.path_segment (variant->get_identifier ().as_string ())},
+    {}, loc, false);
+
+  auto pattern = std::unique_ptr<Pattern> (new ReferencePattern (
+    std::unique_ptr<Pattern> (new PathInExpression (variant_path)), false,
+    false, loc));
+  auto expr = std::unique_ptr<Expr> (new PathInExpression (variant_path));
+
+  return builder.match_case (std::move (pattern), std::move (expr));
+}
+
 void
 DeriveClone::visit_enum (Enum &item)
 {
-  rust_sorry_at (item.get_locus (), "cannot derive %qs for these items yet",
-                "Clone");
+  // Create an arm for each variant of the enum
+  // For enum item variants, just create the same variant
+  // For struct and tuple variants, destructure the pattern and call clone for
+  // each field
+
+  auto cases = std::vector<MatchCase> ();
+
+  for (const auto &variant : item.get_variants ())
+    {
+      switch (variant->get_enum_item_kind ())
+       {
+       // Identifiers and discriminated variants are the same for a clone - we
+       // just return the same variant
+       case EnumItem::Kind::Identifier:
+       case EnumItem::Kind::Discriminant:
+         cases.emplace_back (clone_enum_identifier (item, variant));
+         break;
+       case EnumItem::Kind::Tuple:
+       case EnumItem::Kind::Struct:
+         rust_unreachable ();
+         break;
+       }
+    }
+
+  // match self { ... }
+  auto match = builder.match (builder.identifier ("self"), std::move (cases));
+
+  expanded = clone_impl (clone_fn (std::move (match)),
+                        item.get_identifier ().as_string (),
+                        item.get_generic_params ());
+
+  AST::Dump::debug (*expanded);
 }
 
 void
diff --git a/gcc/rust/expand/rust-derive-clone.h 
b/gcc/rust/expand/rust-derive-clone.h
index 4a43b2ac1fc2..339cf6357ae9 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -63,6 +63,9 @@ private:
   clone_impl (std::unique_ptr<AssociatedItem> &&clone_fn, std::string name,
              const std::vector<std::unique_ptr<GenericParam>> &type_generics);
 
+  MatchCase clone_enum_identifier (Enum &item,
+                                  const std::unique_ptr<EnumItem> &variant);
+
   virtual void visit_struct (StructStruct &item);
   virtual void visit_tuple (TupleStruct &item);
   virtual void visit_enum (Enum &item);

Reply via email to