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

gcc/rust/ChangeLog:

        * resolve/rust-forever-stack.h
        (enum ResolutionMode): New.
        (ForeverStack::get): Add a private overload that takes a
        starting node as a parameter.
        (ForeverStack::resolve_path): Replace boolean parameter
        has_opening_scope_resolution with ResolutionMode parameter mode.
        * resolve/rust-forever-stack.hxx
        (ForeverStack::resolve_path): Likewise.
        (ForeverStack::get): Add a private overload that takes a
        starting node as a parameter.
        * resolve/rust-late-name-resolver-2.0.cc
        (Late::visit): Add Visibility visitor.
        * resolve/rust-late-name-resolver-2.0.h
        (Late::visit): Likewise.
        * resolve/rust-name-resolution-context.h
        (NameResolutionContext::resolve_path): Rework overloading a bit
        and accept ResolutionMode parameter.

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         |  12 +-
 gcc/rust/resolve/rust-forever-stack.hxx       | 103 +++++++++---------
 .../resolve/rust-late-name-resolver-2.0.cc    |  56 ++++++++++
 .../resolve/rust-late-name-resolver-2.0.h     |   1 +
 .../resolve/rust-name-resolution-context.h    |  93 +++++++++-------
 gcc/testsuite/rust/compile/nr2/exclude        |   2 -
 6 files changed, 174 insertions(+), 93 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 81468e5c386..3f6f002da68 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -543,6 +543,13 @@ private:
   Node root;
 };
 
+enum class ResolutionMode
+{
+  Normal,
+  FromRoot,
+  FromExtern, // extern prelude
+};
+
 template <Namespace N> class ForeverStack
 {
 public:
@@ -672,7 +679,7 @@ public:
    */
   template <typename S>
   tl::optional<Rib::Definition> resolve_path (
-    const std::vector<S> &segments, bool has_opening_scope_resolution,
+    const std::vector<S> &segments, ResolutionMode mode,
     std::function<void (const S &, NodeId)> insert_segment_resolution,
     std::vector<Error> &collect_errors);
 
@@ -739,6 +746,9 @@ private:
     tl::optional<Node &> parent; // `None` only if the node is a root
   };
 
