[COMMITTED 02/32] gccrs: nr2.0: Handle global paths

arthur.cohen@embecosm.com arthur.cohen@embecosm.com
Tue Apr 8 08:17:11 GMT 2025


From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.h
	(ForeverStack::ForeverStack): Initialize extern_prelude.
	(ForeverStack::resolve_path): Add parameter
	has_opening_scope_resolution.
	(ForeverStack::extern_prelude): Add field.
	* resolve/rust-forever-stack.hxx: Include rust-edition.h.
	(ForeverStacl::resolve_path): Handle global paths (paths with an
	opening scope resolution operator).
	* resolve/rust-late-name-resolver-2.0.cc
	(Late::visit): Handle global paths.
	* resolve/rust-name-resolution-context.h
	(NameResolutionContext::resolve_path): Handle global paths.

gcc/testsuite/ChangeLog:

	* rust/compile/nr2/exclude: Remove entries.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/resolve/rust-forever-stack.h         |  7 +-
 gcc/rust/resolve/rust-forever-stack.hxx       | 79 ++++++++++++-------
 .../resolve/rust-late-name-resolver-2.0.cc    | 18 ++---
 .../resolve/rust-name-resolution-context.h    | 41 ++++++++--
 gcc/testsuite/rust/compile/nr2/exclude        |  2 -
 5 files changed, 96 insertions(+), 51 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index f390e3889df..cf0265140de 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -549,6 +549,7 @@ public:
   ForeverStack ()
     : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
       lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
+      extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)),
       cursor_reference (root)
   {
     rust_assert (root.is_root ());
@@ -671,7 +672,7 @@ public:
    */
   template <typename S>
   tl::optional<Rib::Definition> resolve_path (
-    const std::vector<S> &segments,
+    const std::vector<S> &segments, bool has_opening_scope_resolution,
     std::function<void (const S &, NodeId)> insert_segment_resolution);
 
   // FIXME: Documentation
@@ -768,6 +769,10 @@ private:
    * resolution
    */
   Node lang_prelude;
+  /*
+   * The extern prelude, used for resolving external crates
+   */
+  Node extern_prelude;
 
   std::reference_wrapper<Node> cursor_reference;
 
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 885f2820684..993e2d4fd2a 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -20,6 +20,7 @@
 #include "rust-ast.h"
 #include "rust-diagnostics.h"
 #include "rust-forever-stack.h"
+#include "rust-edition.h"
 #include "rust-rib.h"
 #include "rust-unwrap-segment.h"
 #include "optional.h"
@@ -618,11 +619,24 @@ template <Namespace N>
 template <typename S>
 tl::optional<Rib::Definition>
 ForeverStack<N>::resolve_path (
-  const std::vector<S> &segments,
+  const std::vector<S> &segments, bool has_opening_scope_resolution,
   std::function<void (const S &, NodeId)> insert_segment_resolution)
 {
   // TODO: What to do if segments.empty() ?
 
+  // handle paths with opening scopes
+  std::function<void (void)> cleanup_current = [] () {};
+  if (has_opening_scope_resolution)
+    {
+      Node *last_current = &cursor_reference.get ();
+      if (get_rust_edition () == Edition::E2015)
+	cursor_reference = root;
+      else
+	cursor_reference = extern_prelude;
+      cleanup_current
+	= [this, last_current] () { cursor_reference = *last_current; };
+    }
+
   // if there's only one segment, we just use `get`
   if (segments.size () == 1)
     {
@@ -633,6 +647,7 @@ ForeverStack<N>::resolve_path (
 	    lang_item.value ());
 
 	  insert_segment_resolution (seg, seg_id);
+	  cleanup_current ();
 	  // TODO: does NonShadowable matter?
 	  return Rib::Definition::NonShadowable (seg_id);
 	}
@@ -646,40 +661,44 @@ ForeverStack<N>::resolve_path (
 
       if (res && !res->is_ambiguous ())
 	insert_segment_resolution (segments.back (), res->get_node_id ());
+      cleanup_current ();
       return res;
     }
 
   std::reference_wrapper<Node> starting_point = cursor ();
 
-  return find_starting_point (segments, starting_point,
-			      insert_segment_resolution)
-    .and_then ([this, &segments, &starting_point, &insert_segment_resolution] (
-		 typename std::vector<S>::const_iterator iterator) {
-      return resolve_segments (starting_point.get (), segments, iterator,
-			       insert_segment_resolution);
-    })
-    .and_then ([this, &segments, &insert_segment_resolution] (
-		 Node final_node) -> tl::optional<Rib::Definition> {
-      // leave resolution within impl blocks to type checker
-      if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
-	return tl::nullopt;
-
-      auto &seg = unwrap_type_segment (segments.back ());
-      std::string seg_name = seg.as_string ();
-
-      // assuming this can't be a lang item segment
-      tl::optional<Rib::Definition> res
-	= resolve_final_segment (final_node, seg_name,
-				 seg.is_lower_self_seg ());
-      // Ok we didn't find it in the rib, Lets try the prelude...
-      if (!res)
-	res = get_lang_prelude (seg_name);
-
-      if (res && !res->is_ambiguous ())
-	insert_segment_resolution (segments.back (), res->get_node_id ());
-
-      return res;
-    });
+  auto res
+    = find_starting_point (segments, starting_point, insert_segment_resolution)
+	.and_then (
+	  [this, &segments, &starting_point, &insert_segment_resolution] (
+	    typename std::vector<S>::const_iterator iterator) {
+	    return resolve_segments (starting_point.get (), segments, iterator,
+				     insert_segment_resolution);
+	  })
+	.and_then ([this, &segments, &insert_segment_resolution] (
+		     Node final_node) -> tl::optional<Rib::Definition> {
+	  // leave resolution within impl blocks to type checker
+	  if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
+	    return tl::nullopt;
+
+	  auto &seg = unwrap_type_segment (segments.back ());
+	  std::string seg_name = seg.as_string ();
+
+	  // assuming this can't be a lang item segment
+	  tl::optional<Rib::Definition> res
+	    = resolve_final_segment (final_node, seg_name,
+				     seg.is_lower_self_seg ());
+	  // Ok we didn't find it in the rib, Lets try the prelude...
+	  if (!res)
+	    res = get_lang_prelude (seg_name);
+
+	  if (res && !res->is_ambiguous ())
+	    insert_segment_resolution (segments.back (), res->get_node_id ());
+
+	  return res;
+	});
+  cleanup_current ();
+  return res;
 }
 
 template <Namespace N>
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 7d323745edb..d18e7e2a324 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -307,8 +307,7 @@ Late::visit (AST::PathInExpression &expr)
       return;
     }
 
