]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: nr2.0: Separate out canonical path handling
authorOwen Avery <powerboat9.gamer@gmail.com>
Fri, 2 May 2025 22:38:50 +0000 (18:38 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:45 +0000 (16:36 +0200)
This should improve our canonical path handling, without requiring
further tweaks to ForeverStack. This may also help if, in the future, we
have to move canonical path calculation to later compilation phases for
proper handling of generics.

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc
(HIRCompileBase::compile_function): Since canonical paths
returned from nr2.0 now include the crate name, avoid prepending
the crate name again.

* backend/rust-compile-implitem.cc (CompileTraitItem::visit):
Use NameResolutionContext::to_canonical_path instead of
ForeverStack::to_canonical_path.
* backend/rust-compile-item.cc (CompileItem::visit): Likewise.
* typecheck/rust-hir-type-check-enumitem.cc
(TypeCheckEnumItem::visit): Likewise.
* typecheck/rust-hir-type-check-implitem.cc
(TypeCheckImplItem::visit): Likewise.
* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
Likewise.
* typecheck/rust-hir-type-check.cc
(TraitItemReference::get_type_from_fn): Likewise.

* resolve/rust-default-resolver.cc (DefaultResolver::visit): Add
Crate and EnumItem instance visitors, handle canonical path
context scoping.
* resolve/rust-default-resolver.h (DefaultResolver::visit): Add
Crate and EnumItem instance visitors.
* resolve/rust-early-name-resolver-2.0.cc (Early::go): Visit
instances of Crate using the virtual member function visit.
* resolve/rust-forever-stack.h
(ForeverStack::to_canonical_path): Remove function declaration.
* resolve/rust-forever-stack.hxx
(ForeverStack::to_canonical_path): Remove function definition.
* resolve/rust-late-name-resolver-2.0.cc (Late::go): Visit
instances of Crate using the virtual member function visit.
* resolve/rust-name-resolution-context.cc
(CanonicalPathRecordCrateRoot::as_path): New function definition.
(CanonicalPathRecordNormal::as_path): Likewise.
(CanonicalPathRecordLookup::as_path): Likewise.
(CanonicalPathRecordImpl::as_path): Likewise.
(CanonicalPathRecordTraitImpl::as_path): Likewise.
(NameResolutionContext::NameResolutionContext): Initialize
member variable canonical_ctx.
* resolve/rust-name-resolution-context.h: Include "rust-item.h".
(class NameResolutionContext): Forward declare class.
(class CanonicalPathRecord): New class.
(class CanonicalPathRecordWithParent): Likewise.
(class CanonicalPathRecordCrateRoot): Likewise.
(class CanonicalPathRecordNormal): Likewise.
(class CanonicalPathRecordLookup): Likewise.
(class CanonicalPathRecordImpl): Likewise.
(class CanonicalPathRecordTraitImpl): Likewise.
(class CanonicalPathCtx): Likewise.
(NameResolutionContext::canonical_ctx): New member variable.
(NameResolutionContext::to_canonical_path): New member function.
* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go):
Visit instances of Crate with the virtual member function visit.
(TopLevel::visit): Handle canonical path context scoping for
external crates, use DefaultResolver::visit when visiting
instances of StructStruct.
* util/rust-canonical-path.h (CanonicalPath::new_seg): Take path
parameter by-value, as a duplicate instance will be constructed
regardless.

gcc/testsuite/ChangeLog:

* rust/compile/nr2/exclude: Remove canonical_paths1.rs.

18 files changed:
gcc/rust/backend/rust-compile-base.cc
gcc/rust/backend/rust-compile-implitem.cc
gcc/rust/backend/rust-compile-item.cc
gcc/rust/resolve/rust-default-resolver.cc
gcc/rust/resolve/rust-default-resolver.h
gcc/rust/resolve/rust-early-name-resolver-2.0.cc
gcc/rust/resolve/rust-forever-stack.h
gcc/rust/resolve/rust-forever-stack.hxx
gcc/rust/resolve/rust-late-name-resolver-2.0.cc
gcc/rust/resolve/rust-name-resolution-context.cc
gcc/rust/resolve/rust-name-resolution-context.h
gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
gcc/rust/typecheck/rust-hir-type-check-implitem.cc
gcc/rust/typecheck/rust-hir-type-check-item.cc
gcc/rust/typecheck/rust-hir-type-check.cc
gcc/rust/util/rust-canonical-path.h
gcc/testsuite/rust/compile/nr2/exclude

