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