From: Arthur Cohen <arthur.co...@embecosm.com>

gcc/rust/ChangeLog:

        * resolve/rust-finalize-imports-2.0.cc (FinalizeImports::go): Turn
        static method into method.
        (FinalizeImports::visit): New.
        * resolve/rust-finalize-imports-2.0.h (class FinalizeImports): Make
        FinalizeImports a visitor.
        * resolve/rust-early-name-resolver-2.0.cc (Early::go): Use new 
FinalizeImports API.
        (Early::resolve_glob_import): Use new API.
        (Early::resolve_simple_import): Likewise.
        (Early::resolve_rebind_import): Likewise.
        (Early::build_import_mapping): Likewise.
        * resolve/rust-early-name-resolver-2.0.h: Likewise.
        * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): 
Likewise.
        * resolve/rust-toplevel-name-resolver-2.0.h: Likewise.
---
 .../resolve/rust-early-name-resolver-2.0.cc   | 84 ++++++++++++-------
 .../resolve/rust-early-name-resolver-2.0.h    | 14 ++--
 gcc/rust/resolve/rust-finalize-imports-2.0.cc | 23 ++++-
 gcc/rust/resolve/rust-finalize-imports-2.0.h  | 23 ++++-
 .../rust-toplevel-name-resolver-2.0.cc        | 10 ++-
 .../resolve/rust-toplevel-name-resolver-2.0.h |  5 +-
 6 files changed, 114 insertions(+), 45 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index ba73a54d412..ac8eb940c8d 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -59,7 +59,7 @@ Early::go (AST::Crate &crate)
     build_import_mapping (std::move (import));
 
   // Once this is done, we finalize their resolution
-  FinalizeImports::go (import_mappings, toplevel, ctx);
+  FinalizeImports (std::move (import_mappings), toplevel, ctx).go (crate);
 
   // We now proceed with resolving macros, which can be nested in almost any
   // items
@@ -70,7 +70,7 @@ Early::go (AST::Crate &crate)
 }
 
 bool
-Early::resolve_glob_import (TopLevel::ImportKind &&glob)
+Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
 {
   auto resolved = ctx.types.resolve_path (glob.to_resolve.get_segments ());
   if (!resolved.has_value ())
@@ -84,58 +84,86 @@ Early::resolve_glob_import (TopLevel::ImportKind &&glob)
   // here, we insert the module's NodeId into the import_mappings and will look
   // up the module proper in `FinalizeImports`
   // The namespace does not matter here since we are dealing with a glob
-  import_mappings.insert ({std::move (glob), ImportData::Glob (*resolved)});
+  // TODO: Ugly
+  import_mappings.insert (
+    {use_dec_id, {{std::move (glob), ImportData::Glob (*resolved)}}});
 
   return true;
 }
 
 bool
-Early::resolve_simple_import (TopLevel::ImportKind &&import)
+Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
 {
   return ctx.resolve_path (import.to_resolve)
     .map ([&] (std::pair<Rib::Definition, Namespace> def_ns) {
-      import_mappings.insert (
-       {std::move (import), ImportData::Simple (def_ns)});
+      // We insert an empty vector, unless an element was already present for
+      // `use_dec_id` - which is returned in the tuple's first member
+      auto tuple = import_mappings.insert ({use_dec_id, {}});
+      // We then get that tuple's first member, which will be an iterator to 
the
+      // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
+      // created empty vector (plus its key since this is a hashmap iterator).
+      // we then access the second member of the pair to get access to the
+      // vector directly.
+      auto &imports = tuple.first->second;
+
+      imports.emplace_back (
+       std::make_pair (std::move (import), ImportData::Simple (def_ns)));
     })
     .has_value ();
 }
 
 bool
