https://gcc.gnu.org/g:9047b32383a05b5ef5909de5eed35a0cd3c9a76a
commit r15-8395-g9047b32383a05b5ef5909de5eed35a0cd3c9a76a Author: Arthur Cohen <arthur.co...@embecosm.com> Date: Sat Apr 6 23:02:51 2024 +0200 gccrs: imports: Make FinalizeImports a resolver visitor as well 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. Diff: --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 84 ++++++++++++++-------- gcc/rust/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 ++++-- .../resolve/rust-toplevel-name-resolver-2.0.cc | 10 ++- gcc/rust/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 ba73a54d412a..ac8eb940c8d5 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 2ae316295335..a503686508c5 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 f5c8157f35b5..ac288e3f6e72 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 ed4dc7d1c910..a8b5ba095905 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 f2f8f359c4c0..47f3adee14c2 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 92a964d2c14f..acb60d36e133 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;