index 12b956168bd3fb99fc5e860e7869ed4dbd2c43b3..84c4bcd3fe434b5429a5147c463c783db3929f5c 100644 (file)
@@ -687,11 +687,6 @@ HIRCompileBase::compile_function (
     }
   std::string asm_name = fn_name;
 
-  auto &mappings = Analysis::Mappings::get ();
-
-  if (flag_name_resolution_2_0)
-    ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name;
-
   unsigned int flags = 0;
   tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
                                   "" /* asm_name */, flags, locus);
index 1230c85c57ca448cb2fdc217e067de5deb093d72..f9172c5282c6c0fe420c05aa921f7f52678141ba 100644 (file)
@@ -33,8 +33,8 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      canonical_path = nr_ctx.values.to_canonical_path (
-       constant.get_mappings ().get_nodeid ());
+      canonical_path
+       = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -103,7 +103,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ());
     }
   else
     {
index 96669903fd55572c41ebe0af99720cc9460be194..3e7ea9a25e9347155f0e26fc288d3041f758c569 100644 (file)
@@ -58,7 +58,7 @@ CompileItem::visit (HIR::StaticItem &var)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -124,8 +124,7 @@ CompileItem::visit (HIR::ConstantItem &constant)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      canonical_path
-       = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value ();
+      canonical_path = nr_ctx.to_canonical_path (mappings.get_nodeid ());
     }
   else
     {
@@ -218,10 +217,8 @@ CompileItem::visit (HIR::Function &function)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      auto path = nr_ctx.values.to_canonical_path (
-       function.get_mappings ().get_nodeid ());
-
-      canonical_path = path.value ();
+      canonical_path
+       = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
     }
   else
     {
index a4793c0487081a38825c3bafff8ab11688f2196d..969711c29950c53bc59791b6038a46b894d3f656 100644 (file)
 namespace Rust {
 namespace Resolver2_0 {
 
+void
+DefaultResolver::visit (AST::Crate &crate)
+{
+  auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); };
+
+  auto &mappings = Analysis::Mappings::get ();
+
+  auto crate_num = mappings.lookup_crate_num (crate.get_node_id ());
+  rust_assert (crate_num.has_value ());
+  auto crate_name = mappings.get_crate_name (*crate_num);
+  rust_assert (crate_name.has_value ());
+
+  ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn);
+}
+
 void
 DefaultResolver::visit (AST::BlockExpr &expr)
 {
@@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr)
 void
 DefaultResolver::visit (AST::Module &module)
 {
-  auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+  auto item_fn_1
+    = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
 
-  ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn,
+  auto item_fn_2 = [this, &module, &item_fn_1] () {
+    ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (),
+                            std::move (item_fn_1));
+  };
+
+  ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2,
              module.get_name ());
 }
 
 void
 DefaultResolver::visit (AST::Function &function)
 {
-  auto def_fn
+  auto def_fn_1
     = [this, &function] () { AST::DefaultASTVisitor::visit (function); };
 
-  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+  auto def_fn_2 = [this, &function, &def_fn_1] () {
+    ctx.canonical_ctx.scope (function.get_node_id (),
+                            function.get_function_name (),
+                            std::move (def_fn_1));
+  };
+
+  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2,
+             function.get_function_name ());
 }
 
 void
@@ -85,9 +113,15 @@ DefaultResolver::visit (AST::IfLetExpr &expr)
 void
 DefaultResolver::visit (AST::Trait &trait)
 {
-  auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+  auto inner_fn_1
+    = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+
+  auto inner_fn_2 = [this, &trait, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (),
+                            std::move (inner_fn_1));
+  };
 
-  ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn,
+  ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_2,
              trait.get_identifier () /* FIXME: Is that valid?*/);
 }
 
@@ -98,12 +132,12 @@ DefaultResolver::visit (AST::InherentImpl &impl)
   visit (impl.get_visibility ());
   visit_inner_attrs (impl);
 
