Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #ifndef RUST_FOREVER_STACK_H
20 : #define RUST_FOREVER_STACK_H
21 :
22 : #include "rust-system.h"
23 : #include "rust-rib.h"
24 : #include "rust-ast.h"
25 : #include "rust-path.h"
26 : #include "optional.h"
27 : #include "expected.h"
28 :
29 : namespace Rust {
30 : namespace Resolver2_0 {
31 :
32 : /**
33 :
34 : Let's look at our stack for resolving and traversing the following Rust code:
35 :
36 : ```rust
37 : mod foo {
38 : mod bar {
39 : fn outer() {
40 : fn inner() {}
41 : }
42 :
43 : fn another() {}
44 : }
45 : }
46 : ```
47 :
48 : We start by creating the stack, which contains only one rib - the crate's. We
49 : won't look in details on how different namespaces end up with different stacks,
50 : and will only consider the "value" namespace for this example. Modules do not
51 : get added to the value namespace, but functions do:
52 :
53 : ```rust
54 : let _ = foo; // foo is a module, invalid Rust code
55 : let _ = outer; // outer is a function, ok!
56 : ```
57 :
58 : So passing each module will create a new Rib, but not add that module's node to
59 : the Rib.
60 :
61 : The current cursor of the stack will be denoted with `-->`: an arrow pointing to
62 : the current rib.
63 :
64 : When we start the `TopLevel` pass on the crate we are compiling, we only see the
65 : top rib, which is empty at first:
66 :
67 : ┌───────────────┐
68 : │ │
69 : --> │ │
70 : │ │
71 : └───────────────┘
72 :
73 : We pass through our first module, and emplace another Rib: Another "scope" is
74 : created, and it impacts name resolution rules.
75 :
76 : ┌───────────────┐
77 : │ │
78 : │ │
79 : │ │
80 : └───────┬───────┘
81 : │
82 : foo │
83 : │
84 : ▼
85 : ┌───────────────┐
86 : │ │
87 : --> │ │
88 : │ │
89 : └───────────────┘
90 :
91 : Notice that we have moved the cursor to the newly-created Rib, and that we have
92 : added a path between the two ribs - this is a `Link`. A link contains
93 : information such as the scope's NodeId, as well as an optional path - present
94 : only when the scope is named. This allows us to easily fetch AST nodes based on
95 : their canonical path, or build a canonical path from a NodeId. It also makes it
96 : really easy to do complex path name resolution, such as `super::super::<item>`.
97 : As mentioned earlier, modules are not present in the value namespace, so our new
98 : rib is also empty. Let's pass through the second module:
99 :
100 : ┌───────────────┐
101 : │ │
102 : │ │
103 : │ │
104 : └───────┬───────┘
105 : │
106 : foo │
107 : │
108 : ▼
109 : ┌───────────────┐
110 : │ │
111 : │ │
112 : │ │
113 : └───────┬───────┘
114 : │
115 : bar │
116 : │
117 : ▼
118 : ┌───────────────┐
119 : │ │
120 : --> │ │
121 : │ │
122 : └───────────────┘
123 :
124 : Once again, the new rib is empty, and we have a link with a path. We now go
125 : through each item in the `bar` module and visit them. The first item is a
126 : function, `outer` - upon being visited, it adds itself to the current rib.
127 :
128 : ┌───────────────┐
129 : │ │
130 : │ │
131 : │ │
132 : └───────┬───────┘
133 : │
134 : foo │
135 : │
136 : ▼
137 : ┌───────────────┐
138 : │ │
139 : │ │
140 : │ │
141 : └───────┬───────┘
142 : │
143 : bar │
144 : │
145 : ▼
146 : ┌───────────────┐
147 : │outer │
148 : --> │ │
149 : │ │
150 : └───────────────┘
151 :
152 : We now visit `outer`'s definition. This creates a new Rib, as functions can have
153 : arguments, whose declaration only lives for the function's scope.
154 :
155 : ┌───────────────┐
156 : │ │
157 : │ │
158 : │ │
159 : └───────┬───────┘
160 : │
161 : foo │
162 : │
163 : ▼
164 : ┌───────────────┐
165 : │ │
166 : │ │
167 : │ │
168 : └───────┬───────┘
169 : │
170 : bar │
171 : │
172 : ▼
173 : ┌───────────────┐
174 : │outer │
175 : │ │
176 : │ │
177 : └───────┬───────┘
178 : │
179 : <anon> │
180 : │
181 : ▼
182 : ┌───────────────┐
183 : │ │
184 : --> │ │
185 : │ │
186 : └───────────────┘
187 :
188 : This rib is anonymous (the link to it does not have a path), because we cannot
189 : refer to a function's inner items from the outside:
190 :
191 : ```rust
192 : pub mod a {
193 : pub fn foo() {}
194 : }
195 :
196 : pub fn b() {
197 : pub fn foo() {}
198 : }
199 :
200 : fn main() {
201 : a::foo(); // ok
202 : b::foo(); // ko!
203 : }
204 : ```
205 :
206 : We visit the function's block, which contain a single declaration, a function
207 : named `inner`. It adds itself to the current rib.
208 :
209 : ┌───────────────┐
210 : │ │
211 : │ │
212 : │ │
213 : └───────┬───────┘
214 : │
215 : foo │
216 : │
217 : ▼
218 : ┌───────────────┐
219 : │ │
220 : │ │
221 : │ │
222 : └───────┬───────┘
223 : │
224 : bar │
225 : │
226 : ▼
227 : ┌───────────────┐
228 : │outer │
229 : │ │
230 : │ │
231 : └───────┬───────┘
232 : │
233 : <anon> │
234 : │
235 : ▼
236 : ┌───────────────┐
237 : │inner │
238 : --> │ │
239 : │ │
240 : └───────────────┘
241 :
242 : We visit `inner`, which yields a rib but no other declaration.
243 :
244 : ┌───────────────┐
245 : │ │
246 : │ │
247 : │ │
248 : └───────┬───────┘
249 : │
250 : foo │
251 : │
252 : ▼
253 : ┌───────────────┐
254 : │ │
255 : │ │
256 : │ │
257 : └───────┬───────┘
258 : │
259 : bar │
260 : │
261 : ▼
262 : ┌───────────────┐
263 : │outer │
264 : │ │
265 : │ │
266 : └───────┬───────┘
267 : │
268 : <anon> │
269 : │
270 : ▼
271 : ┌───────────────┐
272 : │inner │
273 : │ │
274 : │ │
275 : └───────────────┘
276 : │
277 : <anon> │
278 : │
279 : ▼
280 : ┌───────────────┐
281 : │ │
282 : --> │ │
283 : │ │
284 : └───────────────┘
285 :
286 : We are now at the end of the `inner` function, and we want to pop the current
287 : scope. Instead of deleting the current rib, we simply move the cursor backwards.
288 : This allows us to keep track of the existing information and access it in later
289 : name resolution passes. We then finish visiting `outer`, then go back to our
290 : `bar` module. This is what our stack looks like after this. Note how the only
291 : difference is the cursor's location.
292 :
293 : ┌───────────────┐
294 : │ │
295 : │ │
296 : │ │
297 : └───────┬───────┘
298 : │
299 : foo │
300 : │
301 : ▼
302 : ┌───────────────┐
303 : │ │
304 : │ │
305 : │ │
306 : └───────┬───────┘
307 : │
308 : bar │
309 : │
310 : ▼
311 : ┌───────────────┐
312 : │outer │
313 : --> │ │
314 : │ │
315 : └───────┬───────┘
316 : │
317 : <anon> │
318 : │
319 : ▼
320 : ┌───────────────┐
321 : │inner │
322 : │ │
323 : │ │
324 : └───────────────┘
325 : │
326 : <anon> │
327 : │
328 : ▼
329 : ┌───────────────┐
330 : │ │
331 : │ │
332 : │ │
333 : └───────────────┘
334 :
335 : We then visit the remaining `bar` items, which are composed of the `another`
336 : function. It adds itself to the current rib. This function contains no
337 : declarations, but it still creates a Rib upon being visited. We then finish our
338 : visit of `bar`, which marks the end of our visit of `foo`, which marks the end
339 : of our `TopLevel` name resolution pass.
340 :
341 : ┌───────────────┐
342 : │ │
343 : --> │ │
344 : │ │
345 : └───────┬───────┘
346 : │
347 : foo │
348 : │
349 : ▼
350 : ┌───────────────┐
351 : │ │
352 : │ │
353 : │ │
354 : └───────┬───────┘
355 : │
356 : bar │
357 : │
358 : ▼
359 : ┌───────────────┐
360 : │outer │
361 : │another │
362 : │ │
363 : └───────┬──┬────┘
364 : │ │ <anon>
365 : <anon> │ └────────────────────┐
366 : │ │
367 : ▼ ▼
368 : ┌───────────────┐ ┌───────────────┐
369 : │inner │ │ │
370 : │ │ │ │
371 : │ │ │ │
372 : └───────┬───────┘ └───────────────┘
373 : │
374 : <anon> │
375 : │
376 : ▼
377 : ┌───────────────┐
378 : │ │
379 : │ │
380 : │ │
381 : └───────────────┘
382 :
383 : We now have a stack with a lot of ribs, prime for the `Early` and `Late` name
384 : resolution passes. We will revisit the ribs we created in these passes, and we
385 : won't need to allocate or create new ones: because they will still be present in
386 : the stack, we will simply move our cursor to these ribs. In this case, there is
387 : nothing to do, since there are no uses of our definitions, as the Rust code we
388 : are name-resolving is not really interesting. You'll also note that our
389 : `TopLevel` pass did not resolve a whole lot: all it did was create new ribs, and
390 : empty ones at that. The `Early` pass will not go further, since our code does
391 : not contain any imports, macro definitions or macro invocations. You can look at
392 : this pass's documentation for more details on this resolution process.
393 :
394 : **/
395 :
396 : /**
397 : * Intended for use by ForeverStack to store Nodes
398 : * Unlike ForeverStack, does not store a cursor reference
399 : * Intended to make path resolution in multiple namespaces simpler
400 : **/
401 : class ForeverStackStore
402 : {
403 : public:
404 : ForeverStackStore (NodeId crate_id) : root (Rib::Kind::Normal, crate_id)
405 : {
406 : rust_assert (root.is_root ());
407 : rust_assert (root.is_leaf ());
408 : }
409 :
410 : private:
411 : /**
412 : * A link between two Nodes in our trie data structure. This class represents
413 : * the edges of the graph
414 : */
415 0 : class Link
416 : {
417 : public:
418 0 : Link (NodeId id, tl::optional<Identifier> path) : id (id), path (path) {}
419 :
420 0 : bool compare (const Link &other) const { return id < other.id; }
421 :
422 : NodeId id;
423 : tl::optional<Identifier> path;
424 : };
425 :
426 : /* Link comparison class, which we use in a Node's `children` map */
427 : class LinkCmp
428 : {
429 : public:
430 0 : bool operator() (const Link &lhs, const Link &rhs) const
431 : {
432 0 : return lhs.compare (rhs);
433 : }
434 : };
435 :
436 : public:
437 : class Node;
438 :
439 : struct DfsResult
440 : {
441 : Node &first;
442 : std::string second;
443 : };
444 :
445 : struct ConstDfsResult
446 : {
447 : const Node &first;
448 : std::string second;
449 : };
450 :
451 : /* Should we keep going upon seeing a Rib? */
452 : enum class KeepGoing
453 : {
454 : Yes,
455 : No,
456 : };
457 :
458 : class Node
459 : {
460 : private:
461 : friend class ForeverStackStore::ForeverStackStore;
462 :
463 0 : Node (Rib::Kind rib_kind, NodeId id, tl::optional<Node &> parent)
464 0 : : value_rib (rib_kind), type_rib (rib_kind), label_rib (rib_kind),
465 0 : macro_rib (rib_kind), id (id), parent (parent)
466 0 : {}
467 : Node (Rib::Kind rib_kind, NodeId id) : Node (rib_kind, id, tl::nullopt) {}
468 0 : Node (Rib::Kind rib_kind, NodeId id, Node &parent)
469 0 : : Node (rib_kind, id, tl::optional<Node &> (parent))
470 : {}
471 :
472 : public:
473 : Node (const Node &) = default;
474 0 : Node (Node &&) = default;
475 : Node &operator= (const Node &) = delete;
476 : Node &operator= (Node &&) = default;
477 :
478 : bool is_root () const;
479 : bool is_leaf () const;
480 :
481 : NodeId get_id () const;
482 :
483 : Node &insert_child (NodeId id, tl::optional<Identifier> path,
484 : Rib::Kind kind);
485 :
486 : tl::optional<Node &> get_child (const Identifier &path);
487 : tl::optional<const Node &> get_child (const Identifier &path) const;
488 :
489 : tl::optional<Node &> get_parent ();
490 : tl::optional<const Node &> get_parent () const;
491 :
492 : // finds the identifier, if any, used to link
493 : // this node's parent to this node
494 : tl::optional<const Identifier &> get_parent_path () const;
495 :
496 : Rib &get_rib (Namespace ns);
497 : const Rib &get_rib (Namespace ns) const;
498 :
499 : tl::expected<NodeId, DuplicateNameError> insert (const Identifier &name,
500 : NodeId node, Namespace ns);
501 : tl::expected<NodeId, DuplicateNameError>
502 : insert_shadowable (const Identifier &name, NodeId node, Namespace ns);
503 : tl::expected<NodeId, DuplicateNameError>
504 : insert_globbed (const Identifier &name, NodeId node, Namespace ns);
505 :
506 : void reverse_iter (std::function<KeepGoing (Node &)> lambda);
507 : void reverse_iter (std::function<KeepGoing (const Node &)> lambda) const;
508 :
509 : void child_iter (std::function<KeepGoing (
510 : NodeId, tl::optional<const Identifier &>, Node &)>
511 : lambda);
512 : void child_iter (std::function<KeepGoing (
513 : NodeId, tl::optional<const Identifier &>, const Node &)>
514 : lambda) const;
515 :
516 : Node &find_closest_module ();
517 : const Node &find_closest_module () const;
518 :
519 : tl::optional<Node &> dfs_node (NodeId to_find);
520 : tl::optional<const Node &> dfs_node (NodeId to_find) const;
521 :
522 : private:
523 : // per-namespace ribs
524 : Rib value_rib;
525 : Rib type_rib;
526 : Rib label_rib;
527 : Rib macro_rib;
528 : // all linked nodes
529 : std::map<Link, Node, LinkCmp> children;
530 :
531 : NodeId id; // The node id of the Node's scope
532 :
533 : tl::optional<Node &> parent; // `None` only if the node is a root
534 : };
535 :
536 : Node &get_root ();
537 : const Node &get_root () const;
538 :
539 : tl::optional<Node &> get_node (NodeId node_id);
540 : tl::optional<const Node &> get_node (NodeId node_id) const;
541 :
542 : private:
543 : Node root;
544 : };
545 :
546 : enum class ResolutionMode
547 : {
548 : Normal,
549 : FromRoot,
550 : FromExtern, // extern prelude
551 : };
552 :
553 : template <Namespace N> class ForeverStack
554 : {
555 : public:
556 18040 : ForeverStack ()
557 18040 : : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
558 36080 : lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
559 18040 : extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)),
560 18040 : cursor_reference (root)
561 : {
562 18040 : rust_assert (root.is_root ());
563 18040 : rust_assert (root.is_leaf ());
564 :
565 : // TODO: Should we be using the forever stack root as the crate scope?
566 : // TODO: Is this how we should be getting the crate node id?
567 18040 : auto &mappings = Analysis::Mappings::get ();
568 18040 : root.id = *mappings.crate_num_to_nodeid (mappings.get_current_crate ());
569 18040 : }
570 :
571 : /**
572 : * Add a new Rib to the stack. If the Rib already exists, nothing is pushed
573 : * and the stack's cursor is simply moved to this existing Rib.
574 : *
575 : * @param rib The Rib to push
576 : * @param id The NodeId of the node for which the Rib was created. For
577 : * example, if a Rib is created because a lexical scope is entered,
578 : * then `id` is that `BlockExpr`'s NodeId.
579 : * @param path An optional path if the Rib was created due to a "named"
580 : * lexical scope, like a module's.
581 : */
582 : void push (Rib::Kind rib_kind, NodeId id, tl::optional<Identifier> path = {});
583 :
584 : /**
585 : * Pop the innermost Rib from the stack
586 : */
587 : void pop ();
588 :
589 : /**
590 : * Insert a new definition in the innermost `Rib` in this stack
591 : *
592 : * @param name The name of the definition
593 : * @param id Its NodeId
594 : *
595 : * @return `DuplicateNameError` if that node was already present in the Rib,
596 : * the node's `NodeId` otherwise.
597 : *
598 : * @aborts if there are no `Rib`s inserted in the current map, this function
599 : * aborts the program.
600 : */
601 : tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id);
602 :
603 : tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
604 : NodeId id);
605 :
606 : /**
607 : * Insert a new shadowable definition in the innermost `Rib` in this stack
608 : *
609 : * @param name The name of the definition
610 : * @param id Its NodeId
611 : *
612 : * @return `DuplicateNameError` if that node was already present in the Rib,
613 : * the node's `NodeId` otherwise.
614 : *
615 : * @aborts if there are no `Rib`s inserted in the current map, this function
616 : * aborts the program.
617 : */
618 : tl::expected<NodeId, DuplicateNameError> insert_shadowable (Identifier name,
619 : NodeId id);
620 :
621 : /**
622 : * Insert a new glob-originated definition in the innermost `Rib` in this
623 : * stack
624 : *
625 : * @param name The name of the definition
626 : * @param id Its NodeId
627 : *
628 : * @return `DuplicateNameError` if that node was already present in the Rib,
629 : * the node's `NodeId` otherwise.
630 : *
631 : * @aborts if there are no `Rib`s inserted in the current map, this function
632 : * aborts the program.
633 : */
634 : tl::expected<NodeId, DuplicateNameError> insert_globbed (Identifier name,
635 : NodeId id);
636 :
637 : /**
638 : * Insert a new definition at the root of this stack
639 : *
640 : * @param name The name of the definition
641 : * @param id Its NodeId
642 : *
643 : * @return `DuplicateNameError` if that node was already present in the Rib,
644 : * the node's `NodeId` otherwise.
645 : *
646 : * @aborts if there are no `Rib`s inserted in the current map, this function
647 : * aborts the program.
648 : */
649 : tl::expected<NodeId, DuplicateNameError> insert_at_root (Identifier name,
650 : NodeId id);
651 :
652 : /**
653 : * Insert an item within the lang prelude
654 : *
655 : * @param name The name of the definition
656 : * @param id Its NodeId
657 : */
658 : void insert_lang_prelude (Identifier name, NodeId id);
659 :
660 : /* Access the innermost `Rib` in this map */
661 : Rib &peek ();
662 : const Rib &peek () const;
663 :
664 : /**
665 : * Reverse iter on all ribs from the innermost one to the outermost one,
666 : * trying to find a name. This is the default algorithm.
667 : * This function gets specialized based on the Rib::Kind
668 : * this way, we ensure a proper resolution algorithm at the type level
669 : *
670 : * @param name Name of the identifier to locate in this scope or an outermore
671 : * scope
672 : *
673 : * @return a valid option with the Definition if the identifier is present in
674 : * the current map, an empty one otherwise.
675 : */
676 : tl::optional<Rib::Definition> get (const Identifier &name);
677 : tl::optional<Rib::Definition> get_lang_prelude (const Identifier &name);
678 : tl::optional<Rib::Definition> get_lang_prelude (const std::string &name);
679 : tl::optional<Rib::Definition> get_from_prelude (NodeId prelude,
680 : const Identifier &name);
681 :
682 : /**
683 : * Resolve a path to its definition in the current `ForeverStack`
684 : *
685 : * // TODO: Add documentation for `segments`
686 : *
687 : * @return a valid option with the Definition if the path is present in the
688 : * current map, an empty one otherwise.
689 : */
690 : template <typename S>
691 : tl::optional<Rib::Definition> resolve_path (
692 : const std::vector<S> &segments, ResolutionMode mode,
693 : std::function<void (const S &, NodeId)> insert_segment_resolution,
694 : std::vector<Error> &collect_errors);
695 : template <typename S>
696 : tl::optional<Rib::Definition> resolve_path (
697 : const std::vector<S> &segments, ResolutionMode mode,
698 : std::function<void (const S &, NodeId)> insert_segment_resolution,
699 : std::vector<Error> &collect_errors, NodeId starting_point_id);
700 :
701 : // FIXME: Documentation
702 : tl::optional<Rib &> to_rib (NodeId rib_id);
703 : tl::optional<const Rib &> to_rib (NodeId rib_id) const;
704 :
705 : std::string as_debug_string () const;
706 :
707 : /**
708 : * Used to check if a module is a descendant of another module
709 : * Intended for use in the privacy checker
710 : */
711 : bool is_module_descendant (NodeId parent, NodeId child) const;
712 :
713 : private:
714 : /**
715 : * A link between two Nodes in our trie data structure. This class represents
716 : * the edges of the graph
717 : */
718 5061336 : class Link
719 : {
720 : public:
721 1508433 : Link (NodeId id, tl::optional<Identifier> path) : id (id), path (path) {}
722 :
723 4226313 : bool compare (const Link &other) const { return id < other.id; }
724 :
725 : NodeId id;
726 : tl::optional<Identifier> path;
727 : };
728 :
729 : /* Link comparison class, which we use in a Node's `children` map */
730 : class LinkCmp
731 : {
732 : public:
733 4226313 : bool operator() (const Link &lhs, const Link &rhs) const
734 : {
735 4226313 : return lhs.compare (rhs);
736 : }
737 : };
738 :
739 : class Node
740 : {
741 : public:
742 36080 : Node (Rib rib, NodeId id) : rib (rib), id (id) {}
743 1512943 : Node (Rib rib, NodeId id, Node &parent)
744 1512943 : : rib (rib), id (id), parent (parent)
745 : {}
746 :
747 : bool is_root () const;
748 : bool is_prelude () const;
749 : bool is_leaf () const;
750 :
751 : void insert_child (Link link, Node child);
752 :
753 : Rib rib; // this is the "value" of the node - the data it keeps.
754 : std::map<Link, Node, LinkCmp> children; // all the other nodes it links to
755 :
756 : NodeId id; // The node id of the Node's scope
757 :
758 : tl::optional<Node &> parent; // `None` only if the node is a root
759 : };
760 :
761 : /**
762 : * Private overloads which allow specifying a starting point
763 : */
764 :
765 : tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
766 :
767 : template <typename S>
768 : tl::optional<Rib::Definition> resolve_path (
769 : const std::vector<S> &segments, ResolutionMode mode,
770 : std::function<void (const S &, NodeId)> insert_segment_resolution,
771 : std::vector<Error> &collect_errors,
772 : std::reference_wrapper<Node> starting_point);
773 :
774 : /* Should we keep going upon seeing a Rib? */
775 : enum class KeepGoing
776 : {
777 : Yes,
778 : No,
779 : };
780 :
781 : /* Add a new Rib to the stack. This is an internal method */
782 : void push_inner (Rib rib, Link link);
783 :
784 : /* Reverse iterate on `Node`s from the cursor, in an outwards fashion */
785 : void reverse_iter (std::function<KeepGoing (Node &)> lambda);
786 : void reverse_iter (std::function<KeepGoing (const Node &)> lambda) const;
787 :
788 : /* Reverse iterate on `Node`s from a specified one, in an outwards fashion */
789 : void reverse_iter (Node &start, std::function<KeepGoing (Node &)> lambda);
790 : void reverse_iter (const Node &start,
791 : std::function<KeepGoing (const Node &)> lambda) const;
792 :
793 : Node &cursor ();
794 : const Node &cursor () const;
795 : void update_cursor (Node &new_cursor);
796 :
797 : /* The forever stack's actual nodes */
798 : Node root;
799 : /*
800 : * A special prelude node used currently for resolving language builtins
801 : * It has the root node as a parent, and acts as a "special case" for name
802 : * resolution
803 : */
804 : Node lang_prelude;
805 :
806 : /*
807 : * The extern prelude, used for resolving external crates
808 : */
809 : Node extern_prelude;
810 :
811 : std::reference_wrapper<Node> cursor_reference;
812 :
813 : void stream_rib (std::stringstream &stream, const Rib &rib,
814 : const std::string &next, const std::string &next_next) const;
815 : void stream_node (std::stringstream &stream, unsigned indentation,
816 : const Node &node, unsigned depth = 0) const;
817 :
818 : /* Helper types and functions for `resolve_path` */
819 :
820 : template <typename S>
821 : using SegIterator = typename std::vector<S>::const_iterator;
822 :
823 : Node &find_closest_module (Node &starting_point);
824 :
825 : template <typename S>
826 : tl::optional<SegIterator<S>> find_starting_point (
827 : const std::vector<S> &segments,
828 : std::reference_wrapper<Node> &starting_point,
829 : std::function<void (const S &, NodeId)> insert_segment_resolution,
830 : std::vector<Error> &collect_errors);
831 :
832 : template <typename S>
833 : tl::optional<Node &> resolve_segments (
834 : Node &starting_point, const std::vector<S> &segments,
835 : SegIterator<S> iterator,
836 : std::function<void (const S &, NodeId)> insert_segment_resolution,
837 : std::vector<Error> &collect_errors);
838 :
839 : tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,
840 : std::string &seg_name,
841 : bool is_lower_self);
842 :
843 : /* Helper functions for forward resolution (to_canonical_path, to_rib...) */
844 : struct DfsResult
845 : {
846 : Node &first;
847 : std::string second;
848 : };
849 : struct ConstDfsResult
850 : {
851 : const Node &first;
852 : std::string second;
853 : };
854 :
855 : // FIXME: Documentation
856 : tl::optional<DfsResult> dfs (Node &starting_point, NodeId to_find);
857 : tl::optional<ConstDfsResult> dfs (const Node &starting_point,
858 : NodeId to_find) const;
859 : // FIXME: Documentation
860 : tl::optional<Rib &> dfs_rib (Node &starting_point, NodeId to_find);
861 : tl::optional<const Rib &> dfs_rib (const Node &starting_point,
862 : NodeId to_find) const;
863 : // FIXME: Documentation
864 : tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find);
865 : tl::optional<const Node &> dfs_node (const Node &starting_point,
866 : NodeId to_find) const;
867 :
868 : public:
869 53330 : bool forward_declared (NodeId definition, NodeId usage)
870 : {
871 53330 : if (peek ().kind != Rib::Kind::ForwardTypeParamBan)
872 : return false;
873 :
874 1297 : const auto &definition_rib = dfs_rib (cursor (), definition);
875 :
876 1297 : if (!definition_rib)
877 : return false;
878 :
879 : return (definition_rib
880 1 : && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan);
881 : }
882 : };
883 :
884 : } // namespace Resolver2_0
885 : } // namespace Rust
886 :
887 : #include "rust-forever-stack.hxx"
888 :
889 : #endif // !RUST_FOREVER_STACK_H
|