From: Owen Avery <powerboat9.ga...@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.ga...@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

Reply via email to