From: Owen Avery <[email protected]>
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 <[email protected]>
---
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 ¤t) {
+ reverse_iter (start, [&resolved_definition, &name] (Node ¤t) {
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