-  auto inner_fn_inner = [this, &impl] () {
+  auto inner_fn_1 = [this, &impl] () {
     for (auto &item : impl.get_impl_items ())
       visit (item);
   };
 
-  auto inner_fn_outer = [this, &impl, &inner_fn_inner] () {
+  auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
     maybe_insert_big_self (impl);
     for (auto &generic : impl.get_generic_params ())
       visit (generic);
@@ -111,10 +145,14 @@ DefaultResolver::visit (AST::InherentImpl &impl)
       visit (impl.get_where_clause ());
     visit_impl_type (impl.get_type ());
 
-    ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner);
+    ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
   };
 
-  ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer);
+  auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+    ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+  };
+
+  ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
 }
 
 void
@@ -124,12 +162,12 @@ DefaultResolver::visit (AST::TraitImpl &impl)
   visit (impl.get_visibility ());
   visit_inner_attrs (impl);
 
-  auto inner_fn_inner = [this, &impl] () {
+  auto inner_fn_1 = [this, &impl] () {
     for (auto &item : impl.get_impl_items ())
       visit (item);
   };
 
-  auto inner_fn_outer = [this, &impl, &inner_fn_inner] () {
+  auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
     maybe_insert_big_self (impl);
     for (auto &generic : impl.get_generic_params ())
       visit (generic);
@@ -138,55 +176,120 @@ DefaultResolver::visit (AST::TraitImpl &impl)
     visit_impl_type (impl.get_type ());
     visit (impl.get_trait_path ());
 
-    ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner);
+    ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+  };
+
+  auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+    ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
   };
 
-  ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer);
+  ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
 }
 
 void
 DefaultResolver::visit (AST::StructStruct &type)
 {
-  auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+  auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+  auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+                            std::move (inner_fn_1));
+  };
 
   ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
-             inner_fn, type.get_struct_name ());
+             inner_fn_2, type.get_struct_name ());
 }
 
 void
 DefaultResolver::visit (AST::TupleStruct &type)
 {
-  auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+  auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+  auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+                            std::move (inner_fn_1));
+  };
 
   ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
-             inner_fn, type.get_struct_name ());
+             inner_fn_2, type.get_struct_name ());
+}
+
+void
+DefaultResolver::visit (AST::EnumItem &item)
+{
+  auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+  ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                          inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemTuple &item)
+{
+  auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+  ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                          inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemStruct &item)
+{
+  auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+  ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                          inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemDiscriminant &item)
+{
+  auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+  ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                          inner_fn);
 }
 
 void
 DefaultResolver::visit (AST::Enum &type)
 {
-  auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+  auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+  auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+                            std::move (inner_fn_1));
+  };
 
   ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
-             variant_fn, type.get_identifier ());
+             inner_fn_2, type.get_identifier ());
 }
 
 void
 DefaultResolver::visit (AST::Union &type)
 {
-  auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+  auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+  auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+                            std::move (inner_fn_1));
+  };
 
   ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
-             inner_fn, type.get_identifier ());
+             inner_fn_2, type.get_identifier ());
 }
 
 void
 DefaultResolver::visit (AST::TypeAlias &type)
 {
-  auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+  auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+  auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (),
+                            std::move (inner_fn_1));
+  };
 
   ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
-             inner_fn, type.get_new_type_name ());
+             inner_fn_2, type.get_new_type_name ());
 }
 
 void
@@ -221,21 +324,31 @@ DefaultResolver::visit (AST::ConstantItem &item)
 {
   if (item.has_expr ())
     {
-      auto expr_vis
+      auto expr_vis_1
        = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
 
+      auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+       ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                                std::move (expr_vis_1));
+      };
+
       // FIXME: Why do we need a Rib here?
-      ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
+      ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
     }
 }
 
 void
 DefaultResolver::visit (AST::StaticItem &item)
 {
-  auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+  auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+  auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+    ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+                            std::move (expr_vis_1));
+  };
 
   // FIXME: Why do we need a Rib here?
-  ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
+  ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
 }
 
 void
index f500d9018f2eca991aadbeed441ea7046f0e7d1c..e80d77440b15b785d4a97ad6f0a8d9108eef9b14 100644 (file)
@@ -39,6 +39,7 @@ public:
 
   virtual ~DefaultResolver () {}
 
+  void visit (AST::Crate &) override;
   // First, our lexical scope expressions - these visit their sub nodes, always
   // these nodes create new scopes and ribs - they are often used to declare new
   // variables, such as a for loop's iterator, or a function's arguments
@@ -60,6 +61,10 @@ public:
   // type dec nodes, which visit their fields or variants by default
   void visit (AST::StructStruct &) override;
   void visit (AST::TupleStruct &) override;
