https://gcc.gnu.org/g:f4b8b8332ff8d3b985170ffaecd9d76339a9d4cf

commit r16-2907-gf4b8b8332ff8d3b985170ffaecd9d76339a9d4cf
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Tue May 20 14:59:28 2025 +0200

    gccrs: ast: Add reconstruct() method for Type nodes
    
    gcc/rust/ChangeLog:
    
            * ast/rust-ast.h: Add reconstruct() and reconstruct_impl() for Type 
nodes.
            * ast/rust-type.h: Implement them.
            * ast/rust-macro.h: Likewise.
            * ast/rust-path.h: Likewise.

Diff:
---
 gcc/rust/ast/rust-ast.h   |  45 ++++++++++++++------
 gcc/rust/ast/rust-macro.h |  20 ++++++---
 gcc/rust/ast/rust-path.h  |  30 ++++++++++++++
 gcc/rust/ast/rust-type.h  | 103 ++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 167 insertions(+), 31 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 1cc10c90ee85..ecbc29181300 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -88,11 +88,11 @@ public:
  * different from the old NodeId. It then wraps the given pointer into a unique
  * pointer and returns it.
  */
-template <typename T, typename F>
+template <typename T>
 std::unique_ptr<T>
-reconstruct (const T *instance, F method)
+reconstruct_base (const T *instance)
 {
-  auto *reconstructed = (instance->*method) ();
+  auto *reconstructed = instance->reconstruct_impl ();
 
   rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
 
@@ -102,19 +102,14 @@ reconstruct (const T *instance, F method)
 /**
  * Reconstruct multiple items in a vector
  */
-template <typename T, typename F>
+template <typename T>
 std::vector<std::unique_ptr<T>>
-reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct,
-                F method)
+reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
 {
   std::vector<std::unique_ptr<T>> reconstructed;
 
   for (const auto &elt : to_reconstruct)
-    {
-      auto new_elt = (elt.get ()->*method) ();
-
-      reconstructed.emplace_back (std::move (new_elt));
-    }
+    reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
 
   return reconstructed;
 }
@@ -1516,6 +1511,10 @@ public:
     return std::unique_ptr<Type> (clone_type_impl ());
   }
 
+  // Similar to `clone_type`, but generates a new instance of the node with a
+  // different NodeId
+  std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); 
}
+
   // virtual destructor
   virtual ~Type () {}
 
@@ -1534,11 +1533,13 @@ public:
   virtual location_t get_locus () const = 0;
 
   NodeId get_node_id () const { return node_id; }
+  virtual Type *reconstruct_impl () const = 0;
 
 protected:
   Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
+  Type (NodeId node_id) : node_id (node_id) {}
 
-  // Clone function implementation as pure virtual method
+  // Clone and reconstruct function implementations as pure virtual methods
   virtual Type *clone_type_impl () const = 0;
 
   NodeId node_id;
@@ -1554,6 +1555,13 @@ public:
     return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
   }
 
+  std::unique_ptr<TypeNoBounds> reconstruct () const
+  {
+    return reconstruct_base (this);
+  }
+
+  virtual TypeNoBounds *reconstruct_impl () const override = 0;
+
 protected:
   // Clone function implementation as pure virtual method
   virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
@@ -1588,6 +1596,11 @@ public:
     return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
   }
 
+  std::unique_ptr<TypeParamBound> reconstruct () const
+  {
+    return reconstruct_base (this);
+  }
+
   virtual std::string as_string () const = 0;
 
   NodeId get_node_id () const { return node_id; }
@@ -1596,10 +1609,14 @@ public:
 
   virtual TypeParamBoundType get_bound_type () const = 0;
 
+  virtual TypeParamBound *reconstruct_impl () const = 0;
+
 protected:
   // Clone function implementation as pure virtual method
   virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
 
+  TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+  {}
   TypeParamBound (NodeId node_id) : node_id (node_id) {}
 
   NodeId node_id;
@@ -1661,6 +1678,10 @@ protected:
   {
     return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
   }
