From 7d36d8e4e73b4949d2775c09336606490d35dfd8 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 2 Jan 2026 19:16:24 -0500 Subject: [PATCH] Add wrapper class for automatic node cloning 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>): 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>): Add specialization. (struct CloneableDelegate>): Likewise. (struct CloneableDelegate>): Likewise. (struct CloneableDelegate>): Likewise. (struct CloneableDelegate>): Likewise. * util/rust-cloneable.h: New file. Signed-off-by: Owen Avery --- 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 4d5eddc6a66c..6bf4eb0658aa 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 @@ -2115,6 +2116,19 @@ struct Crate : public GlobContainer }; } // namespace AST + +template <> struct CloneableDelegate> +{ + static std::unique_ptr + clone (const std::unique_ptr &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 250e9853c28e..e8bf1c9911e9 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 5d623a4d9612..78780f3cc22a 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 subpattern; + Cloneable> subpattern; location_t locus; NodeId node_id; @@ -120,38 +121,6 @@ class IdentifierPattern : public Pattern 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 @@ class IdentifierPattern : public Pattern Pattern &get_subpattern () { rust_assert (has_subpattern ()); - return *subpattern; + return *subpattern.get (); } std::unique_ptr &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 lower; - std::unique_ptr upper; + Cloneable> lower; + Cloneable> upper; RangeKind range_kind; @@ -425,30 +394,6 @@ class RangePattern : public Pattern 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 @@ class RangePattern : public Pattern 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; + Cloneable> pattern; location_t locus; NodeId node_id; @@ -509,29 +454,6 @@ class ReferencePattern : public Pattern 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 @@ class ReferencePattern : public Pattern Pattern &get_referenced_pattern () { rust_assert (pattern != nullptr); - return *pattern; + return *pattern.get (); } std::unique_ptr &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 @@ class StructPatternField class StructPatternFieldTuplePat : public StructPatternField { TupleIndex index; - std::unique_ptr tuple_pattern; + Cloneable> tuple_pattern; public: StructPatternFieldTuplePat (TupleIndex index, @@ -659,39 +581,6 @@ class StructPatternFieldTuplePat : public StructPatternField 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 @@ class StructPatternFieldTuplePat : public StructPatternField Pattern &get_index_pattern () { rust_assert (tuple_pattern != nullptr); - return *tuple_pattern; + return *tuple_pattern.get (); } std::unique_ptr &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 @@ class StructPatternFieldTuplePat : public StructPatternField class StructPatternFieldIdentPat : public StructPatternField { Identifier ident; - std::unique_ptr ident_pattern; + Cloneable> ident_pattern; public: StructPatternFieldIdentPat (Identifier ident, @@ -745,39 +634,6 @@ class StructPatternFieldIdentPat : public StructPatternField 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 @@ class StructPatternFieldIdentPat : public StructPatternField Pattern &get_ident_pattern () { rust_assert (ident_pattern != nullptr); - return *ident_pattern; + return *ident_pattern.get (); } std::unique_ptr &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 @@ class StructPatternFieldIdent : public StructPatternField class StructPatternElements { // bool has_struct_pattern_fields; - std::vector> fields; + Cloneable>> fields; bool has_rest_pattern; std::vector 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 @@ class StructPatternElements 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 @@ class StructPatternElements // TODO: seems kinda dodgy. Think of better way. std::vector> &get_struct_pattern_fields () { - return fields; + return fields.get (); } const std::vector> & get_struct_pattern_fields () const { - return fields; + return fields.get (); } std::vector &get_etc_outer_attrs () @@ -1065,45 +893,25 @@ class TupleStructItems : public PatternItems // Class for non-ranged tuple struct pattern patterns class TupleStructItemsNoRest : public TupleStructItems { - std::vector> patterns; + Cloneable>> patterns; public: TupleStructItemsNoRest (std::vector> 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> &get_patterns () { return patterns; } + std::vector> &get_patterns () + { + return patterns.get (); + } const std::vector> &get_patterns () const { - return patterns; + return patterns.get (); } ItemType get_item_type () const override final { return ItemType::NO_REST; } @@ -1120,8 +928,8 @@ class TupleStructItemsNoRest : public TupleStructItems // Class for ranged tuple struct pattern patterns class TupleStructItemsHasRest : public TupleStructItems { - std::vector> lower_patterns; - std::vector> upper_patterns; + Cloneable>> lower_patterns; + Cloneable>> upper_patterns; public: TupleStructItemsHasRest (std::vector> lower_patterns, @@ -1130,39 +938,6 @@ class TupleStructItemsHasRest : public TupleStructItems 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 @@ class TupleStructItemsHasRest : public TupleStructItems // TODO: seems kinda dodgy. Think of better way. std::vector> &get_lower_patterns () { - return lower_patterns; + return lower_patterns.get (); } const std::vector> &get_lower_patterns () const { - return lower_patterns; + return lower_patterns.get (); } // TODO: seems kinda dodgy. Think of better way. std::vector> &get_upper_patterns () { - return upper_patterns; + return upper_patterns.get (); } const std::vector> &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 @@ class TupleStructItemsHasRest : public TupleStructItems class TupleStructPattern : public Pattern { PathInExpression path; - std::unique_ptr items; + Cloneable> items; NodeId node_id; /* TOOD: should this store location data? current accessor uses path location @@ -1219,34 +994,6 @@ class TupleStructPattern : public Pattern 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 @@ class TupleStructPattern : public Pattern TupleStructItems &get_items () { rust_assert (items != nullptr); - return *items; + return *items.get (); } PathInExpression &get_path () { return path; } @@ -1294,46 +1041,25 @@ class TuplePatternItems : public PatternItems // Class representing TuplePattern patterns which contains no rest pattern class TuplePatternItemsNoRest : public TuplePatternItems { - std::vector> patterns; + Cloneable>> patterns; public: TuplePatternItemsNoRest (std::vector> 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> &get_patterns () { return patterns; } + std::vector> &get_patterns () + { + return patterns.get (); + } const std::vector> &get_patterns () const { - return patterns; + return patterns.get (); } ItemType get_item_type () const override { return ItemType::NO_REST; } @@ -1350,8 +1076,8 @@ class TuplePatternItemsNoRest : public TuplePatternItems // Class representing TuplePattern patterns which contains a rest pattern class TuplePatternItemsHasRest : public TuplePatternItems { - std::vector> lower_patterns; - std::vector> upper_patterns; + Cloneable>> lower_patterns; + Cloneable>> upper_patterns; public: TuplePatternItemsHasRest ( @@ -1361,39 +1087,6 @@ class TuplePatternItemsHasRest : public TuplePatternItems 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 @@ class TuplePatternItemsHasRest : public TuplePatternItems // TODO: seems kinda dodgy. Think of better way. std::vector> &get_lower_patterns () { - return lower_patterns; + return lower_patterns.get (); } const std::vector> &get_lower_patterns () const { - return lower_patterns; + return lower_patterns.get (); } // TODO: seems kinda dodgy. Think of better way. std::vector> &get_upper_patterns () { - return upper_patterns; + return upper_patterns.get (); } const std::vector> &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 @@ class TuplePatternItemsHasRest : public TuplePatternItems // AST node representing a tuple pattern class TuplePattern : public Pattern { - std::unique_ptr items; + Cloneable> items; location_t locus; NodeId node_id; @@ -1446,29 +1139,6 @@ class TuplePattern : public Pattern 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 @@ class TuplePattern : public Pattern 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 @@ class TuplePattern : public Pattern // AST node representing a pattern in parentheses, used to control precedence class GroupedPattern : public Pattern { - std::unique_ptr pattern_in_parens; + Cloneable> 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_in_parens, location_t locus) @@ -1511,26 +1181,6 @@ class GroupedPattern : public Pattern 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 @@ class GroupedPattern : public Pattern Pattern &get_pattern_in_parens () { rust_assert (pattern_in_parens != nullptr); - return *pattern_in_parens; + return *pattern_in_parens.get (); } std::unique_ptr &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 @@ class SlicePatternItems : public PatternItems // Class representing the patterns in a SlicePattern without `..` class SlicePatternItemsNoRest : public SlicePatternItems { - std::vector> patterns; + Cloneable>> patterns; public: SlicePatternItemsNoRest (std::vector> 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> &get_patterns () { return patterns; } + std::vector> &get_patterns () + { + return patterns.get (); + } const std::vector> &get_patterns () const { - return patterns; + return patterns.get (); } ItemType get_item_type () const override { return ItemType::NO_REST; } @@ -1635,8 +1264,8 @@ class SlicePatternItemsNoRest : public SlicePatternItems // Class representing the patterns in a SlicePattern that contains a `..` class SlicePatternItemsHasRest : public SlicePatternItems { - std::vector> lower_patterns; - std::vector> upper_patterns; + Cloneable>> lower_patterns; + Cloneable>> upper_patterns; public: SlicePatternItemsHasRest ( @@ -1646,39 +1275,6 @@ class SlicePatternItemsHasRest : public SlicePatternItems 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 @@ class SlicePatternItemsHasRest : public SlicePatternItems // TODO: seems kinda dodgy. Think of better way. std::vector> &get_lower_patterns () { - return lower_patterns; + return lower_patterns.get (); } const std::vector> &get_lower_patterns () const { - return lower_patterns; + return lower_patterns.get (); } // TODO: seems kinda dodgy. Think of better way. std::vector> &get_upper_patterns () { - return upper_patterns; + return upper_patterns.get (); } const std::vector> &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 @@ class SlicePatternItemsHasRest : public SlicePatternItems // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::unique_ptr items; + Cloneable> items; location_t locus; NodeId node_id; @@ -1729,33 +1325,6 @@ class SlicePattern : public Pattern 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 @@ class SlicePattern : public Pattern 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 @@ class SlicePattern : public Pattern // joins together what are technically 'PatternNoTopAlt's class AltPattern : public Pattern { - std::vector> alts; + Cloneable>> alts; location_t locus; NodeId node_id; @@ -1796,42 +1365,15 @@ class AltPattern : public Pattern 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> &get_alts () { return alts; } + std::vector> &get_alts () { return alts.get (); } const std::vector> &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> +{ + static std::unique_ptr + clone (const std::unique_ptr &other) + { + if (other == nullptr) + return nullptr; + else + return other->clone_range_pattern_bound (); + } +}; + +template <> struct CloneableDelegate> +{ + static std::unique_ptr + clone (const std::unique_ptr &other) + { + if (other == nullptr) + return nullptr; + else + return other->clone_tuple_struct_items (); + } +}; + +template <> struct CloneableDelegate> +{ + static std::unique_ptr + clone (const std::unique_ptr &other) + { + if (other == nullptr) + return nullptr; + else + return other->clone_tuple_pattern_items (); + } +}; + +template <> struct CloneableDelegate> +{ + static std::unique_ptr + clone (const std::unique_ptr &other) + { + if (other == nullptr) + return nullptr; + else + return other->clone_slice_pattern_items (); + } +}; + +template <> struct CloneableDelegate> +{ + static std::unique_ptr + clone (const std::unique_ptr &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 000000000000..ac6395082688 --- /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 +// . + +#ifndef RUST_CLONEABLE +#define RUST_CLONEABLE + +#include "rust-system.h" + +namespace Rust { + +// used to automatically copy cloneable types + +template struct CloneableDelegate +{ +}; + +template class Cloneable +{ +public: + template + Cloneable (Args &&...args) : inner (std::forward (args)...) + {} + + Cloneable (const Cloneable &other) + : Cloneable (CloneableDelegate::clone (other.inner)) + {} + + template Cloneable &operator= (Arg &&arg) + { + inner = std::forward (arg); + return *this; + } + + Cloneable &operator= (const Cloneable &other) + { + inner = CloneableDelegate::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 struct CloneableDelegate> +{ + static std::vector clone (const std::vector &other) + { + std::vector ret; + ret.reserve (other.size ()); + for (auto &ent : other) + ret.push_back (CloneableDelegate::clone (ent)); + return ret; + } +}; + +} // namespace Rust + +#endif // RUST_CLONEABLE