+  void visit (AST::EnumItem &) override;
+  void visit (AST::EnumItemTuple &) override;
+  void visit (AST::EnumItemStruct &) override;
+  void visit (AST::EnumItemDiscriminant &) override;
   void visit (AST::Enum &) override;
   void visit (AST::Union &) override;
   void visit (AST::TypeAlias &) override;
index b00bd1ee7f8ec7d761f9f287152ef22ebb546367..c10379a65eb4ae713aa7750c819a19c043eefec3 100644 (file)
@@ -62,8 +62,9 @@ Early::go (AST::Crate &crate)
   // We now proceed with resolving macros, which can be nested in almost any
   // items
   textual_scope.push ();
-  for (auto &item : crate.items)
-    item->accept_vis (*this);
+
+  visit (crate);
+
   textual_scope.pop ();
 }
 
index 3f6f002da68855795fc75edb1f160f0de0776ed1..75dd87395befe9c0a4f07fda5eea05ae37516c89 100644 (file)
@@ -683,9 +683,6 @@ public:
     std::function<void (const S &, NodeId)> insert_segment_resolution,
     std::vector<Error> &collect_errors);
 
-  // FIXME: Documentation
-  tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
-
   // FIXME: Documentation
   tl::optional<Rib &> to_rib (NodeId rib_id);
   tl::optional<const Rib &> to_rib (NodeId rib_id) const;
index d568682786c2e9f229cc0d90426e9c0155561bd9..df3df1059fcbb991e51d908ee5935732776793b2 100644 (file)
@@ -773,67 +773,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point,
   return tl::nullopt;
 }
 
-template <Namespace N>
-tl::optional<Resolver::CanonicalPath>
-ForeverStack<N>::to_canonical_path (NodeId id) const
-{
-  // find the id in the current forever stack, starting from the root,
-  // performing either a BFS or DFS once the Node containing the ID is found, go
-  // back up to the root (parent().parent().parent()...) accumulate link
-  // segments reverse them that's your canonical path
-
-  return dfs (root, id).map ([this, id] (ConstDfsResult tuple) {
-    auto containing_node = tuple.first;
-    auto name = tuple.second;
-
-    auto segments = std::vector<Resolver::CanonicalPath> ();
-
-    reverse_iter (containing_node, [&segments] (const Node &current) {
-      if (current.is_root ())
-       return KeepGoing::No;
-
-      auto children = current.parent.value ().children;
-      const Link *outer_link = nullptr;
-
-      for (auto &kv : children)
-       {
-         auto &link = kv.first;
-         auto &child = kv.second;
-
-         if (current.id == child.id)
-           {
-             outer_link = &link;
-             break;
-           }
-       }
-
-      rust_assert (outer_link);
-
-      outer_link->path.map ([&segments, outer_link] (Identifier path) {
-       segments.emplace (segments.begin (),
-                         Resolver::CanonicalPath::new_seg (outer_link->id,
-                                                           path.as_string ()));
-      });
-
-      return KeepGoing::Yes;
-    });
-
-    auto &mappings = Analysis::Mappings::get ();
-    CrateNum crate_num = mappings.lookup_crate_num (root.id).value ();
-    auto path = Resolver::CanonicalPath::new_seg (
-      root.id, mappings.get_crate_name (crate_num).value ());
-    path.set_crate_num (crate_num);
-
-    for (const auto &segment : segments)
-      path = path.append (segment);
-
-    // Finally, append the name
-    path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-
-    return path;
-  });
-}
-
 template <Namespace N>
 tl::optional<Rib &>
 ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find)
index 99e798682464715ab65141034f74d1bc938409d4..1c0850c66f426c68b16811c725786b48128fc800 100644 (file)
@@ -116,8 +116,7 @@ Late::go (AST::Crate &crate)
 {
   setup_builtin_types ();
 
-  for (auto &item : crate.items)
-    item->accept_vis (*this);
+  visit (crate);
 }
 
 void
index f098e4880e59924e86971249a18b3ad405ae912c..34615ed97c323db33fb9a1ea2839a88b418db6a9 100644 (file)
@@ -82,8 +82,63 @@ BindingLayer::get_source () const
   return source;
 }
 
