From: Pierre-Emmanuel Patry <[email protected]>

Add a new function to merge one CanonicalPathCtx within another one. This
move broke the references within the path segment. To avoid this breakage
this commit also changes the way parent handle are stored. Instead of
storing a reference to the parent, a record stores the parent's node id.

gcc/rust/ChangeLog:

        * resolve/rust-name-resolution-context.cc 
(CanonicalPathRecordNormal::as_path):
        Use context and retrieve parent from its node id.
        (CanonicalPathRecordImpl::as_path): Likewise.
        (CanonicalPathRecordTraitImpl::as_path): Likewise.
        (NameResolutionContext::merge): Merge both record map.
        * resolve/rust-name-resolution-context.h: Change parent handle
        representation from reference to node id.

Signed-off-by: Pierre-Emmanuel Patry <[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/3356a3b61f17c904d386da1701370438a83a25f0

The commit has NOT been mentioned in any issue.

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

 .../resolve/rust-name-resolution-context.cc   | 10 ++--
 .../resolve/rust-name-resolution-context.h    | 54 +++++++++++--------
 2 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc 
b/gcc/rust/resolve/rust-name-resolution-context.cc
index 07b8c163c..9444dc3a3 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -144,7 +144,8 @@ Resolver::CanonicalPath
 CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx,
                                    Namespace ns)
 {
-  auto parent_path = get_parent ().as_path (ctx, ns);
+  auto &parent = ctx.canonical_ctx.get_record (get_parent ());
+  auto parent_path = parent.as_path (ctx, ns);
   return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
 }
 
