aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve/rust-forever-stack.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/resolve/rust-forever-stack.hxx')
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx79
1 files changed, 49 insertions, 30 deletions
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 885f282..993e2d4 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>