From: Owen Avery <[email protected]>

This patch adds a wrapper class called Cloneable, which can be used to
automatically perform polymorphic copying. This should greatly reduce
the need for error-prone user defined copy constructors and assignment
operators.

As a demonstration/first step, this patch also uses Cloneable to
simplify the pattern nodes described in gcc/rust/ast/rust-pattern.h.

gcc/rust/ChangeLog:

        * ast/rust-ast.h: Include "rust-cloneable.h".
        (struct CloneableDelegate<std::unique_ptr<AST::Pattern>>): Add
        specialization.
        * ast/rust-pattern.cc (IdentifierPattern::as_string): Handle
        field type changes.
        (RangePattern::as_string): Likewise.
        (ReferencePattern::as_string): Likewise.
        (StructPatternFieldTuplePat::as_string): Likewise.
        (StructPatternFieldIdentPat::as_string): Likewise.
        (StructPatternElements::as_string): Likewise.
        (TupleStructItemsNoRest::as_string): Likewise.
        (TupleStructItemsHasRest::as_string): Likewise.
        (TupleStructPattern::as_string): Likewise.
        (TuplePatternItemsNoRest::as_string): Likewise.
        (TuplePatternItemsHasRest::as_string): Likewise.
        (TuplePattern::as_string): Likewise.
        (SlicePatternItemsNoRest::as_string): Likewise.
        (SlicePatternItemsHasRest::as_string): Likewise.
        (SlicePattern::as_string): Likewise.
        (AltPattern::as_string): Likewise.
        * ast/rust-pattern.h: Include "rust-cloneable.h".
        (class IdentifierPattern): Use Cloneable to simplify copying.
        (class RangePattern): Likewise.
        (class ReferencePattern): Likewise.
        (class StructPatternFieldTuplePat): Likewise.
        (class StructPatternFieldIdentPat): Likewise.
        (class StructPatternElements): Likewise.
        (class TupleStructItemsNoRest): Likewise.
        (class TupleStructItemsHasRest): Likewise.
        (class TupleStructPattern): Likewise.
        (class TuplePatternItemsNoRest): Likewise.
        (class TuplePatternItemsHasRest): Likewise.
        (class TuplePattern): Likewise.
        (class GroupedPattern): Likewise.
        (class SlicePatternItemsNoRest): Likewise.
        (class SlicePatternItemsHasRest): Likewise.
        (class SlicePattern): Likewise.
        (class AltPattern): Likewise.
        (struct
        CloneableDelegate<std::unique_ptr<AST::RangePatternBound>>): Add
        specialization.
        (struct
        CloneableDelegate<std::unique_ptr<AST::TupleStructItems>>):
        Likewise.
        (struct
        CloneableDelegate<std::unique_ptr<AST::TuplePatternItems>>):
        Likewise.
        (struct
        CloneableDelegate<std::unique_ptr<AST::SlicePatternItems>>):
        Likewise.
        (struct
        CloneableDelegate<std::unique_ptr<AST::StructPatternField>>):
        Likewise.
        * util/rust-cloneable.h: New file.

Signed-off-by: Owen Avery <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/308bc94241b95066f12818dc63b9f7b26c0b07f8

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4350

 gcc/rust/ast/rust-ast.h        |  14 +
 gcc/rust/ast/rust-pattern.cc   |  54 +--
 gcc/rust/ast/rust-pattern.h    | 659 +++++++--------------------------
 gcc/rust/util/rust-cloneable.h |  85 +++++
 4 files changed, 257 insertions(+), 555 deletions(-)
 create mode 100644 gcc/rust/util/rust-cloneable.h

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 2e7eaa81e..0f78f01e1 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -26,6 +26,7 @@
 #include "rust-location.h"
 #include "rust-diagnostics.h"
 #include "rust-keyword-values.h"
+#include "rust-cloneable.h"
 
 namespace Rust {
 // TODO: remove typedefs and make actual types for these
@@ -2139,6 +2140,19 @@ public:
 };
 
 } // namespace AST
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::Pattern>>
+{
+  static std::unique_ptr<AST::Pattern>
+  clone (const std::unique_ptr<AST::Pattern> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_pattern ();
+  }
+};
+
 } // namespace Rust
 
 namespace std {
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index 250e9853c..e8bf1c991 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -66,7 +66,7 @@ IdentifierPattern::as_string () const
   str += variable_ident.as_string ();
 
   if (has_subpattern ())
-    str += " @ " + subpattern->as_string ();
+    str += " @ " + subpattern.get ()->as_string ();
 
   return str;
 }
