// 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:
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 ()));
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
};
};
- 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;
}
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;
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,
* 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;
}
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 ();
// 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 ())
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;
}
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++)
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;
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() ?
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> {
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) {
{
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:
derive-eq-invalid.rs
torture/alt_patterns1.rs
torture/name_resolve1.rs
-issue-3568.rs
issue-3663.rs
issue-3671.rs
issue-3652.rs