LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-forever-stack.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 65.7 % 35 23
Test Date: 2026-02-28 14:20:25 Functions: 81.8 % 11 9
Legend: Lines:     hit not hit

            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
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.