@@ -291,12 +291,12 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
291291
292292template <Namespace N>
293293tl::optional<Rib::Definition>
294- ForeverStack<N>::get (const Identifier &name)
294+ ForeverStack<N>::get (Node &start, const Identifier &name)
295295{
296296 tl::optional<Rib::Definition> resolved_definition = tl::nullopt ;
297297
298298 // 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) {
300300 auto candidate = current.rib .get (name.as_string ());
301301
302302 return candidate.map_or (
@@ -318,6 +318,13 @@ ForeverStack<N>::get (const Identifier &name)
318318 return resolved_definition;
319319}
320320
321+ template <Namespace N>
322+ tl::optional<Rib::Definition>
323+ ForeverStack<N>::get (const Identifier &name)
324+ {
325+ return get (cursor (), name);
326+ }
327+
321328template <Namespace N>
322329tl::optional<Rib::Definition>
323330ForeverStack<N>::get_lang_prelude (const Identifier &name)
@@ -625,23 +632,25 @@ template <Namespace N>
625632template <typename S>
626633tl::optional<Rib::Definition>
627634ForeverStack<N>::resolve_path (
628- const std::vector<S> &segments, bool has_opening_scope_resolution ,
635+ const std::vector<S> &segments, ResolutionMode mode ,
629636 std::function<void (const S &, NodeId)> insert_segment_resolution,
630637 std::vector<Error> &collect_errors)
631638{
632639 rust_assert (!segments.empty ());
633640
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)
637643 {
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 ();
645654 }
646655
647656 // if there's only one segment, we just use `get`
@@ -654,59 +663,53 @@ ForeverStack<N>::resolve_path (
654663 lang_item.value ());
655664
656665 insert_segment_resolution (seg, seg_id);
657- cleanup_current ();
658666 // TODO: does NonShadowable matter?
659667 return Rib::Definition::NonShadowable (seg_id);
660668 }
661669
662670 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 ());
664673
665674 if (!res)
666675 res = get_lang_prelude (
667676 unwrap_type_segment (segments.back ()).as_string ());
668677
669678 if (res && !res->is_ambiguous ())
670679 insert_segment_resolution (segments.back (), res->get_node_id ());
671- cleanup_current ();
672680 return res;
673681 }
674682
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);
676707
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+ });
710713}
711714
712715template <Namespace N>
0 commit comments