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);