LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-early-name-resolver-2.0.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.9 % 322 283
Test Date: 2026-08-22 16:33:35 Functions: 92.9 % 28 26
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              : #include "rust-early-name-resolver-2.0.h"
      20              : #include "optional.h"
      21              : #include "options.h"
      22              : #include "rust-ast.h"
      23              : #include "rust-diagnostics.h"
      24              : #include "rust-hir-map.h"
      25              : #include "rust-item.h"
      26              : #include "rust-name-resolution-context.h"
      27              : #include "rust-rib.h"
      28              : #include "rust-toplevel-name-resolver-2.0.h"
      29              : #include "rust-attributes.h"
      30              : #include "rust-finalize-imports-2.0.h"
      31              : #include "rust-attribute-values.h"
      32              : #include "rust-identifier-path.h"
      33              : #include "rust-session-manager.h"
      34              : 
      35              : namespace Rust {
      36              : namespace Resolver2_0 {
      37              : 
      38        11200 : Early::Early (NameResolutionContext &ctx)
      39        11200 :   : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
      40        11200 : {}
      41              : 
      42              : void
      43        91069 : Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
      44              : {
      45        91069 :   auto leaf_macro = ctx.macros.find_leaf_definition (resolved);
      46              : 
      47              :   // Sometimes the import itself isn't resolved yet this turn of the fixed-point
      48        91069 :   if (!leaf_macro)
      49        91069 :     return;
      50              : 
      51              :   // TODO: Should we use `ctx.map_usage()`?
      52              : 
      53            0 :   auto definition = ctx.mappings.lookup_macro_def (leaf_macro->id);
      54              : 
      55            0 :   if (!ctx.mappings.lookup_macro_invocation (invocation))
      56            0 :     ctx.mappings.insert_macro_invocation (invocation, definition.value ());
      57              : }
      58              : 
      59              : void
      60        28897 : Early::insert_once (AST::MacroRulesDefinition &def)
      61              : {
      62        28897 :   if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
      63            1 :     ctx.mappings.insert_macro_def (&def);
      64        28897 : }
      65              : 
      66              : void
      67        11200 : Early::go (AST::Crate &crate)
      68              : {
      69              :   // First we go through TopLevel resolution to get all our declared items
      70        11200 :   toplevel.go (crate);
      71              : 
      72              :   // We start with resolving the list of imports that `TopLevel` has built for
      73              :   // us
      74              : 
      75        11200 :   dirty = toplevel.is_dirty ();
      76              : 
      77              :   // We now proceed with resolving macros, which can be nested in almost any
      78              :   // items
      79        11200 :   textual_scope.push ();
      80              : 
      81        11200 :   visit (crate);
      82              : 
      83        11200 :   textual_scope.pop ();
      84              : 
      85              :   // handle IdentifierPattern vs PathInExpression disambiguation
      86        11200 :   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
      87        11200 : }
      88              : 
      89              : bool
      90         3822 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
      91              : {
      92         3822 :   auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
      93         3822 :   if (!resolved.has_value ())
      94              :     return false;
      95              : 
      96         7640 :   auto result = Analysis::Mappings::get ().lookup_glob_container (
      97         3820 :     resolved->definition.get_node_id ());
      98              : 
      99         3820 :   if (!result)
     100              :     return false;
     101              : 
     102         3820 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     103              : 
     104              :   // here, we insert the module's NodeId into the import_mappings and will look
     105              :   // up the module proper in `FinalizeImports`
     106              :   // The namespace does not matter here since we are dealing with a glob
     107              :   // FIXME: Does the namespace not matter? Is that valid?
     108              :   // TODO: Ugly
     109         7640 :   imports.emplace_back (
     110        11460 :     ImportPair (std::move (glob), ImportData::Glob (resolved->definition)));
     111              : 
     112         3820 :   return true;
     113         3822 : }
     114              : 
     115              : bool
     116            0 : Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
     117              : {
     118            0 :   auto definitions = resolve_path_in_all_ns (import.to_resolve);
     119              : 
     120              :   // if we've found at least one definition, then we're good
     121            0 :   if (definitions.empty ())
     122              :     return false;
     123              : 
     124            0 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     125              : 
     126            0 :   imports.emplace_back (
     127            0 :     ImportPair (std::move (import),
     128            0 :                 ImportData::Simple (std::move (definitions))));
     129              : 
     130            0 :   return true;
     131            0 : }
     132              : 
     133              : bool
     134        39809 : Early::resolve_rebind_import (NodeId use_dec_id,
     135              :                               TopLevel::ImportKind &&rebind_import)
     136              : {
     137        39809 :   NodeId import_id = UNKNOWN_NODEID;
     138        39809 :   auto &path = rebind_import.to_resolve;
     139        39809 :   auto &rebind = rebind_import.rebind.value ();
     140              : 
     141        39809 :   switch (rebind.get_new_bind_type ())
     142              :     {
     143          568 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     144          568 :       import_id = rebind.get_node_id ();
     145          568 :       break;
     146        39237 :     case AST::UseTreeRebind::NewBindType::NONE:
     147        39237 :       {
     148        39237 :         const auto &segments = path.get_segments ();
     149              :         // We don't want to insert `self` with `use module::self`
     150        39237 :         if (path.get_final_segment ().is_lower_self_seg ())
     151              :           {
     152              :             // Erroneous `self` or `{self}` use declaration
     153         1646 :             if (segments.size () == 1)
     154              :               break;
     155         1641 :             import_id = segments[segments.size () - 2].get_node_id ();
     156              :           }
     157              :         else
     158              :           {
     159        37591 :             import_id = path.get_final_segment ().get_node_id ();
     160              :           }
     161              :         break;
     162              :       }
     163              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     164              :       // nothing
     165              :       break;
     166              :     }
     167              : 
     168        39809 :   if (ctx.lookup (import_id, Namespace::Types))
     169              :     return true;
     170              : 
     171         7806 :   auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
     172              : 
     173              :   // if we've found at least one definition, then we're good
     174         7806 :   if (definitions.empty ())
     175              :     return false;
     176        15297 :   for (const auto &def : definitions)
     177              :     {
     178         7788 :       if (def.definition.is_ambiguous ())
     179              :         {
     180            1 :           rich_location rich_locus (line_table,
     181            1 :                                     rebind_import.to_resolve.get_locus ());
     182            1 :           rust_error_at (rich_locus, ErrorCode::E0659, "%qs is ambiguous",
     183            1 :                          rebind_import.to_resolve.as_string ().c_str ());
     184            1 :           return true;
     185            1 :         }
     186              :     }
     187              : 
     188         7509 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     189              : 
     190         7509 :   imports.emplace_back (
     191         7509 :     ImportPair (std::move (rebind_import),
     192        15018 :                 ImportData::Rebind (std::move (definitions))));
     193              : 
     194         7509 :   return true;
     195         7806 : }
     196              : 
     197              : void
     198        25556 : Early::build_import_mapping (
     199              :   std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
     200              : {
     201        25556 :   auto found = false;
     202        25556 :   auto use_dec_id = use_import.first;
     203              : 
     204        69187 :   for (auto &&import : use_import.second)
     205              :     {
     206              :       // We create a copy of the path in case of errors, since the `import` will
     207              :       // be moved into the newly created import mappings
     208        43631 :       auto path = import.to_resolve;
     209              : 
     210              :       // used to skip the "unresolved import" error
     211              :       // if we output other errors during resolution
     212        43631 :       size_t old_error_count = macro_resolve_errors.size ();
     213              : 
     214        43631 :       switch (import.kind)
     215              :         {
     216         3822 :         case TopLevel::ImportKind::Kind::Glob:
     217         3822 :           found = resolve_glob_import (use_dec_id, std::move (import));
     218         3822 :           break;
     219            0 :         case TopLevel::ImportKind::Kind::Simple:
     220            0 :           found = resolve_simple_import (use_dec_id, std::move (import));
     221            0 :           break;
     222        39809 :         case TopLevel::ImportKind::Kind::Rebind:
     223        39809 :           found = resolve_rebind_import (use_dec_id, std::move (import));
     224        39809 :           break;
     225              :         }
     226              : 
     227        43631 :       if (!found && old_error_count == macro_resolve_errors.size ())
     228          592 :         collect_error (Error (path.get_final_segment ().get_locus (),
     229              :                               ErrorCode::E0433, "unresolved import %qs",
     230          592 :                               path.as_string ().c_str ()));
     231        43631 :     }
     232        25556 : }
     233              : 
     234              : void
     235       634059 : Early::TextualScope::push ()
     236              : {
     237              :   // push a new empty scope
     238       634059 :   scopes.emplace_back ();
     239       634059 : }
     240              : 
     241              : void
     242       634059 : Early::TextualScope::pop ()
     243              : {
     244       634059 :   rust_assert (!scopes.empty ());
     245              : 
     246       634059 :   scopes.pop_back ();
     247       634059 : }
     248              : 
     249              : void
     250        28897 : Early::TextualScope::insert (std::string name, NodeId id)
     251              : {
     252        28897 :   rust_assert (!scopes.empty ());
     253              : 
     254              :   // we can ignore the return value as we always want the latest defined macro
     255              :   // to shadow a previous one - so if two macros have the same name and get
     256              :   // inserted with the same key, it's not a bug
     257        57794 :   scopes.back ().insert ({name, id});
     258        28897 : }
     259              : 
     260              : tl::optional<NodeId>
     261        90954 : Early::TextualScope::get (const std::string &name)
     262              : {
     263       146685 :   for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
     264              :     {
     265       111285 :       auto scope = *iterator;
     266       111285 :       auto found = scope.find (name);
     267       111285 :       if (found != scope.end ())
     268        55554 :         return found->second;
     269       111285 :     }
     270              : 
     271        35400 :   return tl::nullopt;
     272              : }
     273              : 
     274              : void
     275        28897 : Early::visit (AST::MacroRulesDefinition &def)
     276              : {
     277        28897 :   DefaultResolver::visit (def);
     278              : 
     279        57794 :   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
     280        28897 :   insert_once (def);
     281        28897 : }
     282              : 
     283              : void
     284       611720 : Early::visit (AST::BlockExpr &block)
     285              : {
     286       611720 :   textual_scope.push ();
     287              : 
     288       611720 :   DefaultResolver::visit (block);
     289              : 
     290       611720 :   textual_scope.pop ();
     291       611720 : }
     292              : 
     293              : void
     294        11486 : Early::visit (AST::Module &module)
     295              : {
     296        11486 :   bool is_macro_use = false;
     297              : 
     298        14494 :   for (const auto &attr : module.get_outer_attrs ())
     299              :     {
     300         3355 :       if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
     301              :         {
     302              :           is_macro_use = true;
     303              :           break;
     304              :         }
     305              :     }
     306              : 
     307        11486 :   if (!is_macro_use)
     308        11139 :     textual_scope.push ();
     309              : 
     310        11486 :   DefaultResolver::visit (module);
     311              : 
     312        11486 :   if (!is_macro_use)
     313        11139 :     textual_scope.pop ();
     314        11486 : }
     315              : 
     316              : void
     317        22686 : Early::maybe_prelude_import ()
     318              : {
     319              :   // handle prelude import
     320        22686 :   if (ctx.prelude)
     321              :     {
     322        16596 :       auto container = Analysis::Mappings::get ().lookup_glob_container (
     323         8298 :         ctx.prelude.value ());
     324         8298 :       rust_assert (container);
     325              : 
     326         8298 :       GlobbingVisitor glob_visit (ctx);
     327         8298 :       glob_visit.go (container.value ());
     328         8298 :       dirty |= glob_visit.is_dirty ();
     329              :     }
     330        22686 : }
     331              : 
     332              : void
     333        91192 : Early::visit (AST::MacroInvocation &invoc)
     334              : {
     335        91192 :   auto &path = invoc.get_invoc_data ().get_path ();
     336              : 
     337              :   // We special case the `offset_of!()` macro if the flag is here, otherwise
     338              :   // we accept whatever `offset_of!()` definition we resolved to.
     339        91192 :   auto resolve_offset_of = Session::get_instance ().should_support_offset_of ()
     340        91192 :                            && (path.as_string () == "offset_of");
     341              : 
     342              :   // Ditto, but for `cfg_select!()`.
     343        91192 :   auto resolve_cfg_select
     344        91192 :     = Session::get_instance ().should_support_cfg_select ()
     345        91192 :       && (path.as_string () == "cfg_select");
     346              : 
     347        91192 :   if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
     348         1074 :     for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
     349          728 :       pending_invoc->accept_vis (*this);
     350              : 
     351              :   // When a macro is invoked by an unqualified identifier (not part of a
     352              :   // multi-part path), it is first looked up in textual scoping. If this does
     353              :   // not yield any results, then it is looked up in path-based scoping. If the
     354              :   // macro's name is qualified with a path, then it is only looked up in
     355              :   // path-based scoping.
     356              : 
     357              :   // https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
     358              : 
     359        91192 :   tl::optional<NameResolutionContext::NamespacedDefinition> ns_def
     360              :     = tl::nullopt;
     361        91192 :   if (path.get_segments ().size () == 1)
     362        90954 :     ns_def = textual_scope.get (path.get_final_segment ().as_string ())
     363       181908 :                .map ([] (NodeId id) {
     364        55554 :                  return NameResolutionContext::NamespacedDefinition (
     365        55554 :                    Rib::Definition::NonShadowable (id), Namespace::Macros);
     366        90954 :                });
     367              : 
     368              :   // we won't have changed `definition` from `nullopt` if there are more
     369              :   // than one segments in our path
     370        91192 :   if (!ns_def.has_value ())
     371        71153 :     ns_def = ctx.resolve_path (path, Namespace::Macros);
     372              : 
     373              :   // if the definition still does not have a value, then it's an error - unless
     374              :   // we should automatically resolve offset_of!() or cfg_select!() calls
     375        91192 :   if (!ns_def.has_value ())
     376              :     {
     377          123 :       if (!resolve_offset_of && !resolve_cfg_select)
     378           76 :         collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
     379              :                               "could not resolve macro invocation %qs",
     380          152 :                               path.as_string ().c_str ()));
     381              :       return;
     382              :     }
     383              : 
     384        91069 :   try_insert_once (invoc, ns_def->definition.get_node_id ());
     385              : 
     386              :   // now do we need to keep mappings or something? or insert "uses" into our
     387              :   // ForeverStack? can we do that? are mappings simpler?
     388        91069 :   auto &mappings = Analysis::Mappings::get ();
     389        91069 :   auto rules_def
     390        91069 :     = mappings.lookup_macro_def (ns_def->definition.get_node_id ());
     391              : 
     392              :   // Macro definition not found, maybe it is not expanded yet.
     393        91069 :   if (!rules_def)
     394              :     return;
     395              : 
     396        91069 :   if (mappings.lookup_macro_invocation (invoc))
     397              :     return;
     398              : 
     399        58237 :   mappings.insert_macro_invocation (invoc, rules_def.value ());
     400        91192 : }
     401              : 
     402              : void
     403          404 : Early::visit_derive_attribute (AST::Attribute &attr,
     404              :                                Analysis::Mappings &mappings)
     405              : {
     406          404 :   auto traits = attr.get_traits_to_derive ();
     407         1468 :   for (auto &trait : traits)
     408              :     {
     409         1064 :       auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
     410         1064 :       if (!ns_def.has_value ())
     411              :         {
     412              :           // FIXME: Change to proper error message
     413          752 :           collect_error (Error (trait.get ().get_locus (),
     414              :                                 "could not resolve trait %qs",
     415          376 :                                 trait.get ().as_string ().c_str ()));
     416          376 :           continue;
     417              :         }
     418              : 
     419          688 :       auto pm_def = mappings.lookup_derive_proc_macro_def (
     420          688 :         ns_def->definition.get_node_id ());
     421              : 
     422          688 :       if (pm_def.has_value ())
     423            0 :         mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
     424         1064 :     }
     425          404 : }
     426              : 
     427              : void
     428            1 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
     429              :                                     Analysis::Mappings &mappings,
     430              :                                     std::string &name)
     431              : {
     432            1 :   auto ns_def = ctx.resolve_path (attr.get_path (), Namespace::Macros);
     433            1 :   if (!ns_def.has_value ())
     434              :     {
     435              :       // FIXME: Change to proper error message
     436            0 :       collect_error (Error (attr.get_locus (),
     437              :                             "could not resolve attribute macro invocation %qs",
     438            0 :                             name.c_str ()));
     439            0 :       return;
     440              :     }
     441            1 :   auto pm_def = mappings.lookup_attribute_proc_macro_def (
     442            1 :     ns_def->definition.get_node_id ());
     443              : 
     444            1 :   if (!pm_def.has_value ())
     445              :     return;
     446              : 
     447            0 :   mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
     448            0 :                                                    pm_def.value ());
     449            1 : }
     450              : 
     451              : void
     452      2542204 : Early::visit (AST::Attribute &attr)
     453              : {
     454      2542204 :   auto &mappings = Analysis::Mappings::get ();
     455              : 
     456      2542204 :   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
     457      5084004 :   auto is_not_builtin = [&name] (AST::Attribute &attr) {
     458      2541800 :     return Analysis::BuiltinAttributeMappings::get ()
     459      2541800 :       ->lookup_builtin (name)
     460      2541800 :       .is_error ();
     461      2542204 :   };
     462              : 
     463      2542204 :   if (attr.is_derive ())
     464              :     {
     465          404 :       visit_derive_attribute (attr, mappings);
     466              :     }
     467      2541800 :   else if (is_not_builtin (attr)) // Do not resolve builtins
     468              :     {
     469            1 :       visit_non_builtin_attribute (attr, mappings, name);
     470              :     }
     471              : 
     472      2542204 :   DefaultResolver::visit (attr);
     473      2542204 : }
     474              : 
     475              : void
     476            0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
     477              : {
     478              :   // FIXME: We probably need to store namespace information
     479              : 
     480            0 :   auto import = mapping.import_kind.to_resolve;
     481            0 :   auto import_id = import.get_final_segment ().get_node_id ();
     482            0 :   auto data = mapping.data;
     483            0 :   auto identifier = import.get_final_segment ().get_segment_name ();
     484              : 
     485            0 :   for (auto &&definition : data.definitions ())
     486              :     {
     487            0 :       ctx.map_usage (Usage (import_id),
     488            0 :                      Definition (definition.definition.get_node_id ()),
     489              :                      definition.ns);
     490              : 
     491            0 :       toplevel.insert_or_error_out (identifier, import.get_locus (),
     492            0 :                                     definition.definition.get_node_id (),
     493              :                                     definition.ns);
     494              : 
     495            0 :       dirty = dirty || toplevel.is_dirty ();
     496            0 :     }
     497            0 : }
     498              : 
     499              : void
     500         3820 : Early::finalize_glob_import (NameResolutionContext &ctx,
     501              :                              const Early::ImportPair &mapping)
     502              : {
     503         7640 :   auto container = Analysis::Mappings::get ().lookup_glob_container (
     504         7640 :     mapping.data.container ().get_node_id ());
     505              : 
     506         3820 :   rust_assert (container);
     507              : 
     508         3820 :   if (mapping.import_kind.is_prelude)
     509              :     {
     510           37 :       rust_assert (container.value ()->get_glob_container_kind ()
     511              :                    == AST::GlobContainer::Kind::Module);
     512              : 
     513              :       // TODO: catch multiple attempted prelude imports
     514           37 :       if (!ctx.prelude)
     515            2 :         dirty = true;
     516              : 
     517           37 :       ctx.prelude = mapping.data.container ().get_node_id ();
     518              :     }
     519              : 
     520         3820 :   GlobbingVisitor glob_visit (ctx);
     521         3820 :   glob_visit.go (container.value ());
     522         3820 :   dirty |= glob_visit.is_dirty ();
     523         3820 : }
     524              : 
     525              : void
     526         7509 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
     527              : {
     528              :   // We can fetch the value here as `resolve_rebind` will only be called on
     529              :   // imports of the right kind
     530         7509 :   auto &path = mapping.import_kind.to_resolve;
     531         7509 :   auto &rebind = mapping.import_kind.rebind.value ();
     532         7509 :   auto data = mapping.data;
     533              : 
     534         7509 :   NodeId import_id = UNKNOWN_NODEID;
     535         7509 :   std::string declared_name;
     536              : 
     537              :   // FIXME: This needs to be done in `FinalizeImports`
     538         7509 :   switch (rebind.get_new_bind_type ())
     539              :     {
     540          393 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     541          393 :       declared_name = rebind.get_identifier ().as_string ();
     542          393 :       import_id = rebind.get_node_id ();
     543          393 :       break;
     544         7112 :     case AST::UseTreeRebind::NewBindType::NONE:
     545         7112 :       {
     546         7112 :         const auto &segments = path.get_segments ();
     547              :         // We don't want to insert `self` with `use module::self`
     548         7112 :         if (path.get_final_segment ().is_lower_self_seg ())
     549              :           {
     550              :             // Erroneous `self` or `{self}` use declaration
     551          100 :             if (segments.size () == 1)
     552              :               return;
     553           95 :             declared_name = segments[segments.size () - 2].as_string ();
     554           95 :             import_id = segments[segments.size () - 2].get_node_id ();
     555              :           }
     556              :         else
     557              :           {
     558         7012 :             declared_name = path.get_final_segment ().as_string ();
     559         7012 :             import_id = path.get_final_segment ().get_node_id ();
     560              :           }
     561              :         break;
     562              :       }
     563              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     564              :       // We don't want to insert it into the trie
     565              :       return;
     566              :     }
     567              : 
     568        15278 :   for (auto &&definition : data.definitions ())
     569              :     {
     570         7778 :       ctx.map_usage (Usage (import_id),
     571         7778 :                      Definition (definition.definition.get_node_id ()),
     572              :                      definition.ns);
     573              : 
     574        23334 :       toplevel.insert_or_error_out (declared_name, path.get_locus (),
     575         7778 :                                     definition.definition.get_node_id (),
     576              :                                     definition.ns);
     577              : 
     578         7778 :       dirty = dirty || toplevel.is_dirty ();
     579              : 
     580              :       // Map the import to the glob container if it exists - this is important
     581              :       // for 2-stepped glob imports which refer to glob containers, e.g.
     582              :       //
     583              :       // enum Foo { ... }
     584              :       // pub use Foo;
     585              :       // use self::Foo::*;
     586         7778 :       auto &mappings = Analysis::Mappings::get ();
     587         7778 :       if (auto container = mappings.lookup_glob_container (
     588         7778 :             definition.definition.get_node_id ()))
     589          545 :         mappings.insert_glob_container (import_id, container.value ());
     590         7500 :     }
     591        15018 : }
     592              : 
     593              : void
     594        25556 : Early::visit (AST::UseDeclaration &decl)
     595              : {
     596              :   // We do not want to visit the use trees, we're only looking for top level
     597              :   // rebind. eg. `use something;` or `use something::other;`
     598        25556 :   if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
     599              :     {
     600        15743 :       auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
     601        15743 :       if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
     602              :         {
     603            2 :           collect_error (
     604            1 :             Error (decl.get_locus (), ErrorCode::E0429,
     605            1 :                    "%<self%> imports are only allowed within a { } list"));
     606              :         }
     607              :     }
     608              : 
     609        25556 :   auto &imports = toplevel.get_imports_to_resolve ();
     610        25556 :   auto current_import = imports.find (decl.get_node_id ());
     611        25556 :   if (current_import != imports.end ())
     612              :     {
     613        25556 :       build_import_mapping (*current_import);
     614              :     }
     615              : 
     616              :   // Once this is done, we finalize their resolution
     617        36885 :   for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
     618        11329 :     switch (mapping.import_kind.kind)
     619              :       {
     620         3820 :       case TopLevel::ImportKind::Kind::Glob:
     621         3820 :         finalize_glob_import (ctx, mapping);
     622         3820 :         break;
     623            0 :       case TopLevel::ImportKind::Kind::Simple:
     624            0 :         finalize_simple_import (mapping);
     625            0 :         break;
     626         7509 :       case TopLevel::ImportKind::Kind::Rebind:
     627         7509 :         finalize_rebind_import (mapping);
     628         7509 :         break;
     629              :       }
     630              : 
     631        25556 :   DefaultResolver::visit (decl);
     632        25556 : }
     633              : 
     634              : void
     635         7500 : Early::visit (AST::UseTreeList &use_list)
     636              : {
     637         7500 :   if (!use_list.has_path ())
     638              :     {
     639           10 :       for (auto &&tree : use_list.get_trees ())
     640              :         {
     641            6 :           if (tree->get_kind () == AST::UseTree::Kind::Rebind)
     642              :             {
     643            6 :               auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
     644            6 :               auto path_size = rebind.get_path ().get_segments ().size ();
     645            6 :               if (path_size == 1
     646            6 :                   && rebind.get_path ()
     647            6 :                        .get_final_segment ()
     648            6 :                        .is_lower_self_seg ())
     649              :                 {
     650            4 :                   collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
     651              :                                         "%<self%> import can only appear in an "
     652            4 :                                         "import list with a non-empty prefix"));
     653              :                 }
     654              :             }
     655              :         }
     656              :     }
     657         7500 :   DefaultResolver::visit (use_list);
     658         7500 : }
     659              : 
     660              : void
     661       736411 : Early::visit (AST::IdentifierPattern &identifier)
     662              : {
     663              :   // check if this is *really* a path pattern
     664       736411 :   if (!identifier.get_is_ref () && !identifier.get_is_mut ()
     665      1439923 :       && !identifier.has_subpattern ())
     666              :     {
     667       702947 :       auto res = ctx.values.get (identifier.get_ident ());
     668       702947 :       if (res)
     669              :         {
     670          943 :           if (res->is_ambiguous ())
     671            0 :             rust_error_at (identifier.get_locus (), ErrorCode::E0659,
     672              :                            "%qs is ambiguous",
     673            0 :                            identifier.get_ident ().as_string ().c_str ());
     674              :           else
     675              :             {
     676              :               // HACK: bail out if the definition is a function
     677          943 :               if (!ctx.mappings.is_function_node (res->get_node_id ()))
     678          514 :                 ident_path_to_convert.insert (identifier.get_node_id ());
     679              :             }
     680              :         }
     681       702947 :     }
     682       736411 : }
     683              : 
     684              : } // namespace Resolver2_0
     685              : } // namespace Rust
        

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.