+Resolver::CanonicalPath
+CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
+{
+  auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
+  ret.set_crate_num (crate_num);
+  return ret;
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
+{
+  auto parent_path = get_parent ().as_path (ctx);
+  return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
+{
+  if (!cache)
+    {
+      auto res = ctx.lookup (lookup_id).and_then (
+       [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
+
+      if (!res)
+       {
+         // HACK: use a dummy value
+         // this should bring us roughly to parity with nr1.0
+         // since nr1.0 doesn't seem to handle canonical paths for generics
+         //   quite right anyways
+         return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
+       }
+
+      cache = res.value ();
+    }
+  return cache->as_path (ctx);
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
+{
+  auto parent_path = get_parent ().as_path (ctx);
+  return parent_path.append (
+    Resolver::CanonicalPath::inherent_impl_seg (impl_id,
+                                               type_record.as_path (ctx)));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
+{
+  auto parent_path = get_parent ().as_path (ctx);
+  return parent_path.append (
+    Resolver::CanonicalPath::trait_impl_projection_seg (
+      impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
+}
+
 NameResolutionContext::NameResolutionContext ()
-  : mappings (Analysis::Mappings::get ())
+  : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
 {}
 
 tl::expected<NodeId, DuplicateNameError>
index 1509857739e8926ea8790c983d2b227ceb440dfb..bb8519a049334de51c9e159fa6de779110383a5b 100644 (file)
@@ -24,6 +24,7 @@
 #include "rust-hir-map.h"
 #include "rust-rib.h"
 #include "rust-stacked-contexts.h"
+#include "rust-item.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -214,6 +215,248 @@ public:
   BindingSource get_source () const;
 };
 
+class NameResolutionContext;
+/*
+ * Used to handle canonical paths
+ * Similar to ForeverStack, but namespace independent and more specialized
+ */
+class CanonicalPathRecord
+{
+public:
+  virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0;
+
+  virtual bool is_root () const = 0;
+
+  virtual ~CanonicalPathRecord () = default;
+};
+
+class CanonicalPathRecordWithParent : public CanonicalPathRecord
+{
+public:
+  CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent)
+  {}
+
+  CanonicalPathRecord &get_parent () { return *parent; }
+
+  bool is_root () const override final { return false; }
+
+private:
+  CanonicalPathRecord *parent;
+};
+
+class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
+{
+public:
+  CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg)
+    : node_id (node_id), seg (std::move (seg))
+  {
+    rust_assert (Analysis::Mappings::get ().node_is_crate (node_id));
+    crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value ();
+  }
+
+  Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+  bool is_root () const override final { return true; }
+
+private:
+  NodeId node_id;
+  CrateNum crate_num;
+  std::string seg;
+};
+
+class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
+{
+public:
+  CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
+                            std::string seg)
+    : CanonicalPathRecordWithParent (parent), node_id (node_id),
+      seg (std::move (seg))
+  {
+    rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
+  }
+
+  Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+  NodeId node_id;
+  std::string seg;
+};
+
+class CanonicalPathRecordLookup : public CanonicalPathRecord
+{
+public:
+  CanonicalPathRecordLookup (NodeId lookup_id)
+    : lookup_id (lookup_id), cache (nullptr)
+  {}
+
+  Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+  bool is_root () const override final { return true; }
+
+private:
+  NodeId lookup_id;
+  CanonicalPathRecord *cache;
+};
+
+class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
+{
+public:
+  CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
+                          NodeId type_id)
+    : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+      type_record (type_id)
+  {}
+
+  Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+  NodeId impl_id;
+  CanonicalPathRecordLookup type_record;
+};
+
+class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
+{
+public:
+  CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
+                               NodeId type_id, NodeId trait_path_id)
+    : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+      type_record (type_id), trait_path_record (trait_path_id)
+  {}
+
+  Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+  NodeId impl_id;
+  CanonicalPathRecordLookup type_record;
+  CanonicalPathRecordLookup trait_path_record;
+};
+
+class CanonicalPathCtx
+{
+public:
+  CanonicalPathCtx (const NameResolutionContext &ctx)
+    : current_record (nullptr), nr_ctx (&ctx)
+  {}
+
+  Resolver::CanonicalPath get_path (NodeId id) const
+  {
+    return get_record (id).as_path (*nr_ctx);
+  }
+
+  CanonicalPathRecord &get_record (NodeId id) const
+  {
+    auto it = records.find (id);
+    rust_assert (it != records.end ());
+    return *it->second;
+  }
+
+  tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const
+  {
+    auto it = records.find (id);
+    if (it == records.end ())
+      return tl::nullopt;
+    else
+      return it->second.get ();
+  }
+
+  void insert_record (NodeId id, const Identifier &ident)
+  {
+    insert_record (id, ident.as_string ());
+  }
+
+  void insert_record (NodeId id, std::string seg)
+  {
+    rust_assert (current_record != nullptr);
+
+    auto it = records.find (id);
+    if (it == records.end ())
+      {
+       auto record = new CanonicalPathRecordNormal (*current_record, id,
+                                                    std::move (seg));
+       bool ok
+         = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+             .second;
+       rust_assert (ok);
+      }
+  }
+
+  template <typename F> void scope (NodeId id, const Identifier &ident, F &&f)
+  {
+    scope (id, ident.as_string (), std::forward<F> (f));
+  }
+
+  template <typename F> void scope (NodeId id, std::string seg, F &&f)
+  {
+    rust_assert (current_record != nullptr);
+
+    scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
+      return new CanonicalPathRecordNormal (*current_record, id,
+                                           std::move (seg));
+    });
+  }
+
+  template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
+  {
+    rust_assert (current_record != nullptr);
+
+    NodeId id = impl.get_node_id ();
+    scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+      return new CanonicalPathRecordImpl (*current_record, id,
+                                         impl.get_type ().get_node_id ());
+    });
+  }
+
+  template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
+  {
+    rust_assert (current_record != nullptr);
+
+    NodeId id = impl.get_node_id ();
+    scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+      return new CanonicalPathRecordTraitImpl (
+       *current_record, id, impl.get_type ().get_node_id (),
+       impl.get_trait_path ().get_node_id ());
+    });
+  }
+
+  template <typename F>
+  void scope_crate (NodeId node_id, std::string crate_name, F &&f)
+  {
+    scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () {
+      return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name));
+    });
+  }
+
+private:
+  template <typename FCreate, typename FCallback>
+  void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
+  {
+    auto it = records.find (id);
+    if (it == records.end ())
+      {
+       CanonicalPathRecord *record = std::forward<FCreate> (f_create) ();
+       it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+              .first;
+      }
+
+    rust_assert (it->second->is_root ()
+                || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
+                       .get_parent ()
+                     == current_record);
+
+    CanonicalPathRecord *stash = it->second.get ();
+    std::swap (stash, current_record);
+
+    std::forward<FCallback> (f_callback) ();
+
+    std::swap (stash, current_record);
+  }
+
+  std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
+  CanonicalPathRecord *current_record;
+
+  const NameResolutionContext *nr_ctx;
+};
+
 // Now our resolver, which keeps track of all the `ForeverStack`s we could want
 class NameResolutionContext
 {
@@ -272,12 +515,19 @@ public:
   Analysis::Mappings &mappings;
   StackedContexts<BindingLayer> bindings;
 
+  CanonicalPathCtx canonical_ctx;
+
   // TODO: Rename
   // TODO: Use newtype pattern for Usage and Definition
   void map_usage (Usage usage, Definition definition);
 
   tl::optional<NodeId> lookup (NodeId usage) const;
 
+  Resolver::CanonicalPath to_canonical_path (NodeId id) const
+  {
+    return canonical_ctx.get_path (id);
+  }
+
   template <typename S>
   tl::optional<Rib::Definition>
   resolve_path (const std::vector<S> &segments, ResolutionMode mode,
index 4d88ad1eb37063b905d2128340eacf7d9cc0bd3c..3e5ed534e4e637a07c04818ae55cd360a2bad47e 100644 (file)
@@ -95,8 +95,7 @@ TopLevel::go (AST::Crate &crate)
   // times in a row in a fixed-point fashion, so it would make the code
   // responsible for this ugly and perfom a lot of error checking.
 
-  for (auto &item : crate.items)
-    item->accept_vis (*this);
+  visit (crate);
 }
 
 void
@@ -194,7 +193,7 @@ TopLevel::visit (AST::ExternCrate &crate)
 
   auto derive_macros = mappings.lookup_derive_proc_macros (num);
 
-  auto sub_visitor = [&] () {
+  auto sub_visitor_1 = [&] () {
     // TODO: Find a way to keep this part clean without the double dispatch.
     if (derive_macros.has_value ())
       {
@@ -216,11 +215,17 @@ TopLevel::visit (AST::ExternCrate &crate)
       }
   };
 
+  auto sub_visitor_2 = [&] () {
+    ctx.canonical_ctx.scope_crate (crate.get_node_id (),
+                                  crate.get_referenced_crate (),
+                                  std::move (sub_visitor_1));
+  };
+
   if (crate.has_as_clause ())
-    ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
+    ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2,
                crate.get_as_clause ());
   else
-    ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
+    ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2,
                crate.get_referenced_crate ());
 }
 
