@@ -291,12 +291,12 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
291
291
292
292
template <Namespace N>
293
293
tl::optional<Rib::Definition>
294
- ForeverStack<N>::get (const Identifier &name)
294
+ ForeverStack<N>::get (Node &start, const Identifier &name)
295
295
{
296
296
tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
297
297
298
298
// TODO: Can we improve the API? have `reverse_iter` return an optional?
299
- reverse_iter ([&resolved_definition, &name] (Node ¤t) {
299
+ reverse_iter (start, [&resolved_definition, &name] (Node ¤t) {
300
300
auto candidate = current.rib .get (name.as_string ());
301
301
302
302
return candidate.map_or (
@@ -318,6 +318,13 @@ ForeverStack<N>::get (const Identifier &name)
318
318
return resolved_definition;
319
319
}
320
320
321
+ template <Namespace N>
322
+ tl::optional<Rib::Definition>
323
+ ForeverStack<N>::get (const Identifier &name)
324
+ {
325
+ return get (cursor (), name);
326
+ }
327
+
321
328
template <Namespace N>
322
329
tl::optional<Rib::Definition>
323
330
ForeverStack<N>::get_lang_prelude (const Identifier &name)
@@ -625,23 +632,25 @@ template <Namespace N>
625
632
template <typename S>
626
633
tl::optional<Rib::Definition>
627
634
ForeverStack<N>::resolve_path (
628
- const std::vector<S> &segments, bool has_opening_scope_resolution ,
635
+ const std::vector<S> &segments, ResolutionMode mode ,
629
636
std::function<void (const S &, NodeId)> insert_segment_resolution,
630
637
std::vector<Error> &collect_errors)
631
638
{
632
639
rust_assert (!segments.empty ());
633
640
634
- // handle paths with opening scopes
635
- std::function<void (void )> cleanup_current = [] () {};
636
- if (has_opening_scope_resolution)
641
+ std::reference_wrapper<Node> starting_point = cursor ();
642
+ switch (mode)
637
643
{
638
- Node *last_current = &cursor_reference.get ();
639
- if (get_rust_edition () == Edition::E2015 )
640
- cursor_reference = root;
641
- else
642
- cursor_reference = extern_prelude;
643
- cleanup_current
644
- = [this , last_current] () { cursor_reference = *last_current; };
644
+ case ResolutionMode::Normal:
645
+ break ; // default
646
+ case ResolutionMode::FromRoot:
647
+ starting_point = root;
648
+ break ;
649
+ case ResolutionMode::FromExtern:
650
+ starting_point = extern_prelude;
651
+ break ;
652
+ default :
653
+ rust_unreachable ();
645
654
}
646
655
647
656
// if there's only one segment, we just use `get`
@@ -654,59 +663,53 @@ ForeverStack<N>::resolve_path (
654
663
lang_item.value ());
655
664
656
665
insert_segment_resolution (seg, seg_id);
657
- cleanup_current ();
658
666
// TODO: does NonShadowable matter?
659
667
return Rib::Definition::NonShadowable (seg_id);
660
668
}
661
669
662
670
tl::optional<Rib::Definition> res
663
- = get (unwrap_type_segment (segments.back ()).as_string ());
671
+ = get (starting_point.get (),
672
+ unwrap_type_segment (segments.back ()).as_string ());
664
673
665
674
if (!res)
666
675
res = get_lang_prelude (
667
676
unwrap_type_segment (segments.back ()).as_string ());
668
677
669
678
if (res && !res->is_ambiguous ())
670
679
insert_segment_resolution (segments.back (), res->get_node_id ());
671
- cleanup_current ();
672
680
return res;
673
681
}
674
682
675
- std::reference_wrapper<Node> starting_point = cursor ();
683
+ return find_starting_point (segments, starting_point,
684
+ insert_segment_resolution, collect_errors)
685
+ .and_then (
686
+ [this , &segments, &starting_point, &insert_segment_resolution,
687
+ &collect_errors] (typename std::vector<S>::const_iterator iterator) {
688
+ return resolve_segments (starting_point.get (), segments, iterator,
689
+ insert_segment_resolution, collect_errors);
690
+ })
691
+ .and_then ([this , &segments, &insert_segment_resolution] (
692
+ Node &final_node) -> tl::optional<Rib::Definition> {
693
+ // leave resolution within impl blocks to type checker
694
+ if (final_node.rib .kind == Rib::Kind::TraitOrImpl)
695
+ return tl::nullopt;
696
+
697
+ auto &seg = unwrap_type_segment (segments.back ());
698
+ std::string seg_name = seg.as_string ();
699
+
700
+ // assuming this can't be a lang item segment
701
+ tl::optional<Rib::Definition> res
702
+ = resolve_final_segment (final_node, seg_name,
703
+ seg.is_lower_self_seg ());
704
+ // Ok we didn't find it in the rib, Lets try the prelude...
705
+ if (!res)
706
+ res = get_lang_prelude (seg_name);
676
707
677
- auto res
678
- = find_starting_point (segments, starting_point, insert_segment_resolution,
679
- collect_errors)
680
- .and_then (
681
- [this , &segments, &starting_point, &insert_segment_resolution,
682
- &collect_errors] (typename std::vector<S>::const_iterator iterator) {
683
- return resolve_segments (starting_point.get (), segments, iterator,
684
- insert_segment_resolution, collect_errors);
685
- })
686
- .and_then ([this , &segments, &insert_segment_resolution] (
687
- Node &final_node) -> tl::optional<Rib::Definition> {
688
- // leave resolution within impl blocks to type checker
689
- if (final_node.rib .kind == Rib::Kind::TraitOrImpl)
690
- return tl::nullopt;
691
-
692
- auto &seg = unwrap_type_segment (segments.back ());
693
- std::string seg_name = seg.as_string ();
694
-
695
- // assuming this can't be a lang item segment
696
- tl::optional<Rib::Definition> res
697
- = resolve_final_segment (final_node, seg_name,
698
- seg.is_lower_self_seg ());
699
- // Ok we didn't find it in the rib, Lets try the prelude...
700
- if (!res)
701
- res = get_lang_prelude (seg_name);
702
-
703
- if (res && !res->is_ambiguous ())
704
- insert_segment_resolution (segments.back (), res->get_node_id ());
705
-
706
- return res;
707
- });
708
- cleanup_current ();
709
- return res;
708
+ if (res && !res->is_ambiguous ())
709
+ insert_segment_resolution (segments.back (), res->get_node_id ());
710
+
711
+ return res;
712
+ });
710
713
}
711
714
712
715
template <Namespace N>
0 commit comments