-Early::resolve_rebind_import (TopLevel::ImportKind &&rebind_import)
+Early::resolve_rebind_import (NodeId use_dec_id,
+                             TopLevel::ImportKind &&rebind_import)
 {
   return ctx.resolve_path (rebind_import.to_resolve)
     .map ([&] (std::pair<Rib::Definition, Namespace> def_ns) {
-      import_mappings.insert (
-       {std::move (rebind_import), ImportData::Rebind (def_ns)});
+      // We insert an empty vector, unless an element was already present for
+      // `use_dec_id` - which is returned in the tuple's first member
+      auto tuple = import_mappings.insert ({use_dec_id, {}});
+      // We then get that tuple's first member, which will be an iterator to 
the
+      // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
+      // created empty vector (plus its key since this is a hashmap iterator).
+      // we then access the second member of the pair to get access to the
+      // vector directly.
+      auto &imports = tuple.first->second;
+
+      imports.emplace_back (std::make_pair (std::move (rebind_import),
+                                           ImportData::Rebind (def_ns)));
     })
     .has_value ();
 }
 
 void
-Early::build_import_mapping (TopLevel::ImportKind &&import)
+Early::build_import_mapping (
+  std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
 {
   auto found = false;
+  auto use_dec_id = use_import.first;
 
-  // We create a copy of the path in case of errors, since the `import` will
-  // be moved into the newly created import mappings
-  auto path = import.to_resolve;
-
-  switch (import.kind)
+  for (auto &&import : use_import.second)
     {
-    case TopLevel::ImportKind::Kind::Glob:
-      found = resolve_glob_import (std::move (import));
-      break;
-    case TopLevel::ImportKind::Kind::Simple:
-      found = resolve_simple_import (std::move (import));
-      break;
-    case TopLevel::ImportKind::Kind::Rebind:
-      found = resolve_rebind_import (std::move (import));
-      break;
-    }
+      // We create a copy of the path in case of errors, since the `import` 
will
+      // be moved into the newly created import mappings
+      auto path = import.to_resolve;
+
+      switch (import.kind)
+       {
+       case TopLevel::ImportKind::Kind::Glob:
+         found = resolve_glob_import (use_dec_id, std::move (import));
+         break;
+       case TopLevel::ImportKind::Kind::Simple:
+         found = resolve_simple_import (use_dec_id, std::move (import));
+         break;
+       case TopLevel::ImportKind::Kind::Rebind:
+         found = resolve_rebind_import (use_dec_id, std::move (import));
+         break;
+       }
 
-  if (!found)
-    rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433,
-                  "unresolved import %qs", path.as_string ().c_str ());
+      if (!found)
+       rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433,
+                      "unresolved import %qs", path.as_string ().c_str ());
+    }
 }
 
 void
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index 2ae31629533..a503686508c 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -127,20 +127,24 @@ private:
     std::vector<std::unordered_map<std::string, NodeId>> scopes;
   };
 
+  // TODO: This is becoming a very complex type - ugly
   // Mappings between an import and the definition it imports
-  std::map<TopLevel::ImportKind, ImportData> import_mappings;
+  std::unordered_map<NodeId,
+                    std::vector<std::pair<TopLevel::ImportKind, ImportData>>>
+    import_mappings;
 
   // FIXME: Documentation
   // Call this on all the paths of a UseDec - so each flattened path in a
   // UseTreeList for example
   // FIXME: Should that return `found`?
-  bool resolve_simple_import (TopLevel::ImportKind &&import);
-  bool resolve_glob_import (TopLevel::ImportKind &&glob_import);
-  bool resolve_rebind_import (TopLevel::ImportKind &&rebind_import);
+  bool resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind 
&&import);
+  bool resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&import);
+  bool resolve_rebind_import (NodeId use_dec_id, TopLevel::ImportKind 
&&import);
 
   // Handle an import, resolving it to its definition and adding it to the list
   // of import mappings
-  void build_import_mapping (TopLevel::ImportKind &&import);
+  void build_import_mapping (
+    std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import);
 
   TextualScope textual_scope;
   std::vector<Error> macro_resolve_errors;
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc 
b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index f5c8157f35b..ac288e3f6e7 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-finalize-imports-2.0.h"
+#include "rust-default-resolver.h"
 #include "rust-hir-map.h"
 #include "rust-name-resolution-context.h"
 #include "rust-rib.h"
@@ -191,11 +192,27 @@ finalize_rebind_import (
                                data.ns.value ());
 }
 