-  auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values,
-				    Namespace::Types);
+  auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
 
   if (!resolved)
     {
@@ -340,13 +339,9 @@ Late::visit (AST::TypePath &type)
 
   DefaultResolver::visit (type);
 
-  // take care of only simple cases
-  // TODO: remove this?
-  rust_assert (!type.has_opening_scope_resolution_op ());
-
   // this *should* mostly work
   // TODO: make sure typepath-like path resolution (?) is working
-  auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types);
+  auto resolved = ctx.resolve_path (type, Namespace::Types);
 
   if (!resolved.has_value ())
     {
@@ -394,8 +389,7 @@ Late::visit (AST::StructExprStruct &s)
   visit_inner_attrs (s);
   DefaultResolver::visit (s.get_struct_name ());
 
-  auto resolved
-    = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+  auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
 
   ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
 		 Definition (resolved->get_node_id ()));
@@ -409,8 +403,7 @@ Late::visit (AST::StructExprStructBase &s)
   DefaultResolver::visit (s.get_struct_name ());
   visit (s.get_struct_base ());
 
-  auto resolved
-    = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+  auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
 
   ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
 		 Definition (resolved->get_node_id ()));
@@ -427,8 +420,7 @@ Late::visit (AST::StructExprStructFields &s)
   for (auto &field : s.get_fields ())
     visit (field);
 
-  auto resolved
-    = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+  auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
 
   ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
 		 Definition (resolved->get_node_id ()));
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index ea81bdeed54..84c0800ac4a 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -221,6 +221,7 @@ public:
 
   template <typename S>
   tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
+					      bool has_opening_scope_resolution,
 					      Namespace ns)
   {
     std::function<void (const S &, NodeId)> insert_segment_resolution
@@ -232,13 +233,17 @@ public:
     switch (ns)
       {
       case Namespace::Values:
-	return values.resolve_path (segments, insert_segment_resolution);
+	return values.resolve_path (segments, has_opening_scope_resolution,
+				    insert_segment_resolution);
       case Namespace::Types:
-	return types.resolve_path (segments, insert_segment_resolution);
+	return types.resolve_path (segments, has_opening_scope_resolution,
+				   insert_segment_resolution);
       case Namespace::Macros:
-	return macros.resolve_path (segments, insert_segment_resolution);
+	return macros.resolve_path (segments, has_opening_scope_resolution,
+				    insert_segment_resolution);
       case Namespace::Labels:
-	return labels.resolve_path (segments, insert_segment_resolution);
+	return labels.resolve_path (segments, has_opening_scope_resolution,
+				    insert_segment_resolution);
       default:
 	rust_unreachable ();
       }
@@ -246,19 +251,45 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
+					      bool has_opening_scope_resolution,
 					      Args... ns_args)
   {
     std::initializer_list<Namespace> namespaces = {ns_args...};
 
     for (auto ns : namespaces)
       {
-	if (auto ret = resolve_path (segments, ns))
+	if (auto ret
+	    = resolve_path (segments, has_opening_scope_resolution, ns))
 	  return ret;
       }
 
     return tl::nullopt;
   }
 
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
+					      Args... ns_args)
+  {
+    return resolve_path (path.get_segments (),
+			 path.has_opening_scope_resolution (), ns_args...);
+  }
+
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
+					      Args... ns_args)
+  {
+    return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+			 ns_args...);
+  }
+
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+					      Args... ns_args)
+  {
+    return resolve_path (path.get_segments (),
+			 path.has_opening_scope_resolution_op (), ns_args...);
+  }
+
 private:
   /* Map of "usage" nodes which have been resolved to a "definition" node */
   std::map<Usage, Definition> resolved_nodes;
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
index 19bf6f8f609..ca725719196 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -21,8 +21,6 @@ issue-266.rs
 derive_clone_enum3.rs
 derive-debug1.rs
 derive-default1.rs
-issue-3402-1.rs
-issue-3403.rs
 derive-eq-invalid.rs
 derive-hash1.rs
 torture/alt_patterns1.rs
-- 
2.49.0



More information about the Gcc-rust mailing list