+  Lifetime *reconstruct_impl () const override
+  {
+    return new Lifetime (lifetime_type, lifetime_name, locus);
+  }
 };
 
 /* Base generic parameter in AST. Abstract - can be represented by a Lifetime
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc01e571b916..e8f377c001ec 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -756,22 +756,16 @@ private:
   std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
 
 protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
   MacroInvocation *clone_pattern_impl () const final override
   {
     return clone_macro_invocation_impl ();
   }
 
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
   MacroInvocation *clone_expr_without_block_impl () const final override
   {
     return clone_macro_invocation_impl ();
   }
 
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
   MacroInvocation *clone_type_no_bounds_impl () const final override
   {
     return clone_macro_invocation_impl ();
@@ -788,6 +782,20 @@ public:
     return new MacroInvocation (*this);
   }
 
+  std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const
+  {
+    return nullptr;
+    //  return reconstruct (this,
+    // &MacroInvocation::reconstruct_macro_invocation_impl);
+  }
+
+  MacroInvocation *reconstruct_impl () const override
+  {
+    return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs,
+                               locus, is_semi_coloned,
+                               reconstruct_vec (pending_eager_invocs));
+  }
+
   void add_semicolon () override { is_semi_coloned = true; }
 
   Pattern::Kind get_pattern_kind () override
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index de895a2f8384..a1b19d559c33 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -786,6 +786,11 @@ public:
   {
     return new TypePathSegment (*this);
   }
+  virtual TypePathSegment *reconstruct_impl () const
+  {
+    return new TypePathSegment (lang_item, ident_segment,
+                               has_separating_scope_resolution, locus);
+  }
 
 public:
   virtual ~TypePathSegment () {}
@@ -797,6 +802,11 @@ public:
   {
     return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
   }
+  // Unique pointer custom reconstruct function
+  std::unique_ptr<TypePathSegment> reconstruct () const
+  {
+    return reconstruct_base (this);
+  }
 
   TypePathSegment (PathIdentSegment ident_segment,
                   bool has_separating_scope_resolution, location_t locus)
@@ -821,6 +831,15 @@ public:
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
+  // General constructor
+  TypePathSegment (tl::optional<LangItem::Kind> lang_item,
+                  tl::optional<PathIdentSegment> ident_segment,
+                  bool has_separating_scope_resolution, location_t locus)
+    : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
+      has_separating_scope_resolution (has_separating_scope_resolution),
+      node_id (Analysis::Mappings::get ().get_next_node_id ())
+  {}
+
   TypePathSegment (TypePathSegment const &other)
     : lang_item (other.lang_item), ident_segment (other.ident_segment),
       locus (other.locus),
@@ -1152,6 +1171,11 @@ protected:
   {
     return new TypePath (*this);
   }
+  TypePath *reconstruct_impl () const override
+  {
+    return new TypePath (reconstruct_vec (segments), locus,
+                        has_opening_scope_resolution);
+  }
 
 public:
   /* Returns whether the TypePath has an opening scope resolution operator
@@ -1443,6 +1467,12 @@ protected:
   {
     return new QualifiedPathInType (*this);
   }
+  QualifiedPathInType *reconstruct_impl () const override
+  {
+    return new QualifiedPathInType (path_type,
+                                   associated_segment->reconstruct (),
+                                   reconstruct_vec (segments), locus);
+  }
 
 public:
   QualifiedPathInType (
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 6c0652a013f9..abbfd36a6f57 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -19,6 +19,7 @@
 #ifndef RUST_AST_TYPE_H
 #define RUST_AST_TYPE_H
 
+#include "optional.h"
 #include "rust-ast.h"
 #include "rust-path.h"
 
@@ -106,6 +107,11 @@ protected:
     return new TraitBound (node_id, type_path, locus, in_parens,
                           opening_question_mark, for_lifetimes);
   }
+  TraitBound *reconstruct_impl () const override
+  {
+    return new TraitBound (type_path, locus, in_parens, opening_question_mark,
+                          for_lifetimes);
+  }
 };
 
 // definition moved to rust-ast.h
@@ -127,6 +133,10 @@ protected:
   {
     return new ImplTraitType (*this);
   }
+  ImplTraitType *reconstruct_impl () const override
+  {
+    return new ImplTraitType (reconstruct_vec (type_param_bounds), locus);
+  }
 
 public:
   ImplTraitType (
@@ -136,7 +146,8 @@ public:
   {}
 
   // copy constructor with vector clone
-  ImplTraitType (ImplTraitType const &other) : locus (other.locus)
+  ImplTraitType (ImplTraitType const &other)
+    : Type (other.node_id), locus (other.locus)
   {
     type_param_bounds.reserve (other.type_param_bounds.size ());
     for (const auto &e : other.type_param_bounds)
@@ -191,6 +202,11 @@ protected:
   {
     return new TraitObjectType (*this);
   }
+  TraitObjectType *reconstruct_impl () const override
+  {
+    return new TraitObjectType (reconstruct_vec (type_param_bounds), locus,
+                               has_dyn);
+  }
 
 public:
   TraitObjectType (
@@ -202,7 +218,7 @@ public:
 
   // copy constructor with vector clone
   TraitObjectType (TraitObjectType const &other)
-    : has_dyn (other.has_dyn), locus (other.locus)
+    : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
   {
     type_param_bounds.reserve (other.type_param_bounds.size ());
     for (const auto &e : other.type_param_bounds)
@@ -258,6 +274,10 @@ protected:
   {
     return new ParenthesisedType (*this);
   }
+  ParenthesisedType *reconstruct_impl () const override
+  {
+    return new ParenthesisedType (type_in_parens->reconstruct (), locus);
+  }
 
 public:
   // Constructor uses Type pointer for polymorphism
@@ -338,6 +358,10 @@ public:
   {
     return new ImplTraitTypeOneBound (*this);
   }
+  TypeNoBounds *reconstruct_impl () const override
+  {
+    return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
+  }
 };
 
 /* A trait object with a single trait bound. The "trait bound" is really just
@@ -355,6 +379,10 @@ protected:
   {
     return new TraitObjectTypeOneBound (*this);
   }
+  TraitObjectTypeOneBound *reconstruct_impl () const override
+  {
+    return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn);
+  }
 
 public:
   TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
@@ -448,6 +476,10 @@ protected:
   {
     return new TupleType (*this);
   }
+  TupleType *reconstruct_impl () const override
+  {
+    return new TupleType (reconstruct_vec (elems), locus);
+  }
 };
 
 /* A type with no values, representing the result of computations that never
@@ -464,6 +496,10 @@ protected:
   {
     return new NeverType (*this);
   }
+  NeverType *reconstruct_impl () const override
+  {
+    return new NeverType (locus);
+  }
 
 public:
   NeverType (location_t locus) : locus (locus) {}
@@ -544,6 +580,10 @@ protected:
   {
     return new RawPointerType (*this);
   }
+  RawPointerType *reconstruct_impl () const override
+  {
+    return new RawPointerType (pointer_type, type->reconstruct (), locus);
+  }
 };
 
 // A type pointing to memory owned by another value
@@ -622,6 +662,16 @@ protected:
   {
     return new ReferenceType (*this);
   }
+  ReferenceType *reconstruct_impl () const override
+  {
+    return new ReferenceType (has_mut, type->reconstruct (), locus,
+                             // TODO: Improve this - it's ugly!
+                             has_lifetime () ? tl::make_optional<Lifetime> (
+                               lifetime->get_lifetime_type (),
+                               lifetime->get_lifetime_name (),
+                               lifetime->get_locus ())
+                                             : tl::nullopt);
+  }
 };
 
 // A fixed-size sequence of elements of a specified type
@@ -689,6 +739,13 @@ protected:
   {
     return new ArrayType (*this);
   }
+  ArrayType *reconstruct_impl () const override
+  {
+    return new ArrayType (
+      elem_type->reconstruct (),
+      size->clone_expr () /* FIXME: This should be `reconstruct_expr()` */,
+      locus);
+  }
 };
 
 /* A dynamically-sized type representing a "view" into a sequence of elements 
of
@@ -739,12 +796,16 @@ public:
   std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
 
 protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
+  /* Use covariance to implement clone function as returning this object
+   * rather than base */
   SliceType *clone_type_no_bounds_impl () const override
   {
     return new SliceType (*this);
   }