+  // private overload which allows specifying a starting point
+  tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
+
   /* Should we keep going upon seeing a Rib? */
   enum class KeepGoing
   {
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 17136b86ffc..d568682786c 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -291,12 +291,12 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
 
 template <Namespace N>
 tl::optional<Rib::Definition>
-ForeverStack<N>::get (const Identifier &name)
+ForeverStack<N>::get (Node &start, const Identifier &name)
 {
   tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
 
   // TODO: Can we improve the API? have `reverse_iter` return an optional?
-  reverse_iter ([&resolved_definition, &name] (Node &current) {
+  reverse_iter (start, [&resolved_definition, &name] (Node &current) {
     auto candidate = current.rib.get (name.as_string ());
 
     return candidate.map_or (
@@ -318,6 +318,13 @@ ForeverStack<N>::get (const Identifier &name)
   return resolved_definition;
 }
 
+template <Namespace N>
+tl::optional<Rib::Definition>
+ForeverStack<N>::get (const Identifier &name)
+{
+  return get (cursor (), name);
+}
+
 template <Namespace N>
 tl::optional<Rib::Definition>
 ForeverStack<N>::get_lang_prelude (const Identifier &name)
@@ -625,23 +632,25 @@ template <Namespace N>
 template <typename S>
 tl::optional<Rib::Definition>
 ForeverStack<N>::resolve_path (
-  const std::vector<S> &segments, bool has_opening_scope_resolution,
+  const std::vector<S> &segments, ResolutionMode mode,
   std::function<void (const S &, NodeId)> insert_segment_resolution,
   std::vector<Error> &collect_errors)
 {
   rust_assert (!segments.empty ());
 
-  // handle paths with opening scopes
-  std::function<void (void)> cleanup_current = [] () {};
-  if (has_opening_scope_resolution)
+  std::reference_wrapper<Node> starting_point = cursor ();
+  switch (mode)
     {
-      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; };
+    case ResolutionMode::Normal:
+      break; // default
+    case ResolutionMode::FromRoot:
+      starting_point = root;
+      break;
+    case ResolutionMode::FromExtern:
+      starting_point = extern_prelude;
+      break;
+    default:
+      rust_unreachable ();
     }
 
   // if there's only one segment, we just use `get`
@@ -654,13 +663,13 @@ 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);
        }
 
       tl::optional<Rib::Definition> res
-       = get (unwrap_type_segment (segments.back ()).as_string ());
+       = get (starting_point.get (),
+              unwrap_type_segment (segments.back ()).as_string ());
 
       if (!res)
        res = get_lang_prelude (
@@ -668,45 +677,39 @@ 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, collect_errors)
+    .and_then (
+      [this, &segments, &starting_point, &insert_segment_resolution,
+       &collect_errors] (typename std::vector<S>::const_iterator iterator) {
+       return resolve_segments (starting_point.get (), segments, iterator,
+                                insert_segment_resolution, collect_errors);
+      })
+    .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);
 
-  auto res
-    = find_starting_point (segments, starting_point, insert_segment_resolution,
-                          collect_errors)
-       .and_then (
-         [this, &segments, &starting_point, &insert_segment_resolution,
-          &collect_errors] (typename std::vector<S>::const_iterator iterator) {
-           return resolve_segments (starting_point.get (), segments, iterator,
-                                    insert_segment_resolution, collect_errors);
-         })
-       .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;
+      if (res && !res->is_ambiguous ())
+       insert_segment_resolution (segments.back (), res->get_node_id ());
+
+      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 3bb364e071d..062c6f2d0b1 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -515,6 +515,62 @@ Late::visit (AST::TypePath &type)
                 Definition (resolved->get_node_id ()));
 }
 
+void
+Late::visit (AST::Visibility &vis)
+{
+  if (!vis.has_path ())
+    return;
+
+  AST::SimplePath &path = vis.get_path ();
+
+  rust_assert (path.get_segments ().size ());
+  auto &first_seg = path.get_segments ()[0];
+
+  auto mode = ResolutionMode::Normal;
+
+  if (path.has_opening_scope_resolution ())
+    {
+      if (get_rust_edition () == Edition::E2015)
+       mode = ResolutionMode::FromRoot;
+      else
+       mode = ResolutionMode::FromExtern;
+    }
+  else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
+          && !first_seg.is_lower_self_seg ())
+    {
+      if (get_rust_edition () == Edition::E2015)
+       {
+         mode = ResolutionMode::FromRoot;
+       }
+      else
+       {
+         rust_error_at (path.get_locus (),
+                        "relative paths are not supported in visibilities in "
+                        "2018 edition or later");
+         return;
+       }
+    }
+
+  auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
+
+  if (!res.has_value ())
+    {
+      rust_error_at (path.get_locus (), ErrorCode::E0433,
+                    "could not resolve path %qs", path.as_string ().c_str ());
+      return;
+    }
+
+  // TODO: is this possible?
+  if (res->is_ambiguous ())
+    {
+      rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
+                    path.as_string ().c_str ());
+      return;
+    }
+
+  ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id 
()));
+}
+
 void
 Late::visit (AST::Trait &trait)
 {
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 4b7b1b87411..5b5637d48a9 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -60,6 +60,7 @@ public:
   void visit (AST::LoopLabel &) override;
   void visit (AST::PathInExpression &) override;
   void visit (AST::TypePath &) override;
+  void visit (AST::Visibility &) override;
   void visit (AST::Trait &) override;
   void visit (AST::StructExprStruct &) override;
   void visit (AST::StructExprStructBase &) override;
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index cf87c8f1c79..1509857739e 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -280,8 +280,7 @@ public:
 
   template <typename S>
   tl::optional<Rib::Definition>
-  resolve_path (const std::vector<S> &segments,
-               bool has_opening_scope_resolution,
+  resolve_path (const std::vector<S> &segments, ResolutionMode mode,
                std::vector<Error> &collect_errors, Namespace ns)
   {
     std::function<void (const S &, NodeId)> insert_segment_resolution
@@ -293,17 +292,17 @@ public:
     switch (ns)
       {
       case Namespace::Values:
-       return values.resolve_path (segments, has_opening_scope_resolution,
-                                   insert_segment_resolution, collect_errors);
+       return values.resolve_path (segments, mode, insert_segment_resolution,
+                                   collect_errors);
       case Namespace::Types:
-       return types.resolve_path (segments, has_opening_scope_resolution,
-                                  insert_segment_resolution, collect_errors);
+       return types.resolve_path (segments, mode, insert_segment_resolution,
+                                  collect_errors);
       case Namespace::Macros:
-       return macros.resolve_path (segments, has_opening_scope_resolution,
-                                   insert_segment_resolution, collect_errors);
+       return macros.resolve_path (segments, mode, insert_segment_resolution,
+                                   collect_errors);
       case Namespace::Labels:
-       return labels.resolve_path (segments, has_opening_scope_resolution,
-                                   insert_segment_resolution, collect_errors);
+       return labels.resolve_path (segments, mode, insert_segment_resolution,
+                                   collect_errors);
       default:
        rust_unreachable ();
       }
@@ -311,8 +310,7 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<Rib::Definition>
-  resolve_path (const std::vector<S> &segments,
-               bool has_opening_scope_resolution,
+  resolve_path (const std::vector<S> &segments, ResolutionMode mode,
                tl::optional<std::vector<Error> &> collect_errors,
                Namespace ns_first, Args... ns_args)
   {
@@ -321,8 +319,7 @@ public:
     for (auto ns : namespaces)
       {
        std::vector<Error> collect_errors_inner;
-       if (auto ret = resolve_path (segments, has_opening_scope_resolution,
-                                    collect_errors_inner, ns))
+       if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))
          return ret;
        if (!collect_errors_inner.empty ())
          {
@@ -344,52 +341,68 @@ public:
     return tl::nullopt;
   }
 
-  template <typename... Args>
+  template <typename S, typename... Args>
   tl::optional<Rib::Definition>
-  resolve_path (const AST::SimplePath &path,
+  resolve_path (const std::vector<S> &path_segments,
+               bool has_opening_scope_resolution,
                tl::optional<std::vector<Error> &> collect_errors,
                Namespace ns_first, Args... ns_args)
   {
-    return resolve_path (path.get_segments (),
-                        path.has_opening_scope_resolution (), collect_errors,
-                        ns_first, ns_args...);
+    auto mode = ResolutionMode::Normal;
+    if (has_opening_scope_resolution)
+      {
+       if (get_rust_edition () == Edition::E2015)
+         mode = ResolutionMode::FromRoot;
+       else
+         mode = ResolutionMode::FromExtern;
+      }
+    return resolve_path (path_segments, mode, collect_errors, ns_first,
+                        ns_args...);
   }
 
-  template <typename... Args>
+  template <typename S, typename... Args>
   tl::optional<Rib::Definition>
-  resolve_path (const AST::PathInExpression &path,
-               tl::optional<std::vector<Error> &> collect_errors,
-               Namespace ns_first, Args... ns_args)
+  resolve_path (const std::vector<S> &path_segments,
+               bool has_opening_scope_resolution, Namespace ns_first,
+               Args... ns_args)
   {
-    return resolve_path (path.get_segments (), path.opening_scope_resolution 
(),
-                        collect_errors, ns_first, ns_args...);
+    return resolve_path (path_segments, has_opening_scope_resolution,
+                        tl::nullopt, ns_first, ns_args...);
   }
 
-  template <typename... Args>
+  template <typename S, typename... Args>
   tl::optional<Rib::Definition>
-  resolve_path (const AST::TypePath &path,
-               tl::optional<std::vector<Error> &> collect_errors,
+  resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
                Namespace ns_first, Args... ns_args)
+  {
+    return resolve_path (path_segments, mode, tl::nullopt, ns_first,
+                        ns_args...);
+  }
+
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
+                                             Args &&...args)
   {
     return resolve_path (path.get_segments (),
-                        path.has_opening_scope_resolution_op (),
-                        collect_errors, ns_first, ns_args...);
+                        path.has_opening_scope_resolution (),
+                        std::forward<Args> (args)...);
   }
 
-  template <typename P, typename... Args>
-  tl::optional<Rib::Definition> resolve_path (const P &path, Namespace 
ns_first,
-                                             Args... ns_args)
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression 
&path,
+                                             Args &&...args)
   {
-    return resolve_path (path, tl::nullopt, ns_first, ns_args...);
+    return resolve_path (path.get_segments (), path.opening_scope_resolution 
(),
+                        std::forward<Args> (args)...);
   }
 
-  template <typename P, typename... Args>
-  tl::optional<Rib::Definition>
-  resolve_path (const P &path_segments, bool has_opening_scope_resolution,
-               Namespace ns_first, Args... ns_args)
+  template <typename... Args>
+  tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+                                             Args &&...args)
   {
-    return resolve_path (path_segments, has_opening_scope_resolution,
-                        tl::nullopt, ns_first, ns_args...);
+    return resolve_path (path.get_segments (),
+                        path.has_opening_scope_resolution_op (),
+                        std::forward<Args> (args)...);
   }
 
 private:
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index d4e066a5f72..70c59f9abdd 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -1,10 +1,8 @@
 canonical_paths1.rs
 issue-3315-2.rs
-privacy5.rs
 privacy8.rs
 pub_restricted_1.rs
 pub_restricted_2.rs
-pub_restricted_3.rs
 issue-2905-2.rs
 torture/alt_patterns1.rs
 torture/name_resolve1.rs
-- 
2.49.0

Reply via email to