Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : : template <Namespace N> class ForeverStack
547 : : {
548 : : public:
549 : 19652 : ForeverStack ()
550 : 19652 : : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
551 : 39304 : lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
552 : 19652 : extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)),
553 : 19652 : cursor_reference (root)
554 : : {
555 : 19652 : rust_assert (root.is_root ());
556 : 19652 : rust_assert (root.is_leaf ());
557 : :
558 : : // TODO: Should we be using the forever stack root as the crate scope?
559 : : // TODO: Is this how we should be getting the crate node id?
560 : 19652 : auto &mappings = Analysis::Mappings::get ();
561 : 19652 : root.id = *mappings.crate_num_to_nodeid (mappings.get_current_crate ());
562 : 19652 : }
563 : :
564 : : /**
565 : : * Add a new Rib to the stack. If the Rib already exists, nothing is pushed
566 : : * and the stack's cursor is simply moved to this existing Rib.
567 : : *
568 : : * @param rib The Rib to push
569 : : * @param id The NodeId of the node for which the Rib was created. For
570 : : * example, if a Rib is created because a lexical scope is entered,
571 : : * then `id` is that `BlockExpr`'s NodeId.
572 : : * @param path An optional path if the Rib was created due to a "named"
573 : : * lexical scope, like a module's.
574 : : */
575 : : void push (Rib::Kind rib_kind, NodeId id, tl::optional<Identifier> path = {});
576 : :
577 : : /**
578 : : * Pop the innermost Rib from the stack
579 : : */
580 : : void pop ();
581 : :
582 : : /**
583 : : * Insert a new definition in the innermost `Rib` in this stack
584 : : *
585 : : * @param name The name of the definition
586 : : * @param id Its NodeId
587 : : *
588 : : * @return `DuplicateNameError` if that node was already present in the Rib,
589 : : * the node's `NodeId` otherwise.
590 : : *
591 : : * @aborts if there are no `Rib`s inserted in the current map, this function
592 : : * aborts the program.
593 : : */
594 : : tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id);
595 : :
596 : : tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
597 : : NodeId id);
598 : :
599 : : /**
600 : : * Insert a new shadowable definition in the innermost `Rib` in this stack
601 : : *
602 : : * @param name The name of the definition
603 : : * @param id Its NodeId
604 : : *
605 : : * @return `DuplicateNameError` if that node was already present in the Rib,
606 : : * the node's `NodeId` otherwise.
607 : : *
608 : : * @aborts if there are no `Rib`s inserted in the current map, this function
609 : : * aborts the program.
610 : : */
611 : : tl::expected<NodeId, DuplicateNameError> insert_shadowable (Identifier name,
612 : : NodeId id);
613 : :
614 : : /**
615 : : * Insert a new glob-originated definition in the innermost `Rib` in this
616 : : * stack
617 : : *
618 : : * @param name The name of the definition
619 : : * @param id Its NodeId
620 : : *
621 : : * @return `DuplicateNameError` if that node was already present in the Rib,
622 : : * the node's `NodeId` otherwise.
623 : : *
624 : : * @aborts if there are no `Rib`s inserted in the current map, this function
625 : : * aborts the program.
626 : : */
627 : : tl::expected<NodeId, DuplicateNameError> insert_globbed (Identifier name,
628 : : NodeId id);
629 : :
630 : : /**
631 : : * Insert a new definition at the root of this stack
632 : : *
633 : : * @param name The name of the definition
634 : : * @param id Its NodeId
635 : : *
636 : : * @return `DuplicateNameError` if that node was already present in the Rib,
637 : : * the node's `NodeId` otherwise.
638 : : *
639 : : * @aborts if there are no `Rib`s inserted in the current map, this function
640 : : * aborts the program.
641 : : */
642 : : tl::expected<NodeId, DuplicateNameError> insert_at_root (Identifier name,
643 : : NodeId id);
644 : :
645 : : /* Access the innermost `Rib` in this map */
646 : : Rib &peek ();
647 : : const Rib &peek () const;
648 : :
649 : : /**
650 : : * Reverse iter on all ribs from the innermost one to the outermost one,
651 : : * trying to find a name. This is the default algorithm.
652 : : * This function gets specialized based on the Rib::Kind
653 : : * this way, we ensure a proper resolution algorithm at the type level
654 : : *
655 : : * @param name Name of the identifier to locate in this scope or an outermore
656 : : * scope
657 : : *
658 : : * @return a valid option with the Definition if the identifier is present in
659 : : * the current map, an empty one otherwise.
660 : : */
661 : : tl::optional<Rib::Definition> get (const Identifier &name);
662 : : tl::optional<Rib::Definition> get_lang_prelude (const Identifier &name);
663 : : tl::optional<Rib::Definition> get_lang_prelude (const std::string &name);
664 : :
665 : : /**
666 : : * Resolve a path to its definition in the current `ForeverStack`
667 : : *
668 : : * // TODO: Add documentation for `segments`
669 : : *
670 : : * @return a valid option with the Definition if the path is present in the
671 : : * current map, an empty one otherwise.
672 : : */
673 : : template <typename S>
674 : : tl::optional<Rib::Definition> resolve_path (
675 : : const std::vector<S> &segments, bool has_opening_scope_resolution,
676 : : std::function<void (const S &, NodeId)> insert_segment_resolution);
677 : :
678 : : // FIXME: Documentation
679 : : tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
680 : :
681 : : // FIXME: Documentation
682 : : tl::optional<Rib &> to_rib (NodeId rib_id);
683 : : tl::optional<const Rib &> to_rib (NodeId rib_id) const;
684 : :
685 : : std::string as_debug_string () const;
686 : :
687 : : /**
688 : : * Used to check if a module is a descendant of another module
689 : : * Intended for use in the privacy checker
690 : : */
691 : : bool is_module_descendant (NodeId parent, NodeId child) const;
692 : :
693 : : private:
694 : : /**
695 : : * A link between two Nodes in our trie data structure. This class represents
696 : : * the edges of the graph
697 : : */
698 : 1052290 : class Link
699 : : {
700 : : public:
701 : 147363 : Link (NodeId id, tl::optional<Identifier> path) : id (id), path (path) {}
702 : :
703 : 405567 : bool compare (const Link &other) const { return id < other.id; }
704 : :
705 : : NodeId id;
706 : : tl::optional<Identifier> path;
707 : : };
708 : :
709 : : /* Link comparison class, which we use in a Node's `children` map */
710 : : class LinkCmp
711 : : {
712 : : public:
713 : 405567 : bool operator() (const Link &lhs, const Link &rhs) const
714 : : {
715 : 405567 : return lhs.compare (rhs);
716 : : }
717 : : };
718 : :
719 : : class Node
720 : : {
721 : : public:
722 : 39304 : Node (Rib rib, NodeId id) : rib (rib), id (id) {}
723 : 164054 : Node (Rib rib, NodeId id, Node &parent)
724 : 164054 : : rib (rib), id (id), parent (parent)
725 : : {}
726 : :
727 : : bool is_root () const;
728 : : bool is_prelude () const;
729 : : bool is_leaf () const;
730 : :
731 : : void insert_child (Link link, Node child);
732 : :
733 : : Rib rib; // this is the "value" of the node - the data it keeps.
734 : : std::map<Link, Node, LinkCmp> children; // all the other nodes it links to
735 : :
736 : : NodeId id; // The node id of the Node's scope
737 : :
738 : : tl::optional<Node &> parent; // `None` only if the node is a root
739 : : };
740 : :
741 : : /* Should we keep going upon seeing a Rib? */
742 : : enum class KeepGoing
743 : : {
744 : : Yes,
745 : : No,
746 : : };
747 : :
748 : : /* Add a new Rib to the stack. This is an internal method */
749 : : void push_inner (Rib rib, Link link);
750 : :
751 : : /* Reverse iterate on `Node`s from the cursor, in an outwards fashion */
752 : : void reverse_iter (std::function<KeepGoing (Node &)> lambda);
753 : : void reverse_iter (std::function<KeepGoing (const Node &)> lambda) const;
754 : :
755 : : /* Reverse iterate on `Node`s from a specified one, in an outwards fashion */
756 : : void reverse_iter (Node &start, std::function<KeepGoing (Node &)> lambda);
757 : : void reverse_iter (const Node &start,
758 : : std::function<KeepGoing (const Node &)> lambda) const;
759 : :
760 : : Node &cursor ();
761 : : const Node &cursor () const;
762 : : void update_cursor (Node &new_cursor);
763 : :
764 : : /* The forever stack's actual nodes */
765 : : Node root;
766 : : /*
767 : : * A special prelude node used currently for resolving language builtins
768 : : * It has the root node as a parent, and acts as a "special case" for name
769 : : * resolution
770 : : */
771 : : Node lang_prelude;
772 : : /*
773 : : * The extern prelude, used for resolving external crates
774 : : */
775 : : Node extern_prelude;
776 : :
777 : : std::reference_wrapper<Node> cursor_reference;
778 : :
779 : : void stream_rib (std::stringstream &stream, const Rib &rib,
780 : : const std::string &next, const std::string &next_next) const;
781 : : void stream_node (std::stringstream &stream, unsigned indentation,
782 : : const Node &node) const;
783 : :
784 : : /* Helper types and functions for `resolve_path` */
785 : :
786 : : template <typename S>
787 : : using SegIterator = typename std::vector<S>::const_iterator;
788 : :
789 : : Node &find_closest_module (Node &starting_point);
790 : :
791 : : template <typename S>
792 : : tl::optional<SegIterator<S>> find_starting_point (
793 : : const std::vector<S> &segments,
794 : : std::reference_wrapper<Node> &starting_point,
795 : : std::function<void (const S &, NodeId)> insert_segment_resolution);
796 : :
797 : : template <typename S>
798 : : tl::optional<Node &> resolve_segments (
799 : : Node &starting_point, const std::vector<S> &segments,
800 : : SegIterator<S> iterator,
801 : : std::function<void (const S &, NodeId)> insert_segment_resolution);
802 : :
803 : : tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,
804 : : std::string &seg_name,
805 : : bool is_lower_self);
806 : :
807 : : /* Helper functions for forward resolution (to_canonical_path, to_rib...) */
808 : : struct DfsResult
809 : : {
810 : : Node &first;
811 : : std::string second;
812 : : };
813 : 29720 : struct ConstDfsResult
814 : : {
815 : : const Node &first;
816 : : std::string second;
817 : : };
818 : :
819 : : // FIXME: Documentation
820 : : tl::optional<DfsResult> dfs (Node &starting_point, NodeId to_find);
821 : : tl::optional<ConstDfsResult> dfs (const Node &starting_point,
822 : : NodeId to_find) const;
823 : : // FIXME: Documentation
824 : : tl::optional<Rib &> dfs_rib (Node &starting_point, NodeId to_find);
825 : : tl::optional<const Rib &> dfs_rib (const Node &starting_point,
826 : : NodeId to_find) const;
827 : : // FIXME: Documentation
828 : : tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find);
829 : : tl::optional<const Node &> dfs_node (const Node &starting_point,
830 : : NodeId to_find) const;
831 : : };
832 : :
833 : : } // namespace Resolver2_0
834 : : } // namespace Rust
835 : :
836 : : #include "rust-forever-stack.hxx"
837 : :
838 : : #endif // !RUST_FOREVER_STACK_H
|