@@ -298,14 +303,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item)
 void
 TopLevel::visit (AST::StructStruct &struct_item)
 {
-  auto generic_vis = [this, &struct_item] () {
-    for (auto &g : struct_item.get_generic_params ())
-      {
-       g->accept_vis (*this);
-      }
-  };
-
-  ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis);
+  DefaultResolver::visit (struct_item);
 
   insert_or_error_out (struct_item.get_struct_name (), struct_item,
                       Namespace::Types);
index c80a12f8f84e6cccb22757626a4c4a53d6f15217..2dbd84d254aeea383d860aeab7f39f0d738a7632 100644 (file)
@@ -87,7 +87,7 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -131,7 +131,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -193,7 +193,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -253,7 +253,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item)
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
     }
   else
     {
index 168a934fa540329b6aa095d1cb1b00191f0c1d26..00f0cc669747354a26b0b07532e61fcd5238a394 100644 (file)
@@ -345,8 +345,8 @@ TypeCheckImplItem::visit (HIR::Function &function)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      canonical_path = nr_ctx.values.to_canonical_path (
-       function.get_mappings ().get_nodeid ());
+      canonical_path
+       = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
     }
   else
     {
index aaa04af628f46e95954b0903e065620de674ba6d..5595dad22cc5df54b10bca0e213b403d9fd15040 100644 (file)
@@ -203,9 +203,8 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      path = nr_ctx.values
-              .to_canonical_path (struct_decl.get_mappings ().get_nodeid ())
-              .value ();
+      path
+       = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -283,12 +282,8 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
     {
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-      auto canonical_path = nr_ctx.types.to_canonical_path (
-       struct_decl.get_mappings ().get_nodeid ());
-
-      if (!canonical_path.has_value ())
-       rust_unreachable ();
-      path = canonical_path.value ();
+      path
+       = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -375,8 +370,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      canonical_path = nr_ctx.types.to_canonical_path (
-       enum_decl.get_mappings ().get_nodeid ());
+      canonical_path
+       = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -439,8 +434,8 @@ TypeCheckItem::visit (HIR::Union &union_decl)
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
-      canonical_path = nr_ctx.types.to_canonical_path (
-       union_decl.get_mappings ().get_nodeid ());
+      canonical_path
+       = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ());
     }
   else
     {
@@ -614,10 +609,7 @@ TypeCheckItem::visit (HIR::Function &function)
     {
       auto &nr_ctx
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-      auto canonical_path = nr_ctx.values.to_canonical_path (
-       function.get_mappings ().get_nodeid ());
-
-      path = canonical_path.value ();
+      path = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
     }
   else
     {
index d386fda036bb2e39c8959e36875ab9184e9810a0..27879e3d4e9da940320cf3db4a1bcb37689c3d6f 100644 (file)
@@ -284,7 +284,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
        = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
 
       canonical_path
-       = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ());
+       = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ());
     }
   else
     {
index ee37befb2e044c75f3ccd327ebda2849454fa4e4..079ae76eadbac1dd51caafc822781ccf3a6b25f0 100644 (file)
@@ -57,10 +57,11 @@ public:
     return *this;
   }
 
-  static CanonicalPath new_seg (NodeId id, const std::string &path)
+  static CanonicalPath new_seg (NodeId id, std::string path)
   {
     rust_assert (!path.empty ());
-    return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
+    return CanonicalPath ({std::pair<NodeId, std::string> (id,
+                                                          std::move (path))},
                          UNKNOWN_CRATENUM);
   }
 
index dc8d5fbcc0892af4b8da75f1344bf0a4b8efe059..9d5b7dfbbd30b7289dbd28b3b938231d3c53b0e7 100644 (file)
@@ -1,4 +1,3 @@
-canonical_paths1.rs
 issue-3315-2.rs
 privacy8.rs
 pub_restricted_1.rs