@@ -34,6 +34,13 @@ ForeverStack<N>::Node::is_root () const
34
34
return !parent.has_value ();
35
35
}
36
36
37
+ template <Namespace N>
38
+ bool
39
+ ForeverStack<N>::Node::is_prelude () const
40
+ {
41
+ return rib.kind == Rib::Kind::Prelude;
42
+ }
43
+
37
44
template <Namespace N>
38
45
bool
39
46
ForeverStack<N>::Node::is_leaf () const
@@ -63,6 +70,16 @@ template <Namespace N>
63
70
void
64
71
ForeverStack<N>::push_inner (Rib rib, Link link)
65
72
{
73
+ if (rib.kind == Rib::Kind::Prelude)
74
+ {
75
+ // If you push_inner into the prelude from outside the root, you will pop
76
+ // back into the root, which could screw up a traversal.
77
+ rust_assert (&cursor_reference.get () == &root);
78
+ // Prelude doesn't have an access path
79
+ rust_assert (!link .path );
80
+ update_cursor (this ->prelude );
81
+ return ;
82
+ }
66
83
// If the link does not exist, we create it and emplace a new `Node` with the
67
84
// current node as its parent. `unordered_map::emplace` returns a pair with
68
85
// the iterator and a boolean. If the value already exists, the iterator
@@ -290,6 +307,20 @@ ForeverStack<N>::get (const Identifier &name)
290
307
return resolved_definition;
291
308
}
292
309
310
+ template <Namespace N>
311
+ tl::optional<Rib::Definition>
312
+ ForeverStack<N>::get_prelude (const Identifier &name)
313
+ {
314
+ return prelude.rib .get (name.as_string ());
315
+ }
316
+
317
+ template <Namespace N>
318
+ tl::optional<Rib::Definition>
319
+ ForeverStack<N>::get_prelude (const std::string &name)
320
+ {
321
+ return prelude.rib .get (name);
322
+ }
323
+
293
324
template <>
294
325
tl::optional<Rib::Definition> inline ForeverStack<Namespace::Labels>::get (
295
326
const Identifier &name)
@@ -389,7 +420,7 @@ ForeverStack<N>::find_starting_point (
389
420
break ;
390
421
391
422
auto &seg = unwrap_type_segment (outer_seg);
392
- auto is_self_or_crate
423
+ bool is_self_or_crate
393
424
= seg.is_crate_path_seg () || seg.is_lower_self_seg ();
394
425
395
426
// if we're after the first path segment and meet `self` or `crate`, it's
@@ -452,7 +483,7 @@ ForeverStack<N>::resolve_segments (
452
483
typename std::vector<S>::const_iterator iterator,
453
484
std::function<void (const S &, NodeId)> insert_segment_resolution)
454
485
{
455
- auto *current_node = &starting_point;
486
+ Node *current_node = &starting_point;
456
487
for (; !is_last (iterator, segments); iterator++)
457
488
{
458
489
auto &outer_seg = *iterator;
@@ -468,7 +499,7 @@ ForeverStack<N>::resolve_segments (
468
499
}
469
500
470
501
auto &seg = unwrap_type_segment (outer_seg);
471
- auto str = seg.as_string ();
502
+ std::string str = seg.as_string ();
472
503
rust_debug (" [ARTHUR]: resolving segment part: %s" , str.c_str ());
473
504
474
505
// check that we don't encounter *any* leading keywords afterwards
@@ -483,10 +514,20 @@ ForeverStack<N>::resolve_segments (
483
514
* On every iteration this loop either
484
515
*
485
516
* 1. terminates
486
- * 2. decreases the depth of the node pointed to by current_node
487
517
*
488
- * This ensures termination
518
+ * 2. decreases the depth of the node pointed to by current_node until
519
+ * current_node reaches the root
520
+ *
521
+ * 3. If the root node is reached, and we were not able to resolve the
522
+ * segment, we search the prelude rib for the segment, by setting
523
+ * current_node to point to the prelude, and toggling the
524
+ * searched_prelude boolean to true. If current_node is the prelude
525
+ * rib, and searched_prelude is true, we will exit.
526
+ *
527
+ * This ensures termination.
528
+ *
489
529
*/
530
+ bool searched_prelude = false ;
490
531
while (true )
491
532
{
492
533
// may set the value of child
@@ -522,9 +563,16 @@ ForeverStack<N>::resolve_segments (
522
563
}
523
564
}
524
565
566
+ if (current_node->is_root () && !searched_prelude)
567
+ {
568
+ searched_prelude = true ;
569
+ current_node = &prelude;
570
+ continue ;
571
+ }
572
+
525
573
if (!is_start (iterator, segments)
526
574
|| current_node->rib .kind == Rib::Kind::Module
527
- || current_node->is_root ())
575
+ || current_node->is_prelude ())
528
576
{
529
577
return tl::nullopt;
530
578
}
@@ -564,7 +612,12 @@ ForeverStack<N>::resolve_path (
564
612
return Rib::Definition::NonShadowable (seg_id);
565
613
}
566
614
567
- auto res = get (unwrap_type_segment (segments.back ()).as_string ());
615
+ tl::optional<Rib::Definition> res
616
+ = get (unwrap_type_segment (segments.back ()).as_string ());
617
+
618
+ if (!res)
619
+ res = get_prelude (unwrap_type_segment (segments.back ()).as_string ());
620
+
568
621
if (res && !res->is_ambiguous ())
569
622
insert_segment_resolution (segments.back (), res->get_node_id ());
570
623
return res;
@@ -579,16 +632,25 @@ ForeverStack<N>::resolve_path (
579
632
return resolve_segments (starting_point.get (), segments, iterator,
580
633
insert_segment_resolution);
581
634
})
582
- .and_then ([&segments, &insert_segment_resolution] (
635
+ .and_then ([this , &segments, &insert_segment_resolution] (
583
636
Node final_node) -> tl::optional<Rib::Definition> {
584
637
// leave resolution within impl blocks to type checker
585
638
if (final_node.rib .kind == Rib::Kind::TraitOrImpl)
586
639
return tl::nullopt;
640
+
641
+ std::string seg_name
642
+ = unwrap_type_segment (segments.back ()).as_string ();
643
+
587
644
// assuming this can't be a lang item segment
588
- auto res = final_node.rib .get (
589
- unwrap_type_segment (segments.back ()).as_string ());
645
+ tl::optional<Rib::Definition> res = final_node.rib .get (seg_name);
646
+
647
+ // Ok we didn't find it in the rib, Lets try the prelude...
648
+ if (!res)
649
+ res = get_prelude (seg_name);
650
+
590
651
if (res && !res->is_ambiguous ())
591
652
insert_segment_resolution (segments.back (), res->get_node_id ());
653
+
592
654
return res;
593
655
});
594
656
}
0 commit comments