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: 88.2 % 323 285
Test Date: 2026-10-24 16:24:59 Functions: 92.6 % 27 25
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        11639 : Early::Early (NameResolutionContext &ctx)
      39        11639 :   : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
      40        11639 : {}
      41              : 
      42              : void
      43        61687 : Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
      44              : {
      45        61687 :   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        61687 :   if (!leaf_macro)
      49        61687 :     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        29349 : Early::insert_once (AST::MacroRulesDefinition &def)
      61              : {
      62        29349 :   if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
      63            1 :     ctx.mappings.insert_macro_def (&def);
      64        29349 : }
      65              : 
      66              : void
      67        11639 : Early::go (AST::Crate &crate)
      68              : {
      69              :   // First we go through TopLevel resolution to get all our declared items
      70        11639 :   toplevel.go (crate);
      71              : 
      72              :   // We start with resolving the list of imports that `TopLevel` has built for
      73              :   // us
      74              : 
      75        11639 :   dirty = toplevel.is_dirty ();
      76              : 
      77              :   // We now proceed with resolving macros, which can be nested in almost any
      78              :   // items
      79        11639 :   textual_scope.push ();
      80              : 
      81        11639 :   visit (crate);
      82              : 
      83        11639 :   textual_scope.pop ();
      84              : 
      85              :   // handle IdentifierPattern vs PathInExpression disambiguation
      86        11639 :   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
      87        11639 : }
      88              : 
      89              : bool
      90         4032 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
      91              : {
      92         4032 :   auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
      93         4032 :   if (!resolved.has_value ())
      94              :     return false;
      95              : 
      96         8060 :   auto result = Analysis::Mappings::get ().lookup_glob_container (
      97         4030 :     resolved->definition.get_node_id ());
      98              : 
      99         4030 :   if (!result)
     100              :     return false;
     101              : 
     102         4030 :   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         8060 :   imports.emplace_back (
     110        12090 :     ImportPair (std::move (glob), ImportData::Glob (resolved->definition)));
     111              : 
     112         4030 :   return true;
     113         4032 : }
     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        43004 : Early::resolve_rebind_import (NodeId use_dec_id,
     135              :                               TopLevel::ImportKind &&rebind_import)
     136              : {
     137        43004 :   NodeId import_id = UNKNOWN_NODEID;
     138        43004 :   auto &path = rebind_import.to_resolve;
     139        43004 :   auto &rebind = rebind_import.rebind.value ();
     140              : 
     141        43004 :   switch (rebind.get_new_bind_type ())
     142              :     {
     143          572 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     144          572 :       import_id = rebind.get_node_id ();
     145          572 :       break;
     146        42428 :     case AST::UseTreeRebind::NewBindType::NONE:
     147        42428 :       import_id = path.get_final_segment ().get_node_id ();
     148        42428 :       break;
     149              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     150              :       // nothing
     151              :       break;
     152              :     }
     153              : 
     154        43004 :   if (ctx.lookup (import_id, Namespace::Types))
     155              :     return true;
     156              : 
     157         8842 :   auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
     158              : 
     159              :   // if we've found at least one definition, then we're good
     160         8842 :   if (definitions.empty ())
     161              :     return false;
     162        17518 :   for (const auto &def : definitions)
     163              :     {
     164         8976 :       if (def.definition.is_ambiguous ())
     165              :         {
     166            1 :           rich_location rich_locus (line_table,
     167            1 :                                     rebind_import.to_resolve.get_locus ());
     168            1 :           rust_error_at (rich_locus, ErrorCode::E0659, "%qs is ambiguous",
     169            1 :                          rebind_import.to_resolve.as_string ().c_str ());
     170            1 :           return true;
     171            1 :         }
     172              :     }
     173              : 
     174         8542 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     175              : 
     176         8542 :   imports.emplace_back (
     177         8542 :     ImportPair (std::move (rebind_import),
     178        17084 :                 ImportData::Rebind (std::move (definitions))));
     179              : 
     180         8542 :   return true;
     181         8842 : }
     182              : 
     183              : void
     184        27562 : Early::build_import_mapping (
     185              :   std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
     186              : {
     187        27562 :   auto found = false;
     188        27562 :   auto use_dec_id = use_import.first;
     189              : 
     190        74598 :   for (auto &&import : use_import.second)
     191              :     {
     192              :       // We create a copy of the path in case of errors, since the `import` will
     193              :       // be moved into the newly created import mappings
     194        47036 :       auto path = import.to_resolve;
     195              : 
     196              :       // used to skip the "unresolved import" error
     197              :       // if we output other errors during resolution
     198        47036 :       size_t old_error_count = macro_resolve_errors.size ();
     199              : 
     200        47036 :       switch (import.kind)
     201              :         {
     202         4032 :         case TopLevel::ImportKind::Kind::Glob:
     203         4032 :           found = resolve_glob_import (use_dec_id, std::move (import));
     204         4032 :           break;
     205            0 :         case TopLevel::ImportKind::Kind::Simple:
     206            0 :           found = resolve_simple_import (use_dec_id, std::move (import));
     207            0 :           break;
     208        43004 :         case TopLevel::ImportKind::Kind::Rebind:
     209        43004 :           found = resolve_rebind_import (use_dec_id, std::move (import));
     210        43004 :           break;
     211              :         }
     212              : 
     213        47036 :       if (!found && old_error_count == macro_resolve_errors.size ())
     214          598 :         collect_error (Error (path.get_final_segment ().get_locus (),
     215              :                               ErrorCode::E0433, "unresolved import %qs",
     216          598 :                               path.as_string ().c_str ()));
     217        47036 :     }
     218        27562 : }
     219              : 
     220              : void
     221       653302 : Early::TextualScope::push ()
     222              : {
     223              :   // push a new empty scope
     224       653302 :   scopes.emplace_back ();
     225       653302 : }
     226              : 
     227              : void
     228       653302 : Early::TextualScope::pop ()
     229              : {
     230       653302 :   rust_assert (!scopes.empty ());
     231              : 
     232       653302 :   scopes.pop_back ();
     233       653302 : }
     234              : 
     235              : void
     236        29349 : Early::TextualScope::insert (std::string name, NodeId id)
     237              : {
     238        29349 :   rust_assert (!scopes.empty ());
     239              : 
     240              :   // we can ignore the return value as we always want the latest defined macro
     241              :   // to shadow a previous one - so if two macros have the same name and get
     242              :   // inserted with the same key, it's not a bug
     243        58698 :   scopes.back ().insert ({name, id});
     244        29349 : }
     245              : 
     246              : tl::optional<NodeId>
     247        61572 : Early::TextualScope::get (const std::string &name)
     248              : {
     249        83833 :   for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
     250              :     {
     251        77958 :       auto scope = *iterator;
     252        77958 :       auto found = scope.find (name);
     253        77958 :       if (found != scope.end ())
     254        55697 :         return found->second;
     255        77958 :     }
     256              : 
     257         5875 :   return tl::nullopt;
     258              : }
     259              : 
     260              : void
     261        29349 : Early::visit (AST::MacroRulesDefinition &def)
     262              : {
     263        29349 :   DefaultResolver::visit (def);
     264              : 
     265        58698 :   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
     266        29349 :   insert_once (def);
     267        29349 : }
     268              : 
     269              : void
     270       629800 : Early::visit (AST::BlockExpr &block)
     271              : {
     272       629800 :   textual_scope.push ();
     273              : 
     274       629800 :   DefaultResolver::visit (block);
     275              : 
     276       629800 :   textual_scope.pop ();
     277       629800 : }
     278              : 
     279              : void
     280        12214 : Early::visit (AST::Module &module)
     281              : {
     282        12214 :   bool is_macro_use = false;
     283              : 
     284        15278 :   for (const auto &attr : module.get_outer_attrs ())
     285              :     {
     286         3415 :       if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
     287              :         {
     288              :           is_macro_use = true;
     289              :           break;
     290              :         }
     291              :     }
     292              : 
     293        12214 :   if (!is_macro_use)
     294        11863 :     textual_scope.push ();
     295              : 
     296        12214 :   DefaultResolver::visit (module);
     297              : 
     298        12214 :   if (!is_macro_use)
     299        11863 :     textual_scope.pop ();
     300        12214 : }
     301              : 
     302              : void
     303        23853 : Early::maybe_prelude_import ()
     304              : {
     305              :   // handle prelude import
     306        23853 :   if (ctx.prelude)
     307              :     {
     308        16596 :       auto container = Analysis::Mappings::get ().lookup_glob_container (
     309         8298 :         ctx.prelude.value ());
     310         8298 :       rust_assert (container);
     311              : 
     312         8298 :       GlobbingVisitor glob_visit (ctx);
     313         8298 :       glob_visit.go (container.value ());
     314         8298 :       dirty |= glob_visit.is_dirty ();
     315              :     }
     316        23853 : }
     317              : 
     318              : void
     319        61810 : Early::visit (AST::MacroInvocation &invoc)
     320              : {
     321        61810 :   auto &path = invoc.get_invoc_data ().get_path ();
     322              : 
     323              :   // We special case the `offset_of!()` macro if the flag is here, otherwise
     324              :   // we accept whatever `offset_of!()` definition we resolved to.
     325        61810 :   auto resolve_offset_of = Session::get_instance ().should_support_offset_of ()
     326        61810 :                            && (path.as_string () == "offset_of");
     327              : 
     328              :   // Ditto, but for `cfg_select!()`.
     329        61810 :   auto resolve_cfg_select
     330        61810 :     = Session::get_instance ().should_support_cfg_select ()
     331        61810 :       && (path.as_string () == "cfg_select");
     332              : 
     333        61810 :   if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
     334         4236 :     for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
     335         2866 :       pending_invoc->accept_vis (*this);
     336              : 
     337              :   // When a macro is invoked by an unqualified identifier (not part of a
     338              :   // multi-part path), it is first looked up in textual scoping. If this does
     339              :   // not yield any results, then it is looked up in path-based scoping. If the
     340              :   // macro's name is qualified with a path, then it is only looked up in
     341              :   // path-based scoping.
     342              : 
     343              :   // https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
     344              : 
     345        61810 :   tl::optional<NameResolutionContext::NamespacedDefinition> ns_def
     346              :     = tl::nullopt;
     347        61810 :   if (path.get_segments ().size () == 1)
     348        61572 :     ns_def = textual_scope.get (path.get_final_segment ().as_string ())
     349       123144 :                .map ([] (NodeId id) {
     350        55697 :                  return NameResolutionContext::NamespacedDefinition (
     351        55697 :                    Rib::Definition::NonShadowable (id), Namespace::Macros);
     352        61572 :                });
     353              : 
     354              :   // we won't have changed `definition` from `nullopt` if there are more
     355              :   // than one segments in our path
     356        61810 :   if (!ns_def.has_value ())
     357        12103 :     ns_def = ctx.resolve_path (path, Namespace::Macros);
     358              : 
     359              :   // if the definition still does not have a value, then it's an error - unless
     360              :   // we should automatically resolve offset_of!() or cfg_select!() calls
     361        61810 :   if (!ns_def.has_value ())
     362              :     {
     363          123 :       if (!resolve_offset_of && !resolve_cfg_select)
     364           76 :         collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
     365              :                               "could not resolve macro invocation %qs",
     366          152 :                               path.as_string ().c_str ()));
     367              :       return;
     368              :     }
     369              : 
     370        61687 :   try_insert_once (invoc, ns_def->definition.get_node_id ());
     371              : 
     372              :   // now do we need to keep mappings or something? or insert "uses" into our
     373              :   // ForeverStack? can we do that? are mappings simpler?
     374        61687 :   auto &mappings = Analysis::Mappings::get ();
     375        61687 :   auto rules_def
     376        61687 :     = mappings.lookup_macro_def (ns_def->definition.get_node_id ());
     377              : 
     378              :   // Macro definition not found, maybe it is not expanded yet.
     379        61687 :   if (!rules_def)
     380              :     return;
     381              : 
     382        61687 :   if (mappings.lookup_macro_invocation (invoc))
     383              :     return;
     384              : 
     385        61687 :   mappings.insert_macro_invocation (invoc, rules_def.value ());
     386        61810 : }
     387              : 
     388              : void
     389          500 : Early::visit_derive_attribute (AST::Attribute &attr,
     390              :                                Analysis::Mappings &mappings)
     391              : {
     392          500 :   auto traits = attr.get_traits_to_derive ();
     393         1827 :   for (auto &trait : traits)
     394              :     {
     395              :       // Special case CoercePointee if we're in a proper compatibility mode.
     396              :       // Count it as a builtin derive macro and keep going.
     397         1327 :       if (trait.get ().as_string () == "CoercePointee"
     398         1327 :           && Session::get_instance ().should_support_coerce_pointee ())
     399            2 :         continue;
     400              : 
     401         1325 :       auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
     402         1325 :       if (!ns_def.has_value ())
     403              :         {
     404              :           // FIXME: Change to proper error message
     405         1078 :           collect_error (Error (trait.get ().get_locus (),
     406              :                                 "could not resolve trait %qs",
     407          539 :                                 trait.get ().as_string ().c_str ()));
     408          539 :           continue;
     409              :         }
     410              : 
     411          786 :       auto pm_def = mappings.pmacro.definitions.derives.lookup (
     412          786 :         ns_def->definition.get_node_id ());
     413              : 
     414          786 :       if (pm_def.has_value ())
     415            0 :         mappings.pmacro.invocations.derives.insert (trait.get ().get_node_id (),
     416            0 :                                                     pm_def.value ());
     417         1327 :     }
     418          500 : }
     419              : 
     420              : void
     421            2 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
     422              :                                     Analysis::Mappings &mappings,
     423              :                                     std::string &name)
     424              : {
     425            2 :   auto ns_def = ctx.resolve_path (attr.get_path (), Namespace::Macros);
     426            2 :   if (!ns_def.has_value ())
     427              :     {
     428              :       // FIXME: Change to proper error message
     429            2 :       collect_error (Error (attr.get_locus (),
     430              :                             "could not resolve attribute macro invocation %qs",
     431            1 :                             name.c_str ()));
     432            1 :       return;
     433              :     }
     434            1 :   auto pm_def = mappings.pmacro.definitions.attributes.lookup (
     435            1 :     ns_def->definition.get_node_id ());
     436              : 
     437            1 :   if (!pm_def.has_value ())
     438              :     return;
     439              : 
     440            0 :   mappings.pmacro.invocations.attributes.insert (
     441            0 :     attr.get_path ().get_node_id (), pm_def.value ());
     442            2 : }
     443              : 
     444              : void
     445      2601452 : Early::visit (AST::Attribute &attr)
     446              : {
     447      2601452 :   auto &mappings = Analysis::Mappings::get ();
     448              : 
     449      2601452 :   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
     450      2601452 :   auto known_check = Analysis::Attributes::is_known (name);
     451              : 
     452              :   // If it is a tool attribute, the compiler can ignore it and let the tool
     453              :   // handle it
     454      2601452 :   if (known_check == Analysis::Attributes::AttributeKnowledge::Tool)
     455            0 :     return;
     456              : 
     457      2601452 :   auto is_builtin
     458              :     = known_check == Analysis::Attributes::AttributeKnowledge::Known;
     459              : 
     460      2601452 :   if (attr.is_derive ())
     461              :     {
     462          500 :       visit_derive_attribute (attr, mappings);
     463              :     }
     464      2600952 :   else if (!is_builtin) // Do not resolve builtins
     465              :     {
     466            2 :       visit_non_builtin_attribute (attr, mappings, name);
     467              :     }
     468              : 
     469      2601452 :   DefaultResolver::visit (attr);
     470      2601452 : }
     471              : 
     472              : void
     473            0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
     474              : {
     475              :   // FIXME: We probably need to store namespace information
     476              : 
     477            0 :   auto import = mapping.import_kind.to_resolve;
     478            0 :   auto import_id = import.get_final_segment ().get_node_id ();
     479            0 :   auto data = mapping.data;
     480            0 :   auto identifier = import.get_final_segment ().get_segment_name ();
     481              : 
     482            0 :   for (auto &&definition : data.definitions ())
     483              :     {
     484            0 :       ctx.map_usage (Usage (import_id),
     485            0 :                      Definition (definition.definition.get_node_id ()),
     486              :                      definition.ns);
     487              : 
     488            0 :       toplevel.insert_or_error_out (identifier, import.get_locus (),
     489            0 :                                     definition.definition.get_node_id (),
     490              :                                     definition.ns);
     491              : 
     492            0 :       dirty = dirty || toplevel.is_dirty ();
     493            0 :     }
     494            0 : }
     495              : 
     496              : void
     497         4030 : Early::finalize_glob_import (NameResolutionContext &ctx,
     498              :                              const Early::ImportPair &mapping)
     499              : {
     500         8060 :   auto container = Analysis::Mappings::get ().lookup_glob_container (
     501         8060 :     mapping.data.container ().get_node_id ());
     502              : 
     503         4030 :   rust_assert (container);
     504              : 
     505         4030 :   if (mapping.import_kind.is_prelude)
     506              :     {
     507           37 :       rust_assert (container.value ()->get_glob_container_kind ()
     508              :                    == AST::GlobContainer::Kind::Module);
     509              : 
     510              :       // TODO: catch multiple attempted prelude imports
     511           37 :       if (!ctx.prelude)
     512            2 :         dirty = true;
     513              : 
     514           37 :       ctx.prelude = mapping.data.container ().get_node_id ();
     515              :     }
     516              : 
     517         4030 :   GlobbingVisitor glob_visit (ctx);
     518         4030 :   glob_visit.go (container.value ());
     519         4030 :   dirty |= glob_visit.is_dirty ();
     520         4030 : }
     521              : 
     522              : void
     523         8542 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
     524              : {
     525              :   // We can fetch the value here as `resolve_rebind` will only be called on
     526              :   // imports of the right kind
     527         8542 :   auto &path = mapping.import_kind.to_resolve;
     528         8542 :   auto &rebind = mapping.import_kind.rebind.value ();
     529         8542 :   auto data = mapping.data;
     530              : 
     531         8542 :   NodeId import_id = UNKNOWN_NODEID;
     532         8542 :   std::string declared_name;
     533              : 
     534              :   // FIXME: This needs to be done in `FinalizeImports`
     535         8542 :   switch (rebind.get_new_bind_type ())
     536              :     {
     537          394 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     538          394 :       declared_name = rebind.get_identifier ().as_string ();
     539          394 :       import_id = rebind.get_node_id ();
     540          394 :       break;
     541         8144 :     case AST::UseTreeRebind::NewBindType::NONE:
     542         8144 :       {
     543         8144 :         const auto &segments = path.get_segments ();
     544              :         // We don't want to insert `self` with `use module::self`
     545         8144 :         if (path.get_final_segment ().is_lower_self_seg ())
     546              :           {
     547              :             // Erroneous `self` or `{self}` use declaration
     548          155 :             if (segments.size () == 1)
     549            6 :               return;
     550              : 
     551          153 :             auto pre_self_segment = segments.rbegin () + 1;
     552              : 
     553          153 :             declared_name = pre_self_segment->as_string ();
     554          153 :             import_id = pre_self_segment->get_node_id ();
     555              :           }
     556              :         else
     557              :           {
     558         7989 :             declared_name = path.get_final_segment ().as_string ();
     559         7989 :             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        17505 :   for (auto &&definition : data.definitions ())
     569              :     {
     570         8969 :       ctx.map_usage (Usage (import_id),
     571         8969 :                      Definition (definition.definition.get_node_id ()),
     572              :                      definition.ns);
     573              : 
     574        26907 :       toplevel.insert_or_error_out (declared_name, path.get_locus (),
     575         8969 :                                     definition.definition.get_node_id (),
     576              :                                     definition.ns);
     577              : 
     578         8969 :       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         8969 :       auto &mappings = Analysis::Mappings::get ();
     587         8969 :       if (auto container = mappings.lookup_glob_container (
     588         8969 :             definition.definition.get_node_id ()))
     589          713 :         mappings.insert_glob_container (import_id, container.value ());
     590         8536 :     }
     591        17084 : }
     592              : 
     593              : void
     594        27564 : 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        27564 :   if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
     599              :     {
     600        16866 :       auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
     601        16866 :       if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
     602              :         {
     603            4 :           collect_error (
     604            2 :             Error (rebind.get_path ().get_final_segment ().get_locus (),
     605              :                    ErrorCode::E0429,
     606            2 :                    "%<self%> imports are only allowed within a { } list"));
     607              :           // We must not continue, malformed use declaration must not be
     608              :           // finalized.
     609            2 :           return;
     610              :         }
     611              :     }
     612              : 
     613        27562 :   auto &imports = toplevel.get_imports_to_resolve ();
     614        27562 :   auto current_import = imports.find (decl.get_node_id ());
     615        27562 :   if (current_import != imports.end ())
     616              :     {
     617        27562 :       build_import_mapping (*current_import);
     618              :     }
     619              : 
     620              :   // Once this is done, we finalize their resolution
     621        40134 :   for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
     622        12572 :     switch (mapping.import_kind.kind)
     623              :       {
     624         4030 :       case TopLevel::ImportKind::Kind::Glob:
     625         4030 :         finalize_glob_import (ctx, mapping);
     626         4030 :         break;
     627            0 :       case TopLevel::ImportKind::Kind::Simple:
     628            0 :         finalize_simple_import (mapping);
     629            0 :         break;
     630         8542 :       case TopLevel::ImportKind::Kind::Rebind:
     631         8542 :         finalize_rebind_import (mapping);
     632         8542 :         break;
     633              :       }
     634              : 
     635        27562 :   DefaultResolver::visit (decl);
     636              : }
     637              : 
     638              : void
     639         8215 : Early::visit (AST::UseTreeList &use_list)
     640              : {
     641         8215 :   if (!use_list.has_path ())
     642              :     {
     643           10 :       for (auto &&tree : use_list.get_trees ())
     644              :         {
     645            6 :           if (tree->get_kind () == AST::UseTree::Kind::Rebind)
     646              :             {
     647            6 :               auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
     648            6 :               auto path_size = rebind.get_path ().get_segments ().size ();
     649            6 :               if (path_size == 1
     650            6 :                   && rebind.get_path ()
     651            6 :                        .get_final_segment ()
     652            6 :                        .is_lower_self_seg ())
     653              :                 {
     654            4 :                   collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
     655              :                                         "%<self%> import can only appear in an "
     656            4 :                                         "import list with a non-empty prefix"));
     657              :                 }
     658              :             }
     659              :         }
     660              :     }
     661         8215 :   DefaultResolver::visit (use_list);
     662         8215 : }
     663              : 
     664              : void
     665       753781 : Early::visit (AST::IdentifierPattern &identifier)
     666              : {
     667              :   // check if this is *really* a path pattern
     668       753781 :   if (!identifier.get_is_ref () && !identifier.get_is_mut ()
     669      1473254 :       && !identifier.has_subpattern ())
     670              :     {
     671       718888 :       auto res = ctx.values.get (identifier.get_ident ());
     672       718888 :       if (res)
     673              :         {
     674         1021 :           if (res->is_ambiguous ())
     675            0 :             rust_error_at (identifier.get_locus (), ErrorCode::E0659,
     676              :                            "%qs is ambiguous",
     677            0 :                            identifier.get_ident ().as_string ().c_str ());
     678              :           else
     679              :             {
     680              :               // HACK: bail out if the definition is a function
     681         1021 :               if (!ctx.mappings.is_function_node (res->get_node_id ()))
     682          578 :                 ident_path_to_convert.insert (identifier.get_node_id ());
     683              :             }
     684              :         }
     685       718888 :     }
     686       753781 : }
     687              : 
     688              : } // namespace Resolver2_0
     689              : } // namespace Rust
        

Generated by: LCOV version 2.5.0-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.