LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-toplevel-name-resolver-2.0.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.4 % 17 14
Test Date: 2026-02-28 14:20:25 Functions: 66.7 % 3 2
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_TOPLEVEL_NAME_RESOLVER_2_0_H
      20              : #define RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
      21              : 
      22              : #include "optional.h"
      23              : #include "rust-ast-visitor.h"
      24              : #include "rust-ast.h"
      25              : #include "rust-item.h"
      26              : #include "rust-name-resolution-context.h"
      27              : #include "rust-default-resolver.h"
      28              : 
      29              : namespace Rust {
      30              : namespace Resolver2_0 {
      31              : 
      32              : /**
      33              :  * The `TopLevel` visitor takes care of collecting all the definitions in a
      34              :  * crate, and inserting them into the proper namespaces. These definitions can
      35              :  * then be accessed by subsequent resolvers, such as `Early` or `Late`.
      36              :  */
      37              : class TopLevel : public DefaultResolver
      38              : {
      39              :   using DefaultResolver::visit;
      40              : 
      41              : public:
      42              :   TopLevel (NameResolutionContext &resolver);
      43              : 
      44              :   void go (AST::Crate &crate);
      45              : 
      46        10411 :   bool is_dirty () { return dirty; }
      47              : 
      48              :   // Each import will be transformed into an instance of `ImportKind`, a class
      49              :   // representing some of the data we need to resolve in the
      50              :   // `EarlyNameResolver`. Basically, for each `UseTree` that we see in
      51              :   // `TopLevel`, create one of these. `TopLevel` should build a list of these
      52              :   // `ImportKind`s, which `Early` can then resolve to their proper definitions.
      53              :   // Then, a final pass will insert the definitions into the `ForeverStack` -
      54              :   // `FinalizeImports`.
      55              :   //
      56              :   // Using this struct should be very simple - each path within a `UseTree`
      57              :   // becomes one `ImportKind`. The complex case is glob imports, in which case
      58              :   // one glob import will become one `ImportKind` which will later become
      59              :   // multiple definitions thanks to the `GlobbingVisitor`.
      60              :   struct ImportKind
      61              :   {
      62              :     enum class Kind
      63              :     {
      64              :       Glob,
      65              :       Simple,
      66              :       Rebind,
      67              :     } kind;
      68              : 
      69           25 :     static ImportKind Glob (AST::SimplePath &&to_resolve, Rib &values_rib,
      70              :                             Rib &types_rib, Rib &macros_rib, bool is_prelude)
      71              :     {
      72           25 :       return ImportKind (Kind::Glob, std::move (to_resolve), values_rib,
      73           25 :                          types_rib, macros_rib, is_prelude);
      74              :     }
      75              : 
      76            0 :     static ImportKind Simple (AST::SimplePath &&to_resolve, Rib &values_rib,
      77              :                               Rib &types_rib, Rib &macros_rib)
      78              :     {
      79            0 :       return ImportKind (Kind::Simple, std::move (to_resolve), values_rib,
      80            0 :                          types_rib, macros_rib);
      81              :     }
      82              : 
      83         4121 :     static ImportKind Rebind (AST::SimplePath &&to_resolve,
      84              :                               AST::UseTreeRebind &&rebind, Rib &values_rib,
      85              :                               Rib &types_rib, Rib &macros_rib)
      86              :     {
      87         4121 :       return ImportKind (
      88              :         Kind::Rebind, std::move (to_resolve), values_rib, types_rib, macros_rib,
      89              :         false /* is_prelude: rebind imports can never be preludes */,
      90         4121 :         std::move (rebind));
      91              :     }
      92              : 
      93              :     // The path for `Early` to resolve.
      94              :     AST::SimplePath to_resolve;
      95              : 
      96              :     // The path to rebind an import to - only present if kind is Kind::Rebind
      97              :     tl::optional<AST::UseTreeRebind> rebind;
      98              : 
      99              :     Rib &values_rib;
     100              :     Rib &types_rib;
     101              :     Rib &macros_rib;
     102              : 
     103              :     // Can only be true if we are dealing with a glob import with the
     104              :     // #[prelude_import] attribute
     105              :     bool is_prelude = false;
     106              : 
     107              :   private:
     108         4146 :     ImportKind (Kind kind, AST::SimplePath &&to_resolve, Rib &values_rib,
     109              :                 Rib &types_rib, Rib &macros_rib, bool is_prelude = false,
     110           25 :                 tl::optional<AST::UseTreeRebind> &&rebind = tl::nullopt)
     111         4146 :       : kind (kind), to_resolve (std::move (to_resolve)),
     112         4146 :         rebind (std::move (rebind)), values_rib (values_rib),
     113         4146 :         types_rib (types_rib), macros_rib (macros_rib), is_prelude (is_prelude)
     114         4146 :     {}
     115              :   };
     116              : 
     117              :   std::unordered_map<NodeId, std::vector<ImportKind>> &get_imports_to_resolve ()
     118              :   {
     119         1842 :     return imports_to_resolve;
     120              :   }
     121              : 
     122              :   void check_multiple_insertion_error (
     123              :     tl::expected<NodeId, DuplicateNameError> result,
     124              :     const Identifier &identifier, const location_t &locus,
     125              :     const NodeId node_id);
     126              : 
     127              :   /**
     128              :    * Insert a new definition or error out if a definition with the same name
     129              :    * was already present in the same namespace in the same scope.
     130              :    *
     131              :    * @param identifier The identifier of the definition to add.
     132              :    * @param node A reference to the node, so we can get its `NodeId` and
     133              :    * location.
     134              :    * @param ns The namespace in which to add the definition.
     135              :    */
     136              :   template <typename T>
     137              :   void insert_or_error_out (const Identifier &identifier, const T &node,
     138              :                             Namespace ns);
     139              :   void insert_or_error_out (const Identifier &identifier,
     140              :                             const location_t &locus, const NodeId &id,
     141              :                             Namespace ns);
     142              : 
     143              :   template <typename T>
     144              :   void insert_enum_variant_or_error_out (const Identifier &identifier,
     145              :                                          const T &node);
     146              : 
     147              :   void insert_enum_variant_or_error_out (const Identifier &identifier,
     148              :                                          const location_t &locus,
     149              :                                          const NodeId node_id);
     150              : 
     151              : private:
     152              :   // If a new export has been defined whilst visiting the visitor is considered
     153              :   // dirty
     154              :   bool dirty;
     155              : 
     156              :   // FIXME: Do we move these to our mappings?
     157              :   std::unordered_map<NodeId, location_t> node_locations;
     158              : 
     159              :   // Store node forwarding for use declaration, the link between a
     160              :   // definition and its new local name.
     161              :   std::unordered_map<NodeId, NodeId> node_forwarding;
     162              : 
     163              :   // One of the outputs of the `TopLevel` visitor - the list of imports that
     164              :   // `Early` should take care of resolving
     165              :   std::unordered_map<NodeId, std::vector<ImportKind>> imports_to_resolve;
     166              : 
     167              :   void visit (AST::Module &module) override;
     168              :   void visit (AST::Trait &trait) override;
     169              :   void maybe_insert_big_self (AST::Impl &impl) override;
     170              :   void visit (AST::TraitItemType &trait_item) override;
     171              :   void visit (AST::MacroRulesDefinition &macro) override;
     172              :   void visit (AST::Function &function) override;
     173              :   void visit (AST::StaticItem &static_item) override;
     174              :   void visit (AST::ExternalStaticItem &static_item) override;
     175              :   void visit (AST::StructStruct &struct_item) override;
     176              :   void visit (AST::TupleStruct &tuple_struct) override;
     177              :   void visit (AST::EnumItem &variant) override;
     178              :   void visit (AST::EnumItemTuple &variant) override;
     179              :   void visit (AST::EnumItemStruct &variant) override;
     180              :   void visit (AST::EnumItemDiscriminant &variant) override;
     181              :   void visit (AST::Enum &enum_item) override;
     182              :   void visit (AST::Union &union_item) override;
     183              :   void visit (AST::ConstantItem &const_item) override;
     184              :   void visit (AST::TypeAlias &type_item) override;
     185              :   void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override;
     186              :   void visit (AST::TypeParam &type_param) override;
     187              :   void visit (AST::ConstGenericParam &const_param) override;
     188              : 
     189              :   void visit (AST::UseDeclaration &use) override;
     190              : };
     191              : 
     192              : } // namespace Resolver2_0
     193              : } // namespace Rust
     194              : 
     195              : // For storing Imports as keys in maps
     196              : namespace std {
     197              : template <> struct less<Rust::Resolver2_0::TopLevel::ImportKind>
     198              : {
     199              :   bool operator() (const Rust::Resolver2_0::TopLevel::ImportKind &lhs,
     200              :                    const Rust::Resolver2_0::TopLevel::ImportKind &rhs) const
     201              :   {
     202              :     return lhs.to_resolve.as_string () < rhs.to_resolve.as_string ()
     203              :            && lhs.kind < rhs.kind;
     204              :   }
     205              : };
     206              : } // namespace std
     207              : 
     208              : #endif // !RUST_TOPLEVEL_NAME_RESOLVER_2_0_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.