@@ -177,7 +178,8 @@ Resolver::CanonicalPath
 CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx,
                                  Namespace ns)
 {
-  auto parent_path = get_parent ().as_path (ctx, ns);
+  auto parent_path
+    = ctx.canonical_ctx.get_record (get_parent ()).as_path (ctx, ns);
   return parent_path.append (
     Resolver::CanonicalPath::inherent_impl_seg (impl_id,
                                                type_record.as_path (ctx, ns)));
@@ -188,7 +190,8 @@ CanonicalPathRecordTraitImpl::as_path (const 
NameResolutionContext &ctx,
                                       Namespace ns)
 {
   // Maybe this doesn't need the namespace and will always be in the types NS?
-  auto parent_path = get_parent ().as_path (ctx, ns);
+  auto parent_path
+    = ctx.canonical_ctx.get_record (get_parent ()).as_path (ctx, ns);
   return parent_path.append (
     Resolver::CanonicalPath::trait_impl_projection_seg (
       impl_id, trait_path_record.as_path (ctx, ns),
@@ -414,6 +417,7 @@ NameResolutionContext::merge (NameResolutionContext &other, 
NodeId at)
   merge_fstack (types, other.types);
   merge_fstack (macros, other.macros);
   merge_fstack (labels, other.labels);
+  canonical_ctx.merge (std::move (other.canonical_ctx));
 }
 
 #if 0
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index 3041dccb5..5aaea9631 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -235,15 +235,16 @@ public:
 class CanonicalPathRecordWithParent : public CanonicalPathRecord
 {
 public:
-  CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent 
(&parent)
+  CanonicalPathRecordWithParent (NodeId parent_node_id)
+    : parent_node_id (parent_node_id)
   {}
 
-  CanonicalPathRecord &get_parent () { return *parent; }
+  NodeId get_parent () { return parent_node_id; }
 
   bool is_root () const override final { return false; }
 
 private:
-  CanonicalPathRecord *parent;
+  NodeId parent_node_id;
 };
 
 class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
@@ -270,9 +271,9 @@ private:
 class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
 {
 public:
-  CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
+  CanonicalPathRecordNormal (NodeId parent_node_id, NodeId node_id,
                             std::string seg)
-    : CanonicalPathRecordWithParent (parent), node_id (node_id),
+    : CanonicalPathRecordWithParent (parent_node_id), node_id (node_id),
       seg (std::move (seg))
   {
     rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
@@ -306,9 +307,9 @@ private:
 class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
 {
 public:
-  CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
+  CanonicalPathRecordImpl (NodeId parent_node_id, NodeId impl_id,
                           NodeId type_id)
-    : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+    : CanonicalPathRecordWithParent (parent_node_id), impl_id (impl_id),
       type_record (type_id)
   {}
 
@@ -323,9 +324,9 @@ private:
 class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
 {
 public:
-  CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
+  CanonicalPathRecordTraitImpl (NodeId parent_node_id, NodeId impl_id,
                                NodeId type_id, NodeId trait_path_id)
-    : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+    : CanonicalPathRecordWithParent (parent_node_id), impl_id (impl_id),
       type_record (type_id), trait_path_record (trait_path_id)
   {}
 
@@ -342,7 +343,7 @@ class CanonicalPathCtx
 {
 public:
   CanonicalPathCtx (const NameResolutionContext &ctx)
-    : current_record (nullptr), nr_ctx (&ctx)
+    : current_record (UNKNOWN_NODEID), nr_ctx (&ctx)
   {}
 
   Resolver::CanonicalPath get_path (NodeId id, Namespace ns) const
@@ -373,13 +374,13 @@ public:
 
   void insert_record (NodeId id, std::string seg)
   {
-    rust_assert (current_record != nullptr);
+    rust_assert (current_record != UNKNOWN_NODEID);
 
     auto it = records.find (id);
     if (it == records.end ())
       {
-       auto record = new CanonicalPathRecordNormal (*current_record, id,
-                                                    std::move (seg));
+       auto record
+         = new CanonicalPathRecordNormal (current_record, id, std::move (seg));
        bool ok
          = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
              .second;
@@ -394,33 +395,33 @@ public:
 
   template <typename F> void scope (NodeId id, std::string seg, F &&f)
   {
-    rust_assert (current_record != nullptr);
+    rust_assert (current_record != UNKNOWN_NODEID);
 
     scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
-      return new CanonicalPathRecordNormal (*current_record, id,
+      return new CanonicalPathRecordNormal (current_record, id,
                                            std::move (seg));
     });
   }
 
   template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
   {
-    rust_assert (current_record != nullptr);
+    rust_assert (current_record != UNKNOWN_NODEID);
 
     NodeId id = impl.get_node_id ();
     scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
-      return new CanonicalPathRecordImpl (*current_record, id,
+      return new CanonicalPathRecordImpl (current_record, id,
                                          impl.get_type ().get_node_id ());
     });
   }
 
   template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
   {
-    rust_assert (current_record != nullptr);
+    rust_assert (current_record != UNKNOWN_NODEID);
 
     NodeId id = impl.get_node_id ();
     scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
       return new CanonicalPathRecordTraitImpl (
-       *current_record, id, impl.get_type ().get_node_id (),
+       current_record, id, impl.get_type ().get_node_id (),
        impl.get_trait_path ().get_node_id ());
     });
   }
@@ -433,6 +434,15 @@ public:
     });
   }
 
+  /** Merge another CanonicalPathCtx within this one. Intended to be used when
+   * merging crate name resolution context.
+   */
+  void merge (CanonicalPathCtx &&other)
+  {
+    records.insert (std::make_move_iterator (other.records.begin ()),
+                   std::make_move_iterator (other.records.end ()));
+  }
+
 private:
   template <typename FCreate, typename FCallback>
   void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
@@ -446,11 +456,11 @@ private:
       }
 
     rust_assert (it->second->is_root ()
-                || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
+                || static_cast<CanonicalPathRecordWithParent &> (*it->second)
                        .get_parent ()
                      == current_record);
 
-    CanonicalPathRecord *stash = it->second.get ();
+    NodeId stash = it->first;
     std::swap (stash, current_record);
 
     std::forward<FCallback> (f_callback) ();
@@ -459,7 +469,7 @@ private:
   }
 
   std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
-  CanonicalPathRecord *current_record;
+  NodeId current_record;
 
   const NameResolutionContext *nr_ctx;
 };
-- 
2.54.0

Reply via email to