-void
-FinalizeImports::go (
-  std::map<TopLevel::ImportKind, Early::ImportData> import_mappings,
+FinalizeImports::FinalizeImports (
+  std::unordered_map<
+    NodeId, std::vector<std::pair<TopLevel::ImportKind, Early::ImportData>>>
+    &&data,
   TopLevel &toplevel, NameResolutionContext &ctx)
+  : DefaultResolver (ctx), data (std::move (data)), toplevel (toplevel),
+    ctx (ctx)
+{}
+
+void
+FinalizeImports::go (AST::Crate &crate)
 {
+  for (auto &item : crate.items)
+    item->accept_vis (*this);
+}
+
+void
+FinalizeImports::visit (AST::UseDeclaration &use)
+{
+  auto import_mappings = data[use.get_node_id ()];
+
   for (const auto &mapping : import_mappings)
     switch (mapping.first.kind)
       {
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h 
b/gcc/rust/resolve/rust-finalize-imports-2.0.h
index ed4dc7d1c91..a8b5ba09590 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.h
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h
@@ -16,6 +16,8 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-ast.h"
+#include "rust-expr.h"
 #include "rust-name-resolution-context.h"
 #include "rust-toplevel-name-resolver-2.0.h"
 #include "rust-early-name-resolver-2.0.h"
@@ -86,12 +88,25 @@ private:
 // each ImportKind - easy!
 //     - yay!
 
-class FinalizeImports
+class FinalizeImports : DefaultResolver
 {
 public:
-  static void
-  go (std::map<TopLevel::ImportKind, Early::ImportData> import_mappings,
-      TopLevel &toplevel, NameResolutionContext &ctx);
+  FinalizeImports (
+    std::unordered_map<
+      NodeId, std::vector<std::pair<TopLevel::ImportKind, Early::ImportData>>>
+      &&data,
+    TopLevel &toplevel, NameResolutionContext &ctx);
+
+  void go (AST::Crate &crate);
+
+private:
+  void visit (AST::UseDeclaration &) override;
+
+  std::unordered_map<
+    NodeId, std::vector<std::pair<TopLevel::ImportKind, Early::ImportData>>>
+    data;
+  TopLevel &toplevel;
+  NameResolutionContext &ctx;
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index f2f8f359c4c..47f3adee14c 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -466,18 +466,22 @@ TopLevel::visit (AST::UseDeclaration &use)
   const auto &tree = use.get_tree ();
   flatten (tree.get (), paths, glob_path, rebind_path, this->ctx);
 
+  auto imports = std::vector<ImportKind> ();
+
   for (auto &&path : paths)
-    imports_to_resolve.emplace_back (
+    imports.emplace_back (
       ImportKind::Simple (std::move (path), values_rib, types_rib, 
macros_rib));
 
   for (auto &&glob : glob_path)
-    imports_to_resolve.emplace_back (
+    imports.emplace_back (
       ImportKind::Glob (std::move (glob), values_rib, types_rib, macros_rib));
 
   for (auto &&rebind : rebind_path)
-    imports_to_resolve.emplace_back (
+    imports.emplace_back (
       ImportKind::Rebind (std::move (rebind.first), std::move (rebind.second),
                          values_rib, types_rib, macros_rib));
+
+  imports_to_resolve.insert ({use.get_node_id (), std::move (imports)});
 }
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 92a964d2c14..acb60d36e13 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -106,7 +106,8 @@ public:
     {}
   };
 
-  std::vector<ImportKind> &&get_imports_to_resolve ()
+  std::unordered_map<NodeId, std::vector<ImportKind>> &&
+  get_imports_to_resolve ()
   {
     return std::move (imports_to_resolve);
   }
@@ -137,7 +138,7 @@ private:
 
   // One of the outputs of the `TopLevel` visitor - the list of imports that
   // `Early` should take care of resolving
-  std::vector<ImportKind> imports_to_resolve;
+  std::unordered_map<NodeId, std::vector<ImportKind>> imports_to_resolve;
 
   void visit (AST::Module &module) override;
   void visit (AST::Trait &trait) override;
-- 
2.45.2

Reply via email to