From: Owen Avery <[email protected]>
gcc/rust/ChangeLog:
* resolve/rust-early-name-resolver-2.0.cc
(Early::build_import_mapping): Avoid outputting an "unresolved
import" error if other errors are outputted during resolution.
* resolve/rust-early-name-resolver-2.0.h
(Early::resolve_path_in_all_ns): Collect path resolution errors
while avoiding duplicate errors for resolutions in each
namespace.
* resolve/rust-forever-stack.h
(ForeverStack::resolve_path): Add parameter for collecting
errors.
(ForeverStack::find_starting_point): Likewise.
(ForeverStack::resolve_segments): Likewise.
* resolve/rust-forever-stack.hxx
(check_leading_kw_at_start): Likewise.
(ForeverStack::find_starting_point): Likewise.
(ForeverStack::resolve_segments): Likewise.
(ForeverStack::resolve_path): Likewise.
* resolve/rust-name-resolution-context.h
(NameResolutionContext::resolve_path): Add optional parameter
for collecting errors.
gcc/testsuite/ChangeLog:
* rust/compile/nr2/exclude: Remove entry.
Signed-off-by: Owen Avery <[email protected]>
---
.../resolve/rust-early-name-resolver-2.0.cc | 6 +-
.../resolve/rust-early-name-resolver-2.0.h | 16 +++-
gcc/rust/resolve/rust-forever-stack.h | 9 +-
gcc/rust/resolve/rust-forever-stack.hxx | 45 ++++++----
.../resolve/rust-name-resolution-context.h | 87 ++++++++++++++-----
gcc/testsuite/rust/compile/nr2/exclude | 1 -
6 files changed, 115 insertions(+), 49 deletions(-)
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 36456e10ff2..7d048ea8289 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -141,6 +141,10 @@ Early::build_import_mapping (
// be moved into the newly created import mappings
auto path = import.to_resolve;
+ // used to skip the "unresolved import" error
+ // if we output other errors during resolution
+ size_t old_error_count = macro_resolve_errors.size ();
+
switch (import.kind)
{
case TopLevel::ImportKind::Kind::Glob:
@@ -154,7 +158,7 @@ Early::build_import_mapping (
break;
}
- if (!found)
+ if (!found && old_error_count == macro_resolve_errors.size ())
collect_error (Error (path.get_final_segment ().get_locus (),
ErrorCode::E0433, "unresolved import %qs",
path.as_string ().c_str ()));
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index c4226fe9ea8..e78bec0199a 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -218,7 +218,6 @@ private:
std::vector<std::pair<Rib::Definition, Namespace>>
resolve_path_in_all_ns (const P &path)
{
- const auto &segments = path.get_segments ();
std::vector<std::pair<Rib::Definition, Namespace>> resolved;
// Pair a definition with the namespace it was found in
@@ -229,13 +228,22 @@ private:
};
};
- ctx.resolve_path (segments, Namespace::Values)
+ std::vector<Error> value_errors;
+ std::vector<Error> type_errors;
+ std::vector<Error> macro_errors;
+
+ ctx.resolve_path (path, value_errors, Namespace::Values)
.map (pair_with_ns (Namespace::Values));
- ctx.resolve_path (segments, Namespace::Types)
+ ctx.resolve_path (path, type_errors, Namespace::Types)
.map (pair_with_ns (Namespace::Types));
- ctx.resolve_path (segments, Namespace::Macros)
+ ctx.resolve_path (path, macro_errors, Namespace::Macros)
.map (pair_with_ns (Namespace::Macros));
+ if (!value_errors.empty () && !type_errors.empty ()
+ && !macro_errors.empty ())
+ for (auto &ent : value_errors)
+ collect_error (std::move (ent));
+
return resolved;
}
diff --git a/gcc/rust/resolve/rust-forever-stack.h
b/gcc/rust/resolve/rust-forever-stack.h
index cf0265140de..75d8c1d9b59 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -673,7 +673,8 @@ public:
template <typename S>
tl::optional<Rib::Definition> resolve_path (
const std::vector<S> &segments, bool has_opening_scope_resolution,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ 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;
@@ -792,13 +793,15 @@ private:
tl::optional<SegIterator<S>> find_starting_point (
const std::vector<S> &segments,
std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
template <typename S>
tl::optional<Node &> resolve_segments (
Node &starting_point, const std::vector<S> &segments,
SegIterator<S> iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,
std::string &seg_name,
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx
b/gcc/rust/resolve/rust-forever-stack.hxx
index 31a33016f09..069111eeb0e 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -398,12 +398,14 @@ ForeverStack<N>::find_closest_module (Node
&starting_point)
* segments */
template <typename S>
static inline bool
-check_leading_kw_at_start (const S &segment, bool condition)
+check_leading_kw_at_start (std::vector<Error> &collect_errors, const S
&segment,
+ bool condition)
{
if (condition)
- rust_error_at (segment.get_locus (), ErrorCode::E0433,
- "%qs in paths can only be used in start position",
- segment.as_string ().c_str ());
+ collect_errors.emplace_back (
+ segment.get_locus (), ErrorCode::E0433,
+ "%qs in paths can only be used in start position",
+ segment.as_string ().c_str ());
return condition;
}
@@ -418,7 +420,8 @@ template <typename S>
tl::optional<typename std::vector<S>::const_iterator>
ForeverStack<N>::find_starting_point (
const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
auto iterator = segments.begin ();
@@ -435,8 +438,9 @@ ForeverStack<N>::find_starting_point (
// if we're after the first path segment and meet `self` or `crate`, it's
// an error - we should only be seeing `super` keywords at this point
- if (check_leading_kw_at_start (seg, !is_start (iterator, segments)
- && is_self_or_crate))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ !is_start (iterator, segments)
+ && is_self_or_crate))
return tl::nullopt;
if (seg.is_crate_path_seg ())
@@ -459,8 +463,9 @@ ForeverStack<N>::find_starting_point (
starting_point = find_closest_module (starting_point);
if (starting_point.get ().is_root ())
{
- rust_error_at (seg.get_locus (), ErrorCode::E0433,
- "too many leading %<super%> keywords");
+ collect_errors.emplace_back (
+ seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
return tl::nullopt;
}
@@ -486,7 +491,8 @@ tl::optional<typename ForeverStack<N>::Node &>
ForeverStack<N>::resolve_segments (
Node &starting_point, const std::vector<S> &segments,
typename std::vector<S>::const_iterator iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
Node *current_node = &starting_point;
for (; !is_last (iterator, segments); iterator++)
@@ -508,9 +514,10 @@ ForeverStack<N>::resolve_segments (
rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ());
// check that we don't encounter *any* leading keywords afterwards
- if (check_leading_kw_at_start (seg, seg.is_crate_path_seg ()
- || seg.is_super_path_seg ()
- || seg.is_lower_self_seg ()))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ seg.is_crate_path_seg ()
+ || seg.is_super_path_seg ()
+ || seg.is_lower_self_seg ()))
return tl::nullopt;
tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt;
@@ -619,7 +626,8 @@ template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
const std::vector<S> &segments, bool has_opening_scope_resolution,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
// TODO: What to do if segments.empty() ?
@@ -667,12 +675,13 @@ ForeverStack<N>::resolve_path (
std::reference_wrapper<Node> starting_point = cursor ();
auto res
- = find_starting_point (segments, starting_point, insert_segment_resolution)
+ = find_starting_point (segments, starting_point, insert_segment_resolution,
+ collect_errors)
.and_then (
- [this, &segments, &starting_point, &insert_segment_resolution] (
- typename std::vector<S>::const_iterator iterator) {
+ [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);
+ insert_segment_resolution, collect_errors);
})
.and_then ([this, &segments, &insert_segment_resolution] (
Node &final_node) -> tl::optional<Rib::Definition> {
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h
b/gcc/rust/resolve/rust-name-resolution-context.h
index 84c0800ac4a..51c08efe3df 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -220,9 +220,10 @@ public:
tl::optional<NodeId> lookup (NodeId usage) const;
template <typename S>
- tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
- Namespace ns)
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &segments,
+ bool has_opening_scope_resolution,
+ std::vector<Error> &collect_errors, Namespace ns)
{
std::function<void (const S &, NodeId)> insert_segment_resolution
= [this] (const S &seg, NodeId id) {
@@ -234,60 +235,102 @@ public:
{
case Namespace::Values:
return values.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution);
+ insert_segment_resolution, collect_errors);
case Namespace::Types:
return types.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution);
+ insert_segment_resolution, collect_errors);
case Namespace::Macros:
return macros.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution);
+ insert_segment_resolution, collect_errors);
case Namespace::Labels:
return labels.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution);
+ insert_segment_resolution, collect_errors);
default:
rust_unreachable ();
}
}
template <typename S, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &segments,
+ bool has_opening_scope_resolution,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
- std::initializer_list<Namespace> namespaces = {ns_args...};
+ std::initializer_list<Namespace> namespaces = {ns_first, ns_args...};
for (auto ns : namespaces)
{
- if (auto ret
- = resolve_path (segments, has_opening_scope_resolution, ns))
+ std::vector<Error> collect_errors_inner;
+ if (auto ret = resolve_path (segments, has_opening_scope_resolution,
+ collect_errors_inner, ns))
return ret;
+ if (!collect_errors_inner.empty ())
+ {
+ if (collect_errors.has_value ())
+ {
+ std::move (collect_errors_inner.begin (),
+ collect_errors_inner.end (),
+ std::back_inserter (collect_errors.value ()));
+ }
+ else
+ {
+ for (auto &e : collect_errors_inner)
+ e.emit ();
+ }
+ return tl::nullopt;
+ }
}
return tl::nullopt;
}
template <typename... Args>
- tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::SimplePath &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution (), ns_args...);
+ path.has_opening_scope_resolution (), collect_errors,
+ ns_first, ns_args...);
}
template <typename... Args>
- tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression
&path,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::PathInExpression &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
return resolve_path (path.get_segments (), path.opening_scope_resolution
(),
- ns_args...);
+ collect_errors, ns_first, ns_args...);
}
template <typename... Args>
- tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::TypePath &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution_op (), ns_args...);
+ path.has_opening_scope_resolution_op (),
+ collect_errors, ns_first, ns_args...);
+ }
+
+ template <typename P, typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const P &path, Namespace
ns_first,
+ Args... ns_args)
+ {
+ return resolve_path (path, tl::nullopt, ns_first, ns_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)
+ {
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
}
private:
diff --git a/gcc/testsuite/rust/compile/nr2/exclude
b/gcc/testsuite/rust/compile/nr2/exclude
index f94cbe46679..d3efe08a531 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -17,7 +17,6 @@ derive-default1.rs
derive-eq-invalid.rs
torture/alt_patterns1.rs
torture/name_resolve1.rs
-issue-3568.rs
issue-3663.rs
issue-3671.rs
issue-3652.rs
--
2.49.0