+  SliceType *reconstruct_impl () const override
+  {
+    return new SliceType (elem_type->reconstruct (), locus);
+  }
 };
 
 /* Type used in generic arguments to explicitly request type inference 
(wildcard
@@ -755,13 +816,21 @@ class InferredType : public TypeNoBounds
 
   // e.g. Vec<_> = whatever
 protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
+  /* Use covariance to implement clone function as returning this object
+   * rather than base */
   InferredType *clone_type_no_bounds_impl () const override
   {
+    // This goes through the copy constructor
     return new InferredType (*this);
   }
 
+  InferredType *reconstruct_impl () const override
+  {
+    // This goes through the base constructor which calls the base
+    // TypeNoBounds constructor, which allocates a new NodeId
+    return new InferredType (locus);
+  }
+
 public:
   InferredType (location_t locus) : locus (locus) {}
 
@@ -980,9 +1049,17 @@ public:
 
   FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; 
}
 
+  BareFunctionType *reconstruct_impl () const override
+  {
+    return new BareFunctionType (
+      for_lifetimes, function_qualifiers, params,
+      /* FIXME: Should params be reconstruct() as well? */
+      _is_variadic, variadic_attrs, return_type->reconstruct (), locus);
+  }
+
 protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
+  /* Use covariance to implement clone function as returning this object
+   * rather than base */
   BareFunctionType *clone_type_no_bounds_impl () const override
   {
     return new BareFunctionType (*this);
@@ -999,13 +1076,13 @@ class MacroInvocation;
  * function item type?
  * closure expression types?
  * primitive types (bool, int, float, char, str (the slice))
- * Although supposedly TypePaths are used to reference these types (including
- * primitives) */
+ * Although supposedly TypePaths are used to reference these types
+ * (including primitives) */
 
 /* FIXME: Incomplete spec references:
- *  anonymous type parameters, aka "impl Trait in argument position" - impl 
then
- * trait bounds abstract return types, aka "impl Trait in return position" -
- * impl then trait bounds */
+ *  anonymous type parameters, aka "impl Trait in argument position" - impl
+ * then trait bounds abstract return types, aka "impl Trait in return
+ * position" - impl then trait bounds */
 } // namespace AST
 } // namespace Rust

Reply via email to