aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2025-01-03 14:27:52 +0000
committerCohenArthur <arthur.cohen@embecosm.com>2025-01-20 12:09:26 +0000
commit40574e5eb02fb0d607267f39e338dcbd53f650da (patch)
tree39fe2c129499316e46279a6e1cb6469772be7e99 /gcc
parent78d4fe9d2505636c9db207cfa0fccd000dbceab7 (diff)
downloadgcc-40574e5eb02fb0d607267f39e338dcbd53f650da.zip
gcc-40574e5eb02fb0d607267f39e338dcbd53f650da.tar.gz
gcc-40574e5eb02fb0d607267f39e338dcbd53f650da.tar.bz2
derive(Clone): Implement clone for enum tuple variants
gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::variant_match_path): New function. (DeriveClone::clone_enum_identifier): Rename. (DeriveClone::clone_enum_tuple): New function. (DeriveClone::visit_enum): Visit tuple variants properly. * expand/rust-derive-clone.h: Declare new functions.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/expand/rust-derive-clone.cc58
-rw-r--r--gcc/rust/expand/rust-derive-clone.h12
2 files changed, 66 insertions, 4 deletions
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index cf944a1..36fa529 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -21,6 +21,8 @@
#include "rust-ast-dump.h"
#include "rust-item.h"
#include "rust-path.h"
+#include "rust-pattern.h"
+#include "rust-system.h"
namespace Rust {
namespace AST {
@@ -236,14 +238,20 @@ DeriveClone::visit_struct (StructStruct &item)
item.get_generic_params ());
}
+PathInExpression
+DeriveClone::variant_match_path (Enum &item, const Identifier &variant)
+{
+ return PathInExpression ({builder.path_segment (
+ item.get_identifier ().as_string ()),
+ builder.path_segment (variant.as_string ())},
+ {}, loc, false);
+}
+
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 variant_path = variant_match_path (item, variant->get_identifier ());
auto pattern = std::unique_ptr<Pattern> (new ReferencePattern (
std::unique_ptr<Pattern> (new PathInExpression (variant_path)), false,
@@ -253,6 +261,45 @@ DeriveClone::clone_enum_identifier (Enum &item,
return builder.match_case (std::move (pattern), std::move (expr));
}
+MatchCase
+DeriveClone::clone_enum_tuple (Enum &item, const EnumItemTuple &variant)
+{
+ auto variant_path = variant_match_path (item, variant.get_identifier ());
+
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ auto cloned_patterns = std::vector<std::unique_ptr<Expr>> ();
+
+ for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++)
+ {
+ // The pattern we're creating for each field is `self_<i>` where `i` is
+ // the index of the field. It doesn't actually matter what we use, as long
+ // as it's ordered, unique, and that we can reuse it in the match case's
+ // return expression to clone the field.
+ auto pattern_str = "__self_" + std::to_string (i);
+
+ patterns.emplace_back (builder.identifier_pattern (pattern_str));
+
+ // Now, for each tuple's element, we create a new expression calling
+ // `clone` on it for the match case's return expression
+ cloned_patterns.emplace_back (
+ clone_call (builder.ref (builder.identifier (pattern_str))));
+ }
+
+ auto pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (patterns)));
+
+ auto pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern (
+ variant_path, std::move (pattern_items))),
+ false, false, loc));
+
+ auto expr
+ = builder.call (std::unique_ptr<Expr> (new PathInExpression (variant_path)),
+ std::move (cloned_patterns));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
+}
+
void
DeriveClone::visit_enum (Enum &item)
{
@@ -274,6 +321,9 @@ DeriveClone::visit_enum (Enum &item)
cases.emplace_back (clone_enum_identifier (item, variant));
break;
case EnumItem::Kind::Tuple:
+ cases.emplace_back (
+ clone_enum_tuple (item, static_cast<EnumItemTuple &> (*variant)));
+ break;
case EnumItem::Kind::Struct:
rust_unreachable ();
break;
diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h
index e518117..844b53f 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -63,8 +63,20 @@ private:
clone_impl (std::unique_ptr<AssociatedItem> &&clone_fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);
+ /**
+ * Get the path to use for matching and creating a variant when matching on an
+ * enum. E.g. for the `Option` enum, with the `None` variant, this will create
+ * a path `Option::None`
+ */
+ PathInExpression variant_match_path (Enum &item, const Identifier &variant);
+
+ /**
+ * Implementation of clone for all possible variants of an enum
+ */
MatchCase clone_enum_identifier (Enum &item,
const std::unique_ptr<EnumItem> &variant);
+ MatchCase clone_enum_tuple (Enum &item, const EnumItemTuple &variant);
+ MatchCase clone_enum_struct (Enum &item, const EnumItemStruct &variant);
virtual void visit_struct (StructStruct &item);
virtual void visit_tuple (TupleStruct &item);