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

gcc/rust/ChangeLog:

        * resolve/rust-early-name-resolver-2.0.cc 
(Early::resolve_simple_import):
        Insert import in all namespaces where they were resolved.
        (Early::resolve_rebind_import): Likewise.
        * resolve/rust-early-name-resolver-2.0.h: Improve APIs, make them
        accept multiple resolutions.
        * resolve/rust-finalize-imports-2.0.cc: Handle multiple resolutions.
        * resolve/rust-name-resolution-context.h (resolve_path): Remove 
function.
---
 .../resolve/rust-early-name-resolver-2.0.cc   | 74 +++++++++++--------
 .../resolve/rust-early-name-resolver-2.0.h    | 66 ++++++++++++++---
 gcc/rust/resolve/rust-finalize-imports-2.0.cc | 17 ++---
 .../resolve/rust-name-resolution-context.h    | 26 -------
 4 files changed, 106 insertions(+), 77 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 47582a6f339..5201c32e24d 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -94,44 +94,54 @@ Early::resolve_glob_import (NodeId use_dec_id, 
TopLevel::ImportKind &&glob)
 bool
 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) {
-      // 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 ();
+  auto definitions = resolve_path_in_all_ns (import.to_resolve);
+
+  // if we've found at least one definition, then we're good
+  if (definitions.empty ())
+    return false;
+
+  // 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 (std::move (definitions))));
+
+  return true;
 }
 
 bool
 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) {
-      // 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 ();
+  auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
+
+  // if we've found at least one definition, then we're good
+  if (definitions.empty ())
+    return false;
+
+  // 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 (std::move (definitions))));
+
+  return true;
 }
 
 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 a503686508c..7d0864ee100 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -65,17 +65,16 @@ public:
       Rebind
     } kind;
 
-    Rib::Definition definition;
-    tl::optional<Namespace> ns;
-
-    static ImportData Simple (std::pair<Rib::Definition, Namespace> def_ns)
+    static ImportData
+    Simple (std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
     {
-      return ImportData (Kind::Simple, def_ns.first, def_ns.second);
+      return ImportData (Kind::Simple, std::move (definitions));
     }
 
-    static ImportData Rebind (std::pair<Rib::Definition, Namespace> def_ns)
+    static ImportData
+    Rebind (std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
     {
-      return ImportData (Kind::Rebind, def_ns.first, def_ns.second);
+      return ImportData (Kind::Rebind, std::move (definitions));
     }
 
     static ImportData Glob (Rib::Definition module)
@@ -83,11 +82,36 @@ public:
       return ImportData (Kind::Glob, module);
     }
 
+    Rib::Definition module () const
+    {
+      rust_assert (kind == Kind::Glob);
+      return glob_module;
+    }
+
+    std::vector<std::pair<Rib::Definition, Namespace>> definitions () const
+    {
+      rust_assert (kind != Kind::Glob);
+      return std::move (resolved_definitions);
+    }
+
   private:
-    ImportData (Kind kind, Rib::Definition definition,
-               tl::optional<Namespace> ns = tl::nullopt)
-      : kind (kind), definition (definition), ns (ns)
+    ImportData (
+      Kind kind,
+      std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
+      : kind (kind), resolved_definitions (std::move (definitions))
     {}
+
+    ImportData (Kind kind, Rib::Definition module)
+      : kind (kind), glob_module (module)
+    {}
+
+    // TODO: Should this be a union?
+
+    // For Simple and Rebind
+    std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
+
+    // For Glob
+    Rib::Definition glob_module;
   };
 
 private:
@@ -141,6 +165,28 @@ private:
   bool resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&import);
   bool resolve_rebind_import (NodeId use_dec_id, TopLevel::ImportKind 
&&import);
 
+  template <typename P>
+  std::vector<std::pair<Rib::Definition, Namespace>>
+  resolve_path_in_all_ns (const P &path)
+  {
+    const auto &segments = path.get_segments ();
+    std::vector<std::pair<Rib::Definition, Namespace>> resolved;
+
+    // Pair a definition with the namespace it was found in
+    auto pair_with_ns = [&] (Namespace ns) {
+      return [&, ns] (Rib::Definition def) {
+       auto pair = std::make_pair (def, ns);
+       return resolved.emplace_back (std::move (pair));
+      };
+    };
+
+    ctx.values.resolve_path (segments).map (pair_with_ns (Namespace::Values));
+    ctx.types.resolve_path (segments).map (pair_with_ns (Namespace::Types));
+    ctx.macros.resolve_path (segments).map (pair_with_ns (Namespace::Macros));
+
+    return resolved;
+  }
+
   // Handle an import, resolving it to its definition and adding it to the list
   // of import mappings
   void build_import_mapping (
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc 
b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index ac288e3f6e7..52bbcaa3538 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -137,10 +137,10 @@ finalize_simple_import (
   auto identifier
     = mapping.first.to_resolve.get_final_segment ().get_segment_name ();
 
-  // FIXME: Fix the namespace in which we insert the new definition
-  toplevel.insert_or_error_out (identifier, locus,
-                               data.definition.get_node_id (),
-                               data.ns.value ());
+  for (auto &&definition : data.definitions ())
+    toplevel
+      .insert_or_error_out (
+       identifier, locus, definition.first.get_node_id (), definition.second 
/* TODO: This isn't clear - it would be better if it was called .ns or 
something */);
 }
 
 void
@@ -149,7 +149,7 @@ finalize_glob_import (
   const std::pair<TopLevel::ImportKind, Early::ImportData> &mapping)
 {
   auto module = Analysis::Mappings::get ().lookup_ast_module (
-    mapping.second.definition.get_node_id ());
+    mapping.second.module ().get_node_id ());
   rust_assert (module);
 
   GlobbingVisitor glob_visitor (ctx);
@@ -186,10 +186,9 @@ finalize_rebind_import (
       break;
     }
 
-  // FIXME: Fix the namespace in which we insert the new definition
-  toplevel.insert_or_error_out (declared_name, locus,
-                               data.definition.get_node_id (),
-                               data.ns.value ());
+  for (auto &&definition : data.definitions ())
+    toplevel.insert_or_error_out (
+      declared_name, locus, definition.first.get_node_id (), definition.second 
/* TODO: This isn't clear - it would be better if it was called .ns or 
something */);
 }
 
 FinalizeImports::FinalizeImports (
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index 2fc8528ed3f..e06d9298abf 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -199,32 +199,6 @@ public:
               std::function<void (void)> lambda,
               tl::optional<Identifier> path = {});
 
-  template <typename P>
-  tl::optional<std::pair<Rib::Definition, Namespace>>
-  resolve_path (const P &path)
-  {
-    const auto &segments = path.get_segments ();
-
-    // Pair a definition with the namespace it was found in
-    auto pair_with_ns = [] (Namespace ns) {
-      return [ns] (Rib::Definition def) { return std::make_pair (def, ns); };
-    };
-
-    // We first check in values, if not found then types, if not found then
-    // macros. There should not be any ambiguity at this point - this function
-    // will short circuit and return the first definition it has found.
-    return values.resolve_path (segments)
-      .map (pair_with_ns (Namespace::Values))
-      .or_else ([&] () {
-       return types.resolve_path (segments).map (
-         pair_with_ns (Namespace::Types));
-      })
-      .or_else ([&] () {
-       return macros.resolve_path (segments).map (
-         pair_with_ns (Namespace::Macros));
-      });
-  }
-
   ForeverStack<Namespace::Values> values;
   ForeverStack<Namespace::Types> types;
   ForeverStack<Namespace::Macros> macros;
-- 
2.45.2

Reply via email to