@@ -91,11 +91,11 @@ RangePattern::as_string () const
   switch (range_kind)
     {
     case RangeKind::EXCLUDED:
-      return lower->as_string () + ".." + upper->as_string ();
+      return lower.get ()->as_string () + ".." + upper.get ()->as_string ();
     case RangeKind::INCLUDED:
-      return lower->as_string () + "..=" + upper->as_string ();
+      return lower.get ()->as_string () + "..=" + upper.get ()->as_string ();
     case RangeKind::ELLIPSIS:
-      return lower->as_string () + "..." + upper->as_string ();
+      return lower.get ()->as_string () + "..." + upper.get ()->as_string ();
     default:
       rust_unreachable ();
     }
@@ -113,7 +113,7 @@ ReferencePattern::as_string () const
   if (is_mut)
     str += "mut ";
 
-  str += pattern->as_string ();
+  str += pattern.get ()->as_string ();
 
   return str;
 }
@@ -135,7 +135,7 @@ StructPatternFieldTuplePat::as_string () const
 
   str += "\n";
 
-  str += std::to_string (index) + " : " + tuple_pattern->as_string ();
+  str += std::to_string (index) + " : " + tuple_pattern.get ()->as_string ();
 
   return str;
 }
@@ -148,7 +148,7 @@ StructPatternFieldIdentPat::as_string () const
 
   str += "\n";
 
-  str += ident.as_string () + " : " + ident_pattern->as_string ();
+  str += ident.as_string () + " : " + ident_pattern.get ()->as_string ();
 
   return str;
 }
@@ -182,7 +182,7 @@ StructPatternElements::as_string () const
     }
   else
     {
-      for (const auto &field : fields)
+      for (const auto &field : fields.get ())
        str += "\n   " + field->as_string ();
     }
 
@@ -216,7 +216,7 @@ TupleStructItemsNoRest::as_string () const
 {
   std::string str;
 
-  for (const auto &pattern : patterns)
+  for (const auto &pattern : patterns.get ())
     str += "\n  " + pattern->as_string ();
 
   return str;
@@ -227,24 +227,24 @@ TupleStructItemsHasRest::as_string () const
 {
   std::string str ("\n  Lower patterns: ");
 
-  if (lower_patterns.empty ())
+  if (lower_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &lower : lower_patterns)
+      for (const auto &lower : lower_patterns.get ())
        str += "\n   " + lower->as_string ();
     }
 
   str += "\n  Upper patterns: ";
-  if (upper_patterns.empty ())
+  if (upper_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &upper : upper_patterns)
+      for (const auto &upper : upper_patterns.get ())
        str += "\n   " + upper->as_string ();
     }
 
@@ -258,7 +258,7 @@ TupleStructPattern::as_string () const
 
   str += path.as_string ();
 
-  str += "\n Tuple struct items: " + items->as_string ();
+  str += "\n Tuple struct items: " + items.get ()->as_string ();
 
   return str;
 }
@@ -268,7 +268,7 @@ TuplePatternItemsNoRest::as_string () const
 {
   std::string str;
 
-  for (const auto &pattern : patterns)
+  for (const auto &pattern : patterns.get ())
     str += "\n " + pattern->as_string ();
 
   return str;
@@ -280,24 +280,24 @@ TuplePatternItemsHasRest::as_string () const
   std::string str;
 
   str += "\n Lower patterns: ";
-  if (lower_patterns.empty ())
+  if (lower_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &lower : lower_patterns)
+      for (const auto &lower : lower_patterns.get ())
        str += "\n  " + lower->as_string ();
     }
 
   str += "\n Upper patterns: ";
-  if (upper_patterns.empty ())
+  if (upper_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &upper : upper_patterns)
+      for (const auto &upper : upper_patterns.get ())
        str += "\n  " + upper->as_string ();
     }
 
@@ -307,7 +307,7 @@ TuplePatternItemsHasRest::as_string () const
 std::string
 TuplePattern::as_string () const
 {
-  return "TuplePattern: " + items->as_string ();
+  return "TuplePattern: " + items.get ()->as_string ();
 }
 
 std::string
@@ -331,7 +331,7 @@ SlicePatternItemsNoRest::as_string () const
 {
   std::string str;
 
-  for (const auto &pattern : patterns)
+  for (const auto &pattern : patterns.get ())
     str += "\n " + pattern->as_string ();
 
   return str;
@@ -343,24 +343,24 @@ SlicePatternItemsHasRest::as_string () const
   std::string str;
 
   str += "\n Lower patterns: ";
-  if (lower_patterns.empty ())
+  if (lower_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &lower : lower_patterns)
+      for (const auto &lower : lower_patterns.get ())
        str += "\n  " + lower->as_string ();
     }
 
   str += "\n Upper patterns: ";
-  if (upper_patterns.empty ())
+  if (upper_patterns.get ().empty ())
     {
       str += "none";
     }
   else
     {
-      for (const auto &upper : upper_patterns)
+      for (const auto &upper : upper_patterns.get ())
        str += "\n  " + upper->as_string ();
     }
 
