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.4 % 319 282
Test Date: 2026-10-03 16:17:38 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        11495 : Early::Early (NameResolutionContext &ctx)
      39        11495 :   : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
      40        11495 : {}
      41              : 
      42              : void
      43        61696 : Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
      44              : {
      45        61696 :   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        61696 :   if (!leaf_macro)
      49        61696 :     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        29365 : Early::insert_once (AST::MacroRulesDefinition &def)
      61              : {
      62        29365 :   if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
      63            1 :     ctx.mappings.insert_macro_def (&def);
      64        29365 : }
      65              : 
      66              : void
      67        11495 : Early::go (AST::Crate &crate)
      68              : {
      69              :   // First we go through TopLevel resolution to get all our declared items
      70        11495 :   toplevel.go (crate);
      71              : 
      72              :   // We start with resolving the list of imports that `TopLevel` has built for
      73              :   // us
      74              : 
      75        11495 :   dirty = toplevel.is_dirty ();
      76              : 
      77              :   // We now proceed with resolving macros, which can be nested in almost any
      78              :   // items
      79        11495 :   textual_scope.push ();
      80              : 
      81        11495 :   visit (crate);
      82              : 
      83        11495 :   textual_scope.pop ();
      84              : 
      85              :   // handle IdentifierPattern vs PathInExpression disambiguation
      86        11495 :   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
      87        11495 : }
      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       652592 : Early::TextualScope::push ()
     222              : {
     223              :   // push a new empty scope
     224       652592 :   scopes.emplace_back ();
     225       652592 : }
     226              : 
     227              : void
     228       652592 : Early::TextualScope::pop ()
     229              : {
     230       652592 :   rust_assert (!scopes.empty ());
     231              : 
     232       652592 :   scopes.pop_back ();
     233       652592 : }
     234              : 
     235              : void
     236        29365 : Early::TextualScope::insert (std::string name, NodeId id)
     237              : {
     238        29365 :   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        58730 :   scopes.back ().insert ({name, id});
     244        29365 : }
     245              : 
     246              : tl::optional<NodeId>
     247        61581 : Early::TextualScope::get (const std::string &name)
     248              : {
     249        83842 :   for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
     250              :     {
     251        77967 :       auto scope = *iterator;
     252        77967 :       auto found = scope.find (name);
     253        77967 :       if (found != scope.end ())
     254        55706 :         return found->second;
     255        77967 :     }
     256              : 
     257         5875 :   return tl::nullopt;
     258              : }
     259              : 
     260              : void
     261        29365 : Early::visit (AST::MacroRulesDefinition &def)
     262              : {
     263        29365 :   DefaultResolver::visit (def);
     264              : 
     265        58730 :   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
     266        29365 :   insert_once (def);
     267        29365 : }
     268              : 
     269              : void
     270       629238 : Early::visit (AST::BlockExpr &block)
     271              : {
     272       629238 :   textual_scope.push ();
     273              : 
     274       629238 :   DefaultResolver::visit (block);
     275              : 
     276       629238 :   textual_scope.pop ();
     277       629238 : }
     278              : 
     279              : void
     280        12210 : Early::visit (AST::Module &module)
     281              : {
     282        12210 :   bool is_macro_use = false;
     283              : 
     284        15274 :   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        12210 :   if (!is_macro_use)
     294        11859 :     textual_scope.push ();
     295              : 
     296        12210 :   DefaultResolver::visit (module);
     297              : 
     298        12210 :   if (!is_macro_use)
     299        11859 :     textual_scope.pop ();
     300        12210 : }
     301              : 
     302              : void
     303        23705 : Early::maybe_prelude_import ()
     304              : {
     305              :   // handle prelude import
     306        23705 :   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        23705 : }
     317              : 
     318              : void
     319        61819 : Early::visit (AST::MacroInvocation &invoc)
     320              : {
     321        61819 :   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        61819 :   auto resolve_offset_of = Session::get_instance ().should_support_offset_of ()
     326        61819 :                            && (path.as_string () == "offset_of");
     327              : 
     328              :   // Ditto, but for `cfg_select!()`.
     329        61819 :   auto resolve_cfg_select
     330        61819 :     = Session::get_instance ().should_support_cfg_select ()
     331        61819 :       && (path.as_string () == "cfg_select");
     332              : 
     333        61819 :   if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
     334         4242 :     for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
     335         2870 :       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        61819 :   tl::optional<NameResolutionContext::NamespacedDefinition> ns_def
     346              :     = tl::nullopt;
     347        61819 :   if (path.get_segments ().size () == 1)
     348        61581 :     ns_def = textual_scope.get (path.get_final_segment ().as_string ())
     349       123162 :                .map ([] (NodeId id) {
     350        55706 :                  return NameResolutionContext::NamespacedDefinition (
     351        55706 :                    Rib::Definition::NonShadowable (id), Namespace::Macros);
     352        61581 :                });
     353              : 
     354              :   // we won't have changed `definition` from `nullopt` if there are more
     355              :   // than one segments in our path
     356        61819 :   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        61819 :   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        61696 :   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        61696 :   auto &mappings = Analysis::Mappings::get ();
     375        61696 :   auto rules_def
     376        61696 :     = mappings.lookup_macro_def (ns_def->definition.get_node_id ());
     377              : 
     378              :   // Macro definition not found, maybe it is not expanded yet.
     379        61696 :   if (!rules_def)
     380              :     return;
     381              : 
     382        61696 :   if (mappings.lookup_macro_invocation (invoc))
     383              :     return;
     384              : 
     385        61696 :   mappings.insert_macro_invocation (invoc, rules_def.value ());
     386        61819 : }
     387              : 
     388              : void
     389          496 : Early::visit_derive_attribute (AST::Attribute &attr,
     390              :                                Analysis::Mappings &mappings)
     391              : {
     392          496 :   auto traits = attr.get_traits_to_derive ();
     393         1819 :   for (auto &trait : traits)
     394              :     {
     395         1323 :       auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
     396         1323 :       if (!ns_def.has_value ())
     397              :         {
     398              :           // FIXME: Change to proper error message
     399         1074 :           collect_error (Error (trait.get ().get_locus (),
     400              :                                 "could not resolve trait %qs",
     401          537 :                                 trait.get ().as_string ().c_str ()));
     402          537 :           continue;
     403              :         }
     404              : 
     405          786 :       auto pm_def = mappings.lookup_derive_proc_macro_def (
     406          786 :         ns_def->definition.get_node_id ());
     407              : 
     408          786 :       if (pm_def.has_value ())
     409            0 :         mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
     410         1323 :     }
     411          496 : }
     412              : 
     413              : void
     414            2 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
     415              :                                     Analysis::Mappings &mappings,
     416              :                                     std::string &name)
     417              : {
     418            2 :   auto ns_def = ctx.resolve_path (attr.get_path (), Namespace::Macros);
     419            2 :   if (!ns_def.has_value ())
     420              :     {
     421              :       // FIXME: Change to proper error message
     422            2 :       collect_error (Error (attr.get_locus (),
     423              :                             "could not resolve attribute macro invocation %qs",
     424            1 :                             name.c_str ()));
     425            1 :       return;
     426              :     }
     427            1 :   auto pm_def = mappings.lookup_attribute_proc_macro_def (
     428            1 :     ns_def->definition.get_node_id ());
     429              : 
     430            1 :   if (!pm_def.has_value ())
     431              :     return;
     432              : 
     433            0 :   mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
     434            0 :                                                    pm_def.value ());
     435            2 : }
     436              : 
     437              : void
     438      2600978 : Early::visit (AST::Attribute &attr)
     439              : {
     440      2600978 :   auto &mappings = Analysis::Mappings::get ();
     441              : 
     442      2600978 :   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
     443      2600978 :   auto known_check = Analysis::Attributes::is_known (name);
     444              : 
     445              :   // If it is a tool attribute, the compiler can ignore it and let the tool
     446              :   // handle it
     447      2600978 :   if (known_check == Analysis::Attributes::AttributeKnowledge::Tool)
     448            0 :     return;
     449              : 
     450      2600978 :   auto is_builtin
     451              :     = known_check == Analysis::Attributes::AttributeKnowledge::Known;
     452              : 
     453      2600978 :   if (attr.is_derive ())
     454              :     {
     455          496 :       visit_derive_attribute (attr, mappings);
     456              :     }
     457      2600482 :   else if (!is_builtin) // Do not resolve builtins
     458              :     {
     459            2 :       visit_non_builtin_attribute (attr, mappings, name);
     460              :     }
     461              : 
     462      2600978 :   DefaultResolver::visit (attr);
     463      2600978 : }
     464              : 
     465              : void
     466            0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
     467              : {
     468              :   // FIXME: We probably need to store namespace information
     469              : 
     470            0 :   auto import = mapping.import_kind.to_resolve;
     471            0 :   auto import_id = import.get_final_segment ().get_node_id ();
     472            0 :   auto data = mapping.data;
     473            0 :   auto identifier = import.get_final_segment ().get_segment_name ();
     474              : 
     475            0 :   for (auto &&definition : data.definitions ())
     476              :     {
     477            0 :       ctx.map_usage (Usage (import_id),
     478            0 :                      Definition (definition.definition.get_node_id ()),
     479              :                      definition.ns);
     480              : 
     481            0 :       toplevel.insert_or_error_out (identifier, import.get_locus (),
     482            0 :                                     definition.definition.get_node_id (),
     483              :                                     definition.ns);
     484              : 
     485            0 :       dirty = dirty || toplevel.is_dirty ();
     486            0 :     }
     487            0 : }
     488              : 
     489              : void
     490         4030 : Early::finalize_glob_import (NameResolutionContext &ctx,
     491              :                              const Early::ImportPair &mapping)
     492              : {
     493         8060 :   auto container = Analysis::Mappings::get ().lookup_glob_container (
     494         8060 :     mapping.data.container ().get_node_id ());
     495              : 
     496         4030 :   rust_assert (container);
     497              : 
     498         4030 :   if (mapping.import_kind.is_prelude)
     499              :     {
     500           37 :       rust_assert (container.value ()->get_glob_container_kind ()
     501              :                    == AST::GlobContainer::Kind::Module);
     502              : 
     503              :       // TODO: catch multiple attempted prelude imports
     504           37 :       if (!ctx.prelude)
     505            2 :         dirty = true;
     506              : 
     507           37 :       ctx.prelude = mapping.data.container ().get_node_id ();
     508              :     }
     509              : 
     510         4030 :   GlobbingVisitor glob_visit (ctx);
     511         4030 :   glob_visit.go (container.value ());
     512         4030 :   dirty |= glob_visit.is_dirty ();
     513         4030 : }
     514              : 
     515              : void
     516         8542 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
     517              : {
     518              :   // We can fetch the value here as `resolve_rebind` will only be called on
     519              :   // imports of the right kind
     520         8542 :   auto &path = mapping.import_kind.to_resolve;
     521         8542 :   auto &rebind = mapping.import_kind.rebind.value ();
     522         8542 :   auto data = mapping.data;
     523              : 
     524         8542 :   NodeId import_id = UNKNOWN_NODEID;
     525         8542 :   std::string declared_name;
     526              : 
     527              :   // FIXME: This needs to be done in `FinalizeImports`
     528         8542 :   switch (rebind.get_new_bind_type ())
     529              :     {
     530          394 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     531          394 :       declared_name = rebind.get_identifier ().as_string ();
     532          394 :       import_id = rebind.get_node_id ();
     533          394 :       break;
     534         8144 :     case AST::UseTreeRebind::NewBindType::NONE:
     535         8144 :       {
     536         8144 :         const auto &segments = path.get_segments ();
     537              :         // We don't want to insert `self` with `use module::self`
     538         8144 :         if (path.get_final_segment ().is_lower_self_seg ())
     539              :           {
     540              :             // Erroneous `self` or `{self}` use declaration
     541          155 :             if (segments.size () == 1)
     542            6 :               return;
     543              : 
     544          153 :             auto pre_self_segment = segments.rbegin () + 1;
     545              : 
     546          153 :             declared_name = pre_self_segment->as_string ();
     547          153 :             import_id = pre_self_segment->get_node_id ();
     548              :           }
     549              :         else
     550              :           {
     551         7989 :             declared_name = path.get_final_segment ().as_string ();
     552         7989 :             import_id = path.get_final_segment ().get_node_id ();
     553              :           }
     554              :         break;
     555              :       }
     556              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     557              :       // We don't want to insert it into the trie
     558              :       return;
     559              :     }
     560              : 
     561        17505 :   for (auto &&definition : data.definitions ())
     562              :     {
     563         8969 :       ctx.map_usage (Usage (import_id),
     564         8969 :                      Definition (definition.definition.get_node_id ()),
     565              :                      definition.ns);
     566              : 
     567        26907 :       toplevel.insert_or_error_out (declared_name, path.get_locus (),
     568         8969 :                                     definition.definition.get_node_id (),
     569              :                                     definition.ns);
     570              : 
     571         8969 :       dirty = dirty || toplevel.is_dirty ();
     572              : 
     573              :       // Map the import to the glob container if it exists - this is important
     574              :       // for 2-stepped glob imports which refer to glob containers, e.g.
     575              :       //
     576              :       // enum Foo { ... }
     577              :       // pub use Foo;
     578              :       // use self::Foo::*;
     579         8969 :       auto &mappings = Analysis::Mappings::get ();
     580         8969 :       if (auto container = mappings.lookup_glob_container (
     581         8969 :             definition.definition.get_node_id ()))
     582          713 :         mappings.insert_glob_container (import_id, container.value ());
     583         8536 :     }
     584        17084 : }
     585              : 
     586              : void
     587        27564 : Early::visit (AST::UseDeclaration &decl)
     588              : {
     589              :   // We do not want to visit the use trees, we're only looking for top level
     590              :   // rebind. eg. `use something;` or `use something::other;`
     591        27564 :   if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
     592              :     {
     593        16866 :       auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
     594        16866 :       if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
     595              :         {
     596            4 :           collect_error (
     597            2 :             Error (rebind.get_path ().get_final_segment ().get_locus (),
     598              :                    ErrorCode::E0429,
     599            2 :                    "%<self%> imports are only allowed within a { } list"));
     600              :           // We must not continue, malformed use declaration must not be
     601              :           // finalized.
     602            2 :           return;
     603              :         }
     604              :     }
     605              : 
     606        27562 :   auto &imports = toplevel.get_imports_to_resolve ();
     607        27562 :   auto current_import = imports.find (decl.get_node_id ());
     608        27562 :   if (current_import != imports.end ())
     609              :     {
     610        27562 :       build_import_mapping (*current_import);
     611              :     }
     612              : 
     613              :   // Once this is done, we finalize their resolution
     614        40134 :   for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
     615        12572 :     switch (mapping.import_kind.kind)
     616              :       {
     617         4030 :       case TopLevel::ImportKind::Kind::Glob:
     618         4030 :         finalize_glob_import (ctx, mapping);
     619         4030 :         break;
     620            0 :       case TopLevel::ImportKind::Kind::Simple:
     621            0 :         finalize_simple_import (mapping);
     622            0 :         break;
     623         8542 :       case TopLevel::ImportKind::Kind::Rebind:
     624         8542 :         finalize_rebind_import (mapping);
     625         8542 :         break;
     626              :       }
     627              : 
     628        27562 :   DefaultResolver::visit (decl);
     629              : }
     630              : 
     631              : void
     632         8215 : Early::visit (AST::UseTreeList &use_list)
     633              : {
     634         8215 :   if (!use_list.has_path ())
     635              :     {
     636           10 :       for (auto &&tree : use_list.get_trees ())
     637              :         {
     638            6 :           if (tree->get_kind () == AST::UseTree::Kind::Rebind)
     639              :             {
     640            6 :               auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
     641            6 :               auto path_size = rebind.get_path ().get_segments ().size ();
     642            6 :               if (path_size == 1
     643            6 :                   && rebind.get_path ()
     644            6 :                        .get_final_segment ()
     645            6 :                        .is_lower_self_seg ())
     646              :                 {
     647            4 :                   collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
     648              :                                         "%<self%> import can only appear in an "
     649            4 :                                         "import list with a non-empty prefix"));
     650              :                 }
     651              :             }
     652              :         }
     653              :     }
     654         8215 :   DefaultResolver::visit (use_list);
     655         8215 : }
     656              : 
     657              : void
     658       753272 : Early::visit (AST::IdentifierPattern &identifier)
     659              : {
     660              :   // check if this is *really* a path pattern
     661       753272 :   if (!identifier.get_is_ref () && !identifier.get_is_mut ()
     662      1472262 :       && !identifier.has_subpattern ())
     663              :     {
     664       718409 :       auto res = ctx.values.get (identifier.get_ident ());
     665       718409 :       if (res)
     666              :         {
     667         1021 :           if (res->is_ambiguous ())
     668            0 :             rust_error_at (identifier.get_locus (), ErrorCode::E0659,
     669              :                            "%qs is ambiguous",
     670            0 :                            identifier.get_ident ().as_string ().c_str ());
     671              :           else
     672              :             {
     673              :               // HACK: bail out if the definition is a function
     674         1021 :               if (!ctx.mappings.is_function_node (res->get_node_id ()))
     675          578 :                 ident_path_to_convert.insert (identifier.get_node_id ());
     676              :             }
     677              :         }
     678       718409 :     }
     679       753272 : }
     680              : 
     681              : } // namespace Resolver2_0
     682              : } // 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.