]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Add name resolution for on globbing use decl
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Tue, 9 Jan 2024 12:51:35 +0000 (13:51 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 1 Aug 2024 14:52:26 +0000 (16:52 +0200)
This is the first part of the code required to enable globbing on use
declarations.

gcc/rust/ChangeLog:

* resolve/rust-toplevel-name-resolver-2.0.cc (GlobbingVisitor::visit):
Insert names into their namespace.
(TopLevel::visit): Insert ast module.
(TopLevel::handle_use_dec): Resolve use declaration.
(TopLevel::handle_use_glob): Use globbing visitor.
(flatten_list): Use globbing path vector.
(flatten_glob): Likewise.
(flatten): Likewise.
(prefix_subpaths): Add a function to prefix subpath.
* resolve/rust-toplevel-name-resolver-2.0.h (class GlobbingVisitor):
Add globbing visitor.
* util/rust-hir-map.cc (Mappings::insert_ast_module): Add function to
insert module in module hashmap.
(Mappings::lookup_ast_module): Add function to retrieve ast module.
* util/rust-hir-map.h: Add module map and getter/setter prototypes.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
gcc/rust/util/rust-hir-map.cc
gcc/rust/util/rust-hir-map.h

index 5e6f5e9bd78a7e2004d3e07de1811b44fde3fdd3..3122d41412f7ce1d90855f7a9543efad1b0a6e92 100644 (file)
 namespace Rust {
 namespace Resolver2_0 {
 
+void
+GlobbingVisitor::visit (AST::Module &module)
+{
+  if (module.get_visibility ().is_public ())
+    ctx.insert (module.get_name (), module.get_node_id (), Namespace::Types);
+}
+
+void
+GlobbingVisitor::visit (AST::MacroRulesDefinition &macro)
+{
+  if (macro.get_visibility ().is_public ())
+    ctx.insert (macro.get_rule_name (), macro.get_node_id (),
+               Namespace::Macros);
+}
+
+void
+GlobbingVisitor::visit (AST::Function &function)
+{
+  if (function.get_visibility ().is_public ())
+    ctx.insert (function.get_function_name (), function.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::StaticItem &static_item)
+{
+  if (static_item.get_visibility ().is_public ())
+    ctx.insert (static_item.get_identifier (), static_item.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::StructStruct &struct_item)
+{
+  if (struct_item.get_visibility ().is_public ())
+    ctx.insert (struct_item.get_identifier (), struct_item.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::TupleStruct &tuple_struct)
+{
+  if (tuple_struct.get_visibility ().is_public ())
+    ctx.insert (tuple_struct.get_identifier (), tuple_struct.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::Enum &enum_item)
+{
+  if (enum_item.get_visibility ().is_public ())
+    ctx.insert (enum_item.get_identifier (), enum_item.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::Union &union_item)
+{
+  if (union_item.get_visibility ().is_public ())
+    ctx.insert (union_item.get_identifier (), union_item.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::ConstantItem &const_item)
+{
+  if (const_item.get_visibility ().is_public ())
+    ctx.insert (const_item.get_identifier (), const_item.get_node_id (),
+               Namespace::Values);
+}
+
+void
+GlobbingVisitor::visit (AST::ExternCrate &crate)
+{}
+
+void
+GlobbingVisitor::visit (AST::UseDeclaration &use)
+{
+  // Handle cycles ?
+}
+
 TopLevel::TopLevel (NameResolutionContext &resolver)
   : DefaultResolver (resolver)
 {}
@@ -81,6 +162,10 @@ TopLevel::visit (AST::Module &module)
 
   ctx.scoped (Rib::Kind::Module, module.get_node_id (), sub_visitor,
              module.get_name ());
+
+  if (Analysis::Mappings::get ()->lookup_ast_module (module.get_node_id ())
+      == tl::nullopt)
+    Analysis::Mappings::get ()->insert_ast_module (&module);
 }
 
 template <typename PROC_MACRO>
@@ -302,13 +387,26 @@ TopLevel::visit (AST::ConstantItem &const_item)
 }
 
 bool
-TopLevel::handle_use_dec (AST::SimplePath path)
+TopLevel::handle_use_glob (AST::SimplePath glob)
 {
-  // TODO: Glob imports can get shadowed by regular imports and regular items.
-  // So we need to store them in a specific way in the ForeverStack - which can
-  // also probably be used by labels and macros etc. Like store it as a
-  // `Shadowable(NodeId)` instead of just a `NodeId`
+  auto resolved = ctx.types.resolve_path (glob.get_segments ());
+  if (!resolved.has_value ())
+    return false;
+
+  auto result = Analysis::Mappings::get ()->lookup_ast_module (*resolved);
+
+  if (!result.has_value ())
+    return false;
+
+  GlobbingVisitor gvisitor (ctx);
+  gvisitor.visit (*result.value ());
+
+  return true;
+}
 
+bool
+TopLevel::handle_use_dec (AST::SimplePath path)
+{
   auto locus = path.get_final_segment ().get_locus ();
   auto declared_name = path.get_final_segment ().as_string ();
 
@@ -377,14 +475,17 @@ static void
 flatten_rebind (const AST::UseTreeRebind &glob,
                std::vector<AST::SimplePath> &paths);
 static void
-flatten_list (const AST::UseTreeList &glob,
-             std::vector<AST::SimplePath> &paths);
+flatten_list (const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
+             std::vector<AST::SimplePath> &glob_paths,
+             NameResolutionContext &ctx);
 static void
 flatten_glob (const AST::UseTreeGlob &glob,
-             std::vector<AST::SimplePath> &paths);
+             std::vector<AST::SimplePath> &glob_paths,
+             NameResolutionContext &ctx);
 
 static void
-flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
+flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths,
+        std::vector<AST::SimplePath> &glob_paths, NameResolutionContext &ctx)
 {
   switch (tree->get_kind ())
     {
@@ -395,13 +496,12 @@ flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
       }
       case AST::UseTree::List: {
        auto list = static_cast<const AST::UseTreeList *> (tree);
-       flatten_list (*list, paths);
+       flatten_list (*list, paths, glob_paths, ctx);
        break;
       }
       case AST::UseTree::Glob: {
-       rust_sorry_at (tree->get_locus (), "cannot resolve glob imports yet");
        auto glob = static_cast<const AST::UseTreeGlob *> (tree);
-       flatten_glob (*glob, paths);
+       flatten_glob (*glob, glob_paths, ctx);
        break;
       }
       break;
@@ -432,8 +532,28 @@ flatten_rebind (const AST::UseTreeRebind &rebind,
     }
 }
 
+/** Prefix a list of subpath
+ * @param prefix A prefix for all subpath
+ * @param subs List of subpath to prefix
+ * @param size List where results should be stored
+ */
+static void
+prefix_subpaths (AST::SimplePath prefix, std::vector<AST::SimplePath> subs,
+                std::vector<AST::SimplePath> &results)
+{
+  for (auto &sub : subs)
+    {
+      auto new_path = prefix;
+      std::copy (sub.get_segments ().begin (), sub.get_segments ().end (),
+                std::back_inserter (new_path.get_segments ()));
+      results.emplace_back (new_path);
+    }
+}
+
 static void
-flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
+flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths,
+             std::vector<AST::SimplePath> &glob_paths,
+             NameResolutionContext &ctx)
 {
   auto prefix = AST::SimplePath::create_empty ();
   if (list.has_path ())
@@ -442,43 +562,52 @@ flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
   for (const auto &tree : list.get_trees ())
     {
       auto sub_paths = std::vector<AST::SimplePath> ();
-      flatten (tree.get (), sub_paths);
-
-      for (auto &sub_path : sub_paths)
-       {
-         auto new_path = prefix;
-         std::copy (sub_path.get_segments ().begin (),
-                    sub_path.get_segments ().end (),
-                    std::back_inserter (new_path.get_segments ()));
+      auto sub_globs = std::vector<AST::SimplePath> ();
+      flatten (tree.get (), sub_paths, sub_globs, ctx);
 
-         paths.emplace_back (new_path);
-       }
+      prefix_subpaths (prefix, sub_paths, paths);
+      prefix_subpaths (prefix, sub_globs, glob_paths);
     }
 }
 
 static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths)
+flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
+             NameResolutionContext &ctx)
 {
   if (glob.has_path ())
     paths.emplace_back (glob.get_path ());
+
+  // (PE): Get path rib
+  auto rib = ctx.values.resolve_path (glob.get_path ().get_segments ())
+              .and_then ([&] (NodeId id) { return ctx.values.to_rib (id); });
+  if (rib.has_value ())
+    {
+      auto value = rib.value ().get_values ();
+    }
 }
 
 void
 TopLevel::visit (AST::UseDeclaration &use)
 {
   auto paths = std::vector<AST::SimplePath> ();
+  auto glob_path = std::vector<AST::SimplePath> ();
 
   // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
   // How do we handle module imports in general? Should they get added to all
   // namespaces?
 
   const auto &tree = use.get_tree ();
-  flatten (tree.get (), paths);
+  flatten (tree.get (), paths, glob_path, this->ctx);
 
   for (auto &path : paths)
     if (!handle_use_dec (path))
       rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433,
                     "unresolved import %qs", path.as_string ().c_str ());
+
+  for (auto &glob : glob_path)
+    if (!handle_use_glob (glob))
+      rust_error_at (glob.get_final_segment ().get_locus (), ErrorCode::E0433,
+                    "unresolved import %qs", glob.as_string ().c_str ());
 }
 
 } // namespace Resolver2_0
index 0a766bab2598ddbe84e0025e247e321098f9dc37..31535a9b22e0f57d5ccb8a497b6b1a7cb05de2e0 100644 (file)
 namespace Rust {
 namespace Resolver2_0 {
 
+class GlobbingVisitor : public AST::DefaultASTVisitor
+{
+  using AST::DefaultASTVisitor::visit;
+
+public:
+  GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {}
+
+  void visit (AST::Module &module) override;
+  void visit (AST::MacroRulesDefinition &macro) override;
+  void visit (AST::Function &function) override;
+  void visit (AST::StaticItem &static_item) override;
+  void visit (AST::StructStruct &struct_item) override;
+  void visit (AST::TupleStruct &tuple_struct) override;
+  void visit (AST::Enum &enum_item) override;
+  void visit (AST::Union &union_item) override;
+  void visit (AST::ConstantItem &const_item) override;
+  void visit (AST::ExternCrate &crate) override;
+  void visit (AST::UseDeclaration &use) override;
+
+private:
+  NameResolutionContext &ctx;
+};
 /**
  * The `TopLevel` visitor takes care of collecting all the definitions in a
  * crate, and inserting them into the proper namespaces. These definitions can
@@ -85,6 +107,7 @@ private:
   // UseTreeList for example
   // FIXME: Should that return `found`?
   bool handle_use_dec (AST::SimplePath path);
+  bool handle_use_glob (AST::SimplePath glob);
 
   void visit (AST::UseDeclaration &use) override;
 };
index c62c11189aed3640590ea8d7b9215d0546b4d774..05b26d64069387f1c21cf24844cb34408cd815fb 100644 (file)
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-hir-map.h"
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
 #include "rust-hir-full.h"
+#include "rust-item.h"
 #include "rust-macro-builtins.h"
 #include "rust-mapping-common.h"
 #include "rust-attribute-values.h"
@@ -1158,6 +1160,23 @@ Mappings::lookup_module_children (NodeId module)
   return it->second;
 }
 
+void
+Mappings::insert_ast_module (AST::Module *module)
+{
+  rust_assert (modules.find (module->get_node_id ()) == modules.end ());
+  modules[module->get_node_id ()] = module;
+}
+
+tl::optional<AST::Module *>
+Mappings::lookup_ast_module (NodeId id)
+{
+  auto it = modules.find (id);
+  if (it == modules.end ())
+    return tl::nullopt;
+
+  return {it->second};
+}
+
 void
 Mappings::insert_module_child_item (NodeId module,
                                    Resolver::CanonicalPath child)
index 927c01251dbd20a30119a816c5f25dff3866fc92..92af0673f953875623dd42d6fc0674ef77e49eb3 100644 (file)
@@ -328,6 +328,8 @@ public:
   void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility);
   bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def);
 
+  void insert_ast_module (AST::Module *);
+  tl::optional<AST::Module *> lookup_ast_module (NodeId id);
   void insert_module_child (NodeId module, NodeId child);
   tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module);
 
@@ -427,6 +429,7 @@ private:
   std::map<NodeId, std::vector<NodeId>> module_child_map;
   std::map<NodeId, std::vector<Resolver::CanonicalPath>> module_child_items;
   std::map<NodeId, NodeId> child_to_parent_module_map;
+  std::map<NodeId, AST::Module *> modules;
 
   // AST mappings
   std::map<NodeId, AST::Item *> ast_item_mappings;