@@ -370,7 +370,7 @@ SlicePatternItemsHasRest::as_string () const
 std::string
 SlicePattern::as_string () const
 {
-  return "SlicePattern: " + items->as_string ();
+  return "SlicePattern: " + items.get ()->as_string ();
 }
 
 std::string
@@ -378,7 +378,7 @@ AltPattern::as_string () const
 {
   std::string str ("AltPattern: ");
 
-  for (const auto &pattern : alts)
+  for (const auto &pattern : alts.get ())
     str += "\n " + pattern->as_string ();
 
   return str;
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 5d623a4d9..78780f3cc 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -21,6 +21,7 @@
 
 #include "rust-ast.h"
 #include "rust-path.h"
+#include "rust-cloneable.h"
 
 namespace Rust {
 namespace AST {
@@ -93,7 +94,7 @@ class IdentifierPattern : public Pattern
   bool is_mut;
 
   // bool has_pattern;
-  std::unique_ptr<Pattern> subpattern;
+  Cloneable<std::unique_ptr<Pattern>> subpattern;
   location_t locus;
   NodeId node_id;
 
@@ -120,38 +121,6 @@ public:
       node_id (node_id)
   {}
 
-  // Copy constructor with clone
-  IdentifierPattern (IdentifierPattern const &other)
-    : variable_ident (other.variable_ident), is_ref (other.is_ref),
-      is_mut (other.is_mut), locus (other.locus), node_id (other.node_id)
-  {
-    // fix to get prevent null pointer dereference
-    if (other.subpattern != nullptr)
-      subpattern = other.subpattern->clone_pattern ();
-  }
-
-  // Overload assignment operator to use clone
-  IdentifierPattern &operator= (IdentifierPattern const &other)
-  {
-    variable_ident = other.variable_ident;
-    is_ref = other.is_ref;
-    is_mut = other.is_mut;
-    locus = other.locus;
-    node_id = other.node_id;
-
-    // fix to prevent null pointer dereference
-    if (other.subpattern != nullptr)
-      subpattern = other.subpattern->clone_pattern ();
-    else
-      subpattern = nullptr;
-
-    return *this;
-  }
-
-  // default move semantics
-  IdentifierPattern (IdentifierPattern &&other) = default;
-  IdentifierPattern &operator= (IdentifierPattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -159,13 +128,13 @@ public:
   Pattern &get_subpattern ()
   {
     rust_assert (has_subpattern ());
-    return *subpattern;
+    return *subpattern.get ();
   }
 
   std::unique_ptr<Pattern> &get_subpattern_ptr ()
   {
     rust_assert (has_subpattern ());
-    return subpattern;
+    return subpattern.get ();
   }
 
   Identifier get_ident () const { return variable_ident; }
@@ -403,8 +372,8 @@ RangeKind tokenid_to_rangekind (TokenId id);
 // AST node for matching within a certain range (range pattern)
 class RangePattern : public Pattern
 {
-  std::unique_ptr<RangePatternBound> lower;
-  std::unique_ptr<RangePatternBound> upper;
+  Cloneable<std::unique_ptr<RangePatternBound>> lower;
+  Cloneable<std::unique_ptr<RangePatternBound>> upper;
 
   RangeKind range_kind;
 
@@ -425,30 +394,6 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  // Copy constructor with clone
-  RangePattern (RangePattern const &other)
-    : lower (other.lower->clone_range_pattern_bound ()),
-      upper (other.upper->clone_range_pattern_bound ()),
-      range_kind (other.range_kind), locus (other.locus),
-      node_id (other.node_id)
-  {}
-
-  // Overloaded assignment operator to clone
-  RangePattern &operator= (RangePattern const &other)
-  {
-    lower = other.lower->clone_range_pattern_bound ();
-    upper = other.upper->clone_range_pattern_bound ();
-    range_kind = other.range_kind;
-    locus = other.locus;
-    node_id = other.node_id;
-
-    return *this;
-  }
-
-  // default move semantics
-  RangePattern (RangePattern &&other) = default;
-  RangePattern &operator= (RangePattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   bool get_has_ellipsis_syntax () const
@@ -468,13 +413,13 @@ public:
   RangePatternBound &get_lower_bound ()
   {
     rust_assert (lower != nullptr);
-    return *lower;
+    return *lower.get ();
   }
 
   RangePatternBound &get_upper_bound ()
   {
     rust_assert (upper != nullptr);
-    return *upper;
+    return *upper.get ();
   }
 
   NodeId get_node_id () const override { return node_id; }
@@ -495,7 +440,7 @@ class ReferencePattern : public Pattern
 {
   bool has_two_amps;
   bool is_mut;
-  std::unique_ptr<Pattern> pattern;
+  Cloneable<std::unique_ptr<Pattern>> pattern;
   location_t locus;
   NodeId node_id;
 
@@ -509,29 +454,6 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  // Copy constructor requires clone
-  ReferencePattern (ReferencePattern const &other)
-    : has_two_amps (other.has_two_amps), is_mut (other.is_mut),
-      pattern (other.pattern->clone_pattern ()), locus (other.locus),
-      node_id (other.node_id)
-  {}
-
-  // Overload assignment operator to clone
-  ReferencePattern &operator= (ReferencePattern const &other)
-  {
-    pattern = other.pattern->clone_pattern ();
-    is_mut = other.is_mut;
-    has_two_amps = other.has_two_amps;
-    locus = other.locus;
-    node_id = other.node_id;
-
-    return *this;
-  }
-
-  // default move semantics
-  ReferencePattern (ReferencePattern &&other) = default;
-  ReferencePattern &operator= (ReferencePattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -540,13 +462,13 @@ public:
   Pattern &get_referenced_pattern ()
   {
     rust_assert (pattern != nullptr);
-    return *pattern;
+    return *pattern.get ();
   }
 
   std::unique_ptr<Pattern> &get_referenced_pattern_ptr ()
   {
     rust_assert (pattern != nullptr);
-    return pattern;
+    return pattern.get ();
   }
 
   bool is_double_reference () const { return has_two_amps; }
@@ -647,7 +569,7 @@ protected:
 class StructPatternFieldTuplePat : public StructPatternField
 {
   TupleIndex index;
-  std::unique_ptr<Pattern> tuple_pattern;
+  Cloneable<std::unique_ptr<Pattern>> tuple_pattern;
 
 public:
   StructPatternFieldTuplePat (TupleIndex index,
@@ -659,39 +581,6 @@ public:
       index (index), tuple_pattern (std::move (tuple_pattern))
   {}
 
-  // Copy constructor requires clone
-  StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
-    : StructPatternField (other), index (other.index)
-  {
-    // guard to prevent null dereference (only required if error state)
-    node_id = other.get_node_id ();
-    if (other.tuple_pattern != nullptr)
-      tuple_pattern = other.tuple_pattern->clone_pattern ();
-  }
-
-  // Overload assignment operator to perform clone
-  StructPatternFieldTuplePat &
-  operator= (StructPatternFieldTuplePat const &other)
-  {
-    StructPatternField::operator= (other);
-    index = other.index;
-    // outer_attrs = other.outer_attrs;
-    node_id = other.get_node_id ();
-
-    // guard to prevent null dereference (only required if error state)
-    if (other.tuple_pattern != nullptr)
-      tuple_pattern = other.tuple_pattern->clone_pattern ();
-    else
-      tuple_pattern = nullptr;
-
-    return *this;
-  }
-
-  // default move semantics
-  StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
-  StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -709,13 +598,13 @@ public:
   Pattern &get_index_pattern ()
   {
     rust_assert (tuple_pattern != nullptr);
-    return *tuple_pattern;
+    return *tuple_pattern.get ();
   }
 
   std::unique_ptr<Pattern> &get_index_pattern_ptr ()
   {
     rust_assert (tuple_pattern != nullptr);
-    return tuple_pattern;
+    return tuple_pattern.get ();
   }
 
   ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; 
}
@@ -733,7 +622,7 @@ protected:
 class StructPatternFieldIdentPat : public StructPatternField
 {
   Identifier ident;
-  std::unique_ptr<Pattern> ident_pattern;
+  Cloneable<std::unique_ptr<Pattern>> ident_pattern;
 
 public:
   StructPatternFieldIdentPat (Identifier ident,
@@ -745,39 +634,6 @@ public:
       ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
   {}
 
-  // Copy constructor requires clone
-  StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
-    : StructPatternField (other), ident (other.ident)
-  {
-    // guard to prevent null dereference (only required if error state)
-    node_id = other.get_node_id ();
-    if (other.ident_pattern != nullptr)
-      ident_pattern = other.ident_pattern->clone_pattern ();
-  }
-
-  // Overload assignment operator to clone
-  StructPatternFieldIdentPat &
-  operator= (StructPatternFieldIdentPat const &other)
-  {
-    StructPatternField::operator= (other);
-    ident = other.ident;
-    // outer_attrs = other.outer_attrs;
-    node_id = other.get_node_id ();
-
-    // guard to prevent null dereference (only required if error state)
-    if (other.ident_pattern != nullptr)
-      ident_pattern = other.ident_pattern->clone_pattern ();
-    else
-      ident_pattern = nullptr;
-
-    return *this;
-  }
-
-  // default move semantics
-  StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
-  StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -795,13 +651,13 @@ public:
   Pattern &get_ident_pattern ()
   {
     rust_assert (ident_pattern != nullptr);
-    return *ident_pattern;
+    return *ident_pattern.get ();
   }
 
   std::unique_ptr<Pattern> &get_ident_pattern_ptr ()
   {
     rust_assert (ident_pattern != nullptr);
-    return ident_pattern;
+    return ident_pattern.get ();
   }
 
   ItemType get_item_type () const override final { return ItemType::IDENT_PAT; 
}
@@ -859,7 +715,7 @@ protected:
 class StructPatternElements
 {
   // bool has_struct_pattern_fields;
-  std::vector<std::unique_ptr<StructPatternField>> fields;
+  Cloneable<std::vector<std::unique_ptr<StructPatternField>>> fields;
 
   bool has_rest_pattern;
   std::vector<Attribute> struct_pattern_etc_attrs;
@@ -871,7 +727,7 @@ class StructPatternElements
 
 public:
   // Returns whether there are any struct pattern fields
-  bool has_struct_pattern_fields () const { return !fields.empty (); }
+  bool has_struct_pattern_fields () const { return !fields.get ().empty (); }
 
   /* Returns whether the struct pattern elements is entirely empty (no fields,
    * no etc). */
@@ -897,34 +753,6 @@ public:
       struct_pattern_etc_attrs ()
   {}
 
-  // Copy constructor with vector clone
-  StructPatternElements (StructPatternElements const &other)
-    : has_rest_pattern (other.has_rest_pattern),
-      struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
-  {
-    fields.reserve (other.fields.size ());
-    for (const auto &e : other.fields)
-      fields.push_back (e->clone_struct_pattern_field ());
-  }
-
-  // Overloaded assignment operator with vector clone
-  StructPatternElements &operator= (StructPatternElements const &other)
-  {
-    struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
-    has_rest_pattern = other.has_rest_pattern;
-
-    fields.clear ();
-    fields.reserve (other.fields.size ());
-    for (const auto &e : other.fields)
-      fields.push_back (e->clone_struct_pattern_field ());
-
-    return *this;
-  }
-
-  // move constructors
-  StructPatternElements (StructPatternElements &&other) = default;
-  StructPatternElements &operator= (StructPatternElements &&other) = default;
-
   // Creates an empty StructPatternElements
   static StructPatternElements create_empty ()
   {
@@ -937,12 +765,12 @@ public:
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields 
()
   {
-    return fields;
+    return fields.get ();
   }
   const std::vector<std::unique_ptr<StructPatternField>> &
   get_struct_pattern_fields () const
   {
-    return fields;
+    return fields.get ();
   }
 
   std::vector<Attribute> &get_etc_outer_attrs ()
@@ -1065,45 +893,25 @@ protected:
 // Class for non-ranged tuple struct pattern patterns
 class TupleStructItemsNoRest : public TupleStructItems
 {
-  std::vector<std::unique_ptr<Pattern>> patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
 
 public:
   TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
     : patterns (std::move (patterns))
   {}
 
-  // Copy constructor with vector clone
-  TupleStructItemsNoRest (TupleStructItemsNoRest const &other)
-  {
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator with vector clone
-  TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other)
-  {
-    patterns.clear ();
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default;
-  TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
+  {
+    return patterns.get ();
+  }
   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
   {
-    return patterns;
+    return patterns.get ();
   }
 
   ItemType get_item_type () const override final { return ItemType::NO_REST; }
@@ -1120,8 +928,8 @@ protected:
 // Class for ranged tuple struct pattern patterns
 class TupleStructItemsHasRest : public TupleStructItems
 {
-  std::vector<std::unique_ptr<Pattern>> lower_patterns;
-  std::vector<std::unique_ptr<Pattern>> upper_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns;
 
 public:
   TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> 
lower_patterns,
@@ -1130,39 +938,6 @@ public:
       upper_patterns (std::move (upper_patterns))
   {}
 
-  // Copy constructor with vector clone
-  TupleStructItemsHasRest (TupleStructItemsHasRest const &other)
-  {
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to clone
-  TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other)
-  {
-    lower_patterns.clear ();
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.clear ();
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default;
-  TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1170,21 +945,21 @@ public:
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
 
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
 
   ItemType get_item_type () const override final { return ItemType::HAS_REST; }
@@ -1202,7 +977,7 @@ protected:
 class TupleStructPattern : public Pattern
 {
   PathInExpression path;
-  std::unique_ptr<TupleStructItems> items;
+  Cloneable<std::unique_ptr<TupleStructItems>> items;
   NodeId node_id;
 
   /* TOOD: should this store location data? current accessor uses path location
@@ -1219,34 +994,6 @@ public:
     rust_assert (this->items != nullptr);
   }
 
-  // Copy constructor required to clone
-  TupleStructPattern (TupleStructPattern const &other) : path (other.path)
-  {
-    // guard to protect from null dereference
-    rust_assert (other.items != nullptr);
-
-    node_id = other.node_id;
-    items = other.items->clone_tuple_struct_items ();
-  }
-
-  // Operator overload assignment operator to clone
-  TupleStructPattern &operator= (TupleStructPattern const &other)
-  {
-    path = other.path;
-    node_id = other.node_id;
-
-    // guard to protect from null dereference
-    rust_assert (other.items != nullptr);
-
-    items = other.items->clone_tuple_struct_items ();
-
-    return *this;
-  }
-
-  // move constructors
-  TupleStructPattern (TupleStructPattern &&other) = default;
-  TupleStructPattern &operator= (TupleStructPattern &&other) = default;
-
   location_t get_locus () const override { return path.get_locus (); }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1254,7 +1001,7 @@ public:
   TupleStructItems &get_items ()
   {
     rust_assert (items != nullptr);
-    return *items;
+    return *items.get ();
   }
 
   PathInExpression &get_path () { return path; }
@@ -1294,46 +1041,25 @@ protected:
 // Class representing TuplePattern patterns which contains no rest pattern
 class TuplePatternItemsNoRest : public TuplePatternItems
 {
-  std::vector<std::unique_ptr<Pattern>> patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
 
 public:
   TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
     : patterns (std::move (patterns))
   {}
 
-  // Copy constructor with vector clone
-  TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other)
-  {
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to vector clone
-  TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other)
-  {
-    patterns.clear ();
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default;
-  TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
+  {
+    return patterns.get ();
+  }
   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
   {
-    return patterns;
+    return patterns.get ();
   }
 
   ItemType get_item_type () const override { return ItemType::NO_REST; }
@@ -1350,8 +1076,8 @@ protected:
 // Class representing TuplePattern patterns which contains a rest pattern
 class TuplePatternItemsHasRest : public TuplePatternItems
 {
-  std::vector<std::unique_ptr<Pattern>> lower_patterns;
-  std::vector<std::unique_ptr<Pattern>> upper_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns;
 
 public:
   TuplePatternItemsHasRest (
@@ -1361,39 +1087,6 @@ public:
       upper_patterns (std::move (upper_patterns))
   {}
 
-  // Copy constructor with vector clone
-  TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other)
-  {
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to clone
-  TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other)
-  {
-    lower_patterns.clear ();
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.clear ();
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default;
-  TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1401,21 +1094,21 @@ public:
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
 
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
 
   ItemType get_item_type () const override { return ItemType::HAS_REST; }
@@ -1432,7 +1125,7 @@ protected:
 // AST node representing a tuple pattern
 class TuplePattern : public Pattern
 {
-  std::unique_ptr<TuplePatternItems> items;
+  Cloneable<std::unique_ptr<TuplePatternItems>> items;
   location_t locus;
   NodeId node_id;
 
@@ -1446,29 +1139,6 @@ public:
     rust_assert (this->items != nullptr);
   }
 
-  // Copy constructor requires clone
-  TuplePattern (TuplePattern const &other) : locus (other.locus)
-  {
-    // guard to prevent null dereference
-    rust_assert (other.items != nullptr);
-
-    node_id = other.node_id;
-    items = other.items->clone_tuple_pattern_items ();
-  }
-
-  // Overload assignment operator to clone
-  TuplePattern &operator= (TuplePattern const &other)
-  {
-    locus = other.locus;
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    rust_assert (other.items != nullptr);
-
-    items = other.items->clone_tuple_pattern_items ();
-    return *this;
-  }
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1477,7 +1147,7 @@ public:
   TuplePatternItems &get_items ()
   {
     rust_assert (items != nullptr);
-    return *items;
+    return *items.get ();
   }
 
   NodeId get_node_id () const override { return node_id; }
@@ -1496,14 +1166,14 @@ protected:
 // AST node representing a pattern in parentheses, used to control precedence
 class GroupedPattern : public Pattern
 {
-  std::unique_ptr<Pattern> pattern_in_parens;
+  Cloneable<std::unique_ptr<Pattern>> pattern_in_parens;
   location_t locus;
   NodeId node_id;
 
 public:
   std::string as_string () const override
   {
-    return "(" + pattern_in_parens->as_string () + ")";
+    return "(" + pattern_in_parens.get ()->as_string () + ")";
   }
 
   GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus)
@@ -1511,26 +1181,6 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  // Copy constructor uses clone
-  GroupedPattern (GroupedPattern const &other)
-    : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
-      locus (other.locus), node_id (other.node_id)
-  {}
-
-  // Overload assignment operator to clone
-  GroupedPattern &operator= (GroupedPattern const &other)
-  {
-    pattern_in_parens = other.pattern_in_parens->clone_pattern ();
-    locus = other.locus;
-    node_id = other.node_id;
-
-    return *this;
-  }
-
-  // default move semantics
-  GroupedPattern (GroupedPattern &&other) = default;
-  GroupedPattern &operator= (GroupedPattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1539,13 +1189,13 @@ public:
   Pattern &get_pattern_in_parens ()
   {
     rust_assert (pattern_in_parens != nullptr);
-    return *pattern_in_parens;
+    return *pattern_in_parens.get ();
   }
 
   std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
   {
     rust_assert (pattern_in_parens != nullptr);
-    return pattern_in_parens;
+    return pattern_in_parens.get ();
   }
 
   NodeId get_node_id () const override { return node_id; }
@@ -1579,46 +1229,25 @@ protected:
 // Class representing the patterns in a SlicePattern without `..`
 class SlicePatternItemsNoRest : public SlicePatternItems
 {
-  std::vector<std::unique_ptr<Pattern>> patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
 
 public:
   SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
     : patterns (std::move (patterns))
   {}
 
-  // Copy constructor with vector clone
-  SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
-  {
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to vector clone
-  SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
-  {
-    patterns.clear ();
-    patterns.reserve (other.patterns.size ());
-    for (const auto &e : other.patterns)
-      patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
-  SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
+  {
+    return patterns.get ();
+  }
   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
   {
-    return patterns;
+    return patterns.get ();
   }
 
   ItemType get_item_type () const override { return ItemType::NO_REST; }
@@ -1635,8 +1264,8 @@ protected:
 // Class representing the patterns in a SlicePattern that contains a `..`
 class SlicePatternItemsHasRest : public SlicePatternItems
 {
-  std::vector<std::unique_ptr<Pattern>> lower_patterns;
-  std::vector<std::unique_ptr<Pattern>> upper_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns;
 
 public:
   SlicePatternItemsHasRest (
@@ -1646,39 +1275,6 @@ public:
       upper_patterns (std::move (upper_patterns))
   {}
 
-  // Copy constructor with vector clone
-  SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
-  {
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to clone
-  SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
-  {
-    lower_patterns.clear ();
-    lower_patterns.reserve (other.lower_patterns.size ());
-    for (const auto &e : other.lower_patterns)
-      lower_patterns.push_back (e->clone_pattern ());
-
-    upper_patterns.clear ();
-    upper_patterns.reserve (other.upper_patterns.size ());
-    for (const auto &e : other.upper_patterns)
-      upper_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
-  SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
-    = default;
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1686,21 +1282,21 @@ public:
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
   {
-    return lower_patterns;
+    return lower_patterns.get ();
   }
 
   // TODO: seems kinda dodgy. Think of better way.
   std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
   const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
   {
-    return upper_patterns;
+    return upper_patterns.get ();
   }
 
   ItemType get_item_type () const override { return ItemType::HAS_REST; }
@@ -1717,7 +1313,7 @@ protected:
 // AST node representing patterns that can match slices and arrays
 class SlicePattern : public Pattern
 {
-  std::unique_ptr<SlicePatternItems> items;
+  Cloneable<std::unique_ptr<SlicePatternItems>> items;
   location_t locus;
   NodeId node_id;
 
@@ -1729,33 +1325,6 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  // Copy constructor requires clone
-  SlicePattern (SlicePattern const &other) : locus (other.locus)
-  {
-    // guard to prevent null dereference
-    rust_assert (other.items != nullptr);
-
-    node_id = other.node_id;
-    items = other.items->clone_slice_pattern_items ();
-  }
-
-  // Overloaded assignment operator to clone
-  SlicePattern &operator= (SlicePattern const &other)
-  {
-    locus = other.locus;
-    node_id = other.node_id;
-
-    // guard to prevent null dereference
-    rust_assert (other.items != nullptr);
-
-    items = other.items->clone_slice_pattern_items ();
-    return *this;
-  }
-
-  // move constructors
-  SlicePattern (SlicePattern &&other) = default;
-  SlicePattern &operator= (SlicePattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1764,7 +1333,7 @@ public:
   SlicePatternItems &get_items ()
   {
     rust_assert (items != nullptr);
-    return *items;
+    return *items.get ();
   }
 
   NodeId get_node_id () const override { return node_id; }
@@ -1784,7 +1353,7 @@ protected:
 // joins together what are technically 'PatternNoTopAlt's
 class AltPattern : public Pattern
 {
-  std::vector<std::unique_ptr<Pattern>> alts;
+  Cloneable<std::vector<std::unique_ptr<Pattern>>> alts;
   location_t locus;
   NodeId node_id;
 
@@ -1796,42 +1365,15 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  // Copy constructor with vector clone
-  AltPattern (AltPattern const &other) : locus (other.locus)
-  {
-    node_id = other.node_id;
-    alts.reserve (other.alts.size ());
-    for (const auto &e : other.alts)
-      alts.push_back (e->clone_pattern ());
-  }
-
-  // Overloaded assignment operator to vector clone
-  AltPattern &operator= (AltPattern const &other)
-  {
-    locus = other.locus;
-    node_id = other.node_id;
-
-    alts.clear ();
-    alts.reserve (other.alts.size ());
-    for (const auto &e : other.alts)
-      alts.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  AltPattern (AltPattern &&other) = default;
-  AltPattern &operator= (AltPattern &&other) = default;
-
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
+  std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts.get (); }
   const std::vector<std::unique_ptr<Pattern>> &get_alts () const
   {
-    return alts;
+    return alts.get ();
   }
 
   NodeId get_node_id () const override { return node_id; }
@@ -1857,6 +1399,67 @@ class QualifiedPathInExpression;
 // Replaced with forward decl - defined in rust-macro.h
 class MacroInvocation;
 } // namespace AST
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::RangePatternBound>>
+{
+  static std::unique_ptr<AST::RangePatternBound>
+  clone (const std::unique_ptr<AST::RangePatternBound> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_range_pattern_bound ();
+  }
+};
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::TupleStructItems>>
+{
+  static std::unique_ptr<AST::TupleStructItems>
+  clone (const std::unique_ptr<AST::TupleStructItems> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_tuple_struct_items ();
+  }
+};
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::TuplePatternItems>>
+{
+  static std::unique_ptr<AST::TuplePatternItems>
+  clone (const std::unique_ptr<AST::TuplePatternItems> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_tuple_pattern_items ();
+  }
+};
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::SlicePatternItems>>
+{
+  static std::unique_ptr<AST::SlicePatternItems>
+  clone (const std::unique_ptr<AST::SlicePatternItems> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_slice_pattern_items ();
+  }
+};
+
+template <> struct CloneableDelegate<std::unique_ptr<AST::StructPatternField>>
+{
+  static std::unique_ptr<AST::StructPatternField>
+  clone (const std::unique_ptr<AST::StructPatternField> &other)
+  {
+    if (other == nullptr)
+      return nullptr;
+    else
+      return other->clone_struct_pattern_field ();
+  }
+};
+
 } // namespace Rust
 
 #endif
diff --git a/gcc/rust/util/rust-cloneable.h b/gcc/rust/util/rust-cloneable.h
new file mode 100644
index 000000000..ac6395082
--- /dev/null
+++ b/gcc/rust/util/rust-cloneable.h
@@ -0,0 +1,85 @@
+// Copyright (C) 2026 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_CLONEABLE
+#define RUST_CLONEABLE
+
+#include "rust-system.h"
+
+namespace Rust {
+
+// used to automatically copy cloneable types
+
+template <typename T> struct CloneableDelegate
+{
+};
+
+template <typename T> class Cloneable
+{
+public:
+  template <typename... Args>
+  Cloneable (Args &&...args) : inner (std::forward<Args> (args)...)
+  {}
+
+  Cloneable (const Cloneable &other)
+    : Cloneable (CloneableDelegate<T>::clone (other.inner))
+  {}
+
+  template <typename Arg> Cloneable &operator= (Arg &&arg)
+  {
+    inner = std::forward<Arg> (arg);
+    return *this;
+  }
+
+  Cloneable &operator= (const Cloneable &other)
+  {
+    inner = CloneableDelegate<T>::clone (other.inner);
+    return *this;
+  }
+
+  Cloneable (Cloneable &&) = default;
+  Cloneable &operator= (Cloneable &&) = default;
+
+  T &get () { return inner; }
+  const T &get () const { return inner; }
+
+  bool operator== (decltype (nullptr)) const { return inner == nullptr; }
+
+  bool operator!= (decltype (nullptr)) const { return inner != nullptr; }
+
+private:
+  T inner;
+};
+
+// general specializations
+
+template <typename T> struct CloneableDelegate<std::vector<T>>
+{
+  static std::vector<T> clone (const std::vector<T> &other)
+  {
+    std::vector<T> ret;
+    ret.reserve (other.size ());
+    for (auto &ent : other)
+      ret.push_back (CloneableDelegate<T>::clone (ent));
+    return ret;
+  }
+};
+
+} // namespace Rust
+
+#endif // RUST_CLONEABLE

base-commit: 6eec7e7b6c4ea905c74bffbf32185117d4d1a8c6
-- 
2.52.0

Reply via email to