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.3 % 317 280
Test Date: 2026-09-12 16:25:28 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        11342 : Early::Early (NameResolutionContext &ctx)
      39        11342 :   : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
      40        11342 : {}
      41              : 
      42              : void
      43        61411 : Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
      44              : {
      45        61411 :   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        61411 :   if (!leaf_macro)
      49        61411 :     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        28915 : Early::insert_once (AST::MacroRulesDefinition &def)
      61              : {
      62        28915 :   if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
      63            1 :     ctx.mappings.insert_macro_def (&def);
      64        28915 : }
      65              : 
      66              : void
      67        11342 : Early::go (AST::Crate &crate)
      68              : {
      69              :   // First we go through TopLevel resolution to get all our declared items
      70        11342 :   toplevel.go (crate);
      71              : 
      72              :   // We start with resolving the list of imports that `TopLevel` has built for
      73              :   // us
      74              : 
      75        11342 :   dirty = toplevel.is_dirty ();
      76              : 
      77              :   // We now proceed with resolving macros, which can be nested in almost any
      78              :   // items
      79        11342 :   textual_scope.push ();
      80              : 
      81        11342 :   visit (crate);
      82              : 
      83        11342 :   textual_scope.pop ();
      84              : 
      85              :   // handle IdentifierPattern vs PathInExpression disambiguation
      86        11342 :   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
      87        11342 : }
      88              : 
      89              : bool
      90         3826 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
      91              : {
      92         3826 :   auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
      93         3826 :   if (!resolved.has_value ())
      94              :     return false;
      95              : 
      96         7648 :   auto result = Analysis::Mappings::get ().lookup_glob_container (
      97         3824 :     resolved->definition.get_node_id ());
      98              : 
      99         3824 :   if (!result)
     100              :     return false;
     101              : 
     102         3824 :   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         7648 :   imports.emplace_back (
     110        11472 :     ImportPair (std::move (glob), ImportData::Glob (resolved->definition)));
     111              : 
     112         3824 :   return true;
     113         3826 : }
     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        39823 : Early::resolve_rebind_import (NodeId use_dec_id,
     135              :                               TopLevel::ImportKind &&rebind_import)
     136              : {
     137        39823 :   NodeId import_id = UNKNOWN_NODEID;
     138        39823 :   auto &path = rebind_import.to_resolve;
     139        39823 :   auto &rebind = rebind_import.rebind.value ();
     140              : 
     141        39823 :   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        39251 :     case AST::UseTreeRebind::NewBindType::NONE:
     147        39251 :       import_id = path.get_final_segment ().get_node_id ();
     148        39251 :       break;
     149              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     150              :       // nothing
     151              :       break;
     152              :     }
     153              : 
     154        39823 :   if (ctx.lookup (import_id, Namespace::Types))
     155              :     return true;
     156              : 
     157         7812 :   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         7812 :   if (definitions.empty ())
     161              :     return false;
     162        15311 :   for (const auto &def : definitions)
     163              :     {
     164         7796 :       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         7515 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     175              : 
     176         7515 :   imports.emplace_back (
     177         7515 :     ImportPair (std::move (rebind_import),
     178        15030 :                 ImportData::Rebind (std::move (definitions))));
     179              : 
     180         7515 :   return true;
     181         7812 : }
     182              : 
     183              : void
     184        25564 : Early::build_import_mapping (
     185              :   std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
     186              : {
     187        25564 :   auto found = false;
     188        25564 :   auto use_dec_id = use_import.first;
     189              : 
     190        69213 :   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        43649 :       auto path = import.to_resolve;
     195              : 
     196              :       // used to skip the "unresolved import" error
     197              :       // if we output other errors during resolution
     198        43649 :       size_t old_error_count = macro_resolve_errors.size ();
     199              : 
     200        43649 :       switch (import.kind)
     201              :         {
     202         3826 :         case TopLevel::ImportKind::Kind::Glob:
     203         3826 :           found = resolve_glob_import (use_dec_id, std::move (import));
     204         3826 :           break;
     205            0 :         case TopLevel::ImportKind::Kind::Simple:
     206            0 :           found = resolve_simple_import (use_dec_id, std::move (import));
     207            0 :           break;
     208        39823 :         case TopLevel::ImportKind::Kind::Rebind:
     209        39823 :           found = resolve_rebind_import (use_dec_id, std::move (import));
     210        39823 :           break;
     211              :         }
     212              : 
     213        43649 :       if (!found && old_error_count == macro_resolve_errors.size ())
     214          592 :         collect_error (Error (path.get_final_segment ().get_locus (),
     215              :                               ErrorCode::E0433, "unresolved import %qs",
     216          592 :                               path.as_string ().c_str ()));
     217        43649 :     }
     218        25564 : }
     219              : 
     220              : void
     221       634590 : Early::TextualScope::push ()
     222              : {
     223              :   // push a new empty scope
     224       634590 :   scopes.emplace_back ();
     225       634590 : }
     226              : 
     227              : void
     228       634590 : Early::TextualScope::pop ()
     229              : {
     230       634590 :   rust_assert (!scopes.empty ());
     231              : 
     232       634590 :   scopes.pop_back ();
     233       634590 : }
     234              : 
     235              : void
     236        28915 : Early::TextualScope::insert (std::string name, NodeId id)
     237              : {
     238        28915 :   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        57830 :   scopes.back ().insert ({name, id});
     244        28915 : }
     245              : 
     246              : tl::optional<NodeId>
     247        61296 : Early::TextualScope::get (const std::string &name)
     248              : {
     249        82785 :   for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
     250              :     {
     251        77061 :       auto scope = *iterator;
     252        77061 :       auto found = scope.find (name);
     253        77061 :       if (found != scope.end ())
     254        55572 :         return found->second;
     255        77061 :     }
     256              : 
     257         5724 :   return tl::nullopt;
     258              : }
     259              : 
     260              : void
     261        28915 : Early::visit (AST::MacroRulesDefinition &def)
     262              : {
     263        28915 :   DefaultResolver::visit (def);
     264              : 
     265        57830 :   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
     266        28915 :   insert_once (def);
     267        28915 : }
     268              : 
     269              : void
     270       612089 : Early::visit (AST::BlockExpr &block)
     271              : {
     272       612089 :   textual_scope.push ();
     273              : 
     274       612089 :   DefaultResolver::visit (block);
     275              : 
     276       612089 :   textual_scope.pop ();
     277       612089 : }
     278              : 
     279              : void
     280        11506 : Early::visit (AST::Module &module)
     281              : {
     282        11506 :   bool is_macro_use = false;
     283              : 
     284        14514 :   for (const auto &attr : module.get_outer_attrs ())
     285              :     {
     286         3355 :       if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
     287              :         {
     288              :           is_macro_use = true;
     289              :           break;
     290              :         }
     291              :     }
     292              : 
     293        11506 :   if (!is_macro_use)
     294        11159 :     textual_scope.push ();
     295              : 
     296        11506 :   DefaultResolver::visit (module);
     297              : 
     298        11506 :   if (!is_macro_use)
     299        11159 :     textual_scope.pop ();
     300        11506 : }
     301              : 
     302              : void
     303        22848 : Early::maybe_prelude_import ()
     304              : {
     305              :   // handle prelude import
     306        22848 :   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        22848 : }
     317              : 
     318              : void
     319        61534 : Early::visit (AST::MacroInvocation &invoc)
     320              : {
     321        61534 :   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        61534 :   auto resolve_offset_of = Session::get_instance ().should_support_offset_of ()
     326        61534 :                            && (path.as_string () == "offset_of");
     327              : 
     328              :   // Ditto, but for `cfg_select!()`.
     329        61534 :   auto resolve_cfg_select
     330        61534 :     = Session::get_instance ().should_support_cfg_select ()
     331        61534 :       && (path.as_string () == "cfg_select");
     332              : 
     333        61534 :   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        61534 :   tl::optional<NameResolutionContext::NamespacedDefinition> ns_def
     346              :     = tl::nullopt;
     347        61534 :   if (path.get_segments ().size () == 1)
     348        61296 :     ns_def = textual_scope.get (path.get_final_segment ().as_string ())
     349       122592 :                .map ([] (NodeId id) {
     350        55572 :                  return NameResolutionContext::NamespacedDefinition (
     351        55572 :                    Rib::Definition::NonShadowable (id), Namespace::Macros);
     352        61296 :                });
     353              : 
     354              :   // we won't have changed `definition` from `nullopt` if there are more
     355              :   // than one segments in our path
     356        61534 :   if (!ns_def.has_value ())
     357        11801 :     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        61534 :   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        61411 :   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        61411 :   auto &mappings = Analysis::Mappings::get ();
     375        61411 :   auto rules_def
     376        61411 :     = mappings.lookup_macro_def (ns_def->definition.get_node_id ());
     377              : 
     378              :   // Macro definition not found, maybe it is not expanded yet.
     379        61411 :   if (!rules_def)
     380              :     return;
     381              : 
     382        61411 :   if (mappings.lookup_macro_invocation (invoc))
     383              :     return;
     384              : 
     385        61411 :   mappings.insert_macro_invocation (invoc, rules_def.value ());
     386        61534 : }
     387              : 
     388              : void
     389          405 : Early::visit_derive_attribute (AST::Attribute &attr,
     390              :                                Analysis::Mappings &mappings)
     391              : {
     392          405 :   auto traits = attr.get_traits_to_derive ();
     393         1470 :   for (auto &trait : traits)
     394              :     {
     395         1065 :       auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
     396         1065 :       if (!ns_def.has_value ())
     397              :         {
     398              :           // FIXME: Change to proper error message
     399          754 :           collect_error (Error (trait.get ().get_locus (),
     400              :                                 "could not resolve trait %qs",
     401          377 :                                 trait.get ().as_string ().c_str ()));
     402          377 :           continue;
     403              :         }
     404              : 
     405          688 :       auto pm_def = mappings.lookup_derive_proc_macro_def (
     406          688 :         ns_def->definition.get_node_id ());
     407              : 
     408          688 :       if (pm_def.has_value ())
     409            0 :         mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
     410         1065 :     }
     411          405 : }
     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      2542703 : Early::visit (AST::Attribute &attr)
     439              : {
     440      2542703 :   auto &mappings = Analysis::Mappings::get ();
     441              : 
     442      2542703 :   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
     443      2542703 :   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      2542703 :   if (known_check == Analysis::Attributes::AttributeKnowledge::Tool)
     448            0 :     return;
     449              : 
     450      2542703 :   auto is_builtin
     451              :     = known_check == Analysis::Attributes::AttributeKnowledge::Known;
     452              : 
     453      2542703 :   if (attr.is_derive ())
     454              :     {
     455          405 :       visit_derive_attribute (attr, mappings);
     456              :     }
     457      2542298 :   else if (!is_builtin) // Do not resolve builtins
     458              :     {
     459            2 :       visit_non_builtin_attribute (attr, mappings, name);
     460              :     }
     461              : 
     462      2542703 :   DefaultResolver::visit (attr);
     463      2542703 : }
     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         3824 : Early::finalize_glob_import (NameResolutionContext &ctx,
     491              :                              const Early::ImportPair &mapping)
     492              : {
     493         7648 :   auto container = Analysis::Mappings::get ().lookup_glob_container (
     494         7648 :     mapping.data.container ().get_node_id ());
     495              : 
     496         3824 :   rust_assert (container);
     497              : 
     498         3824 :   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         3824 :   GlobbingVisitor glob_visit (ctx);
     511         3824 :   glob_visit.go (container.value ());
     512         3824 :   dirty |= glob_visit.is_dirty ();
     513         3824 : }
     514              : 
     515              : void
     516         7515 : 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         7515 :   auto &path = mapping.import_kind.to_resolve;
     521         7515 :   auto &rebind = mapping.import_kind.rebind.value ();
     522         7515 :   auto data = mapping.data;
     523              : 
     524         7515 :   NodeId import_id = UNKNOWN_NODEID;
     525         7515 :   std::string declared_name;
     526              : 
     527              :   // FIXME: This needs to be done in `FinalizeImports`
     528         7515 :   switch (rebind.get_new_bind_type ())
     529              :     {
     530          393 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     531          393 :       declared_name = rebind.get_identifier ().as_string ();
     532          393 :       import_id = rebind.get_node_id ();
     533          393 :       break;
     534         7118 :     case AST::UseTreeRebind::NewBindType::NONE:
     535         7118 :       {
     536         7118 :         const auto &segments = path.get_segments ();
     537              :         // We don't want to insert `self` with `use module::self`
     538         7118 :         if (path.get_final_segment ().is_lower_self_seg ())
     539              :           {
     540              :             // Erroneous `self` or `{self}` use declaration
     541          102 :             if (segments.size () == 1)
     542              :               return;
     543           99 :             declared_name = segments[segments.size () - 2].as_string ();
     544           99 :             import_id = segments[segments.size () - 2].get_node_id ();
     545              :           }
     546              :         else
     547              :           {
     548         7016 :             declared_name = path.get_final_segment ().as_string ();
     549         7016 :             import_id = path.get_final_segment ().get_node_id ();
     550              :           }
     551              :         break;
     552              :       }
     553              :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     554              :       // We don't want to insert it into the trie
     555              :       return;
     556              :     }
     557              : 
     558        15296 :   for (auto &&definition : data.definitions ())
     559              :     {
     560         7788 :       ctx.map_usage (Usage (import_id),
     561         7788 :                      Definition (definition.definition.get_node_id ()),
     562              :                      definition.ns);
     563              : 
     564        23364 :       toplevel.insert_or_error_out (declared_name, path.get_locus (),
     565         7788 :                                     definition.definition.get_node_id (),
     566              :                                     definition.ns);
     567              : 
     568         7788 :       dirty = dirty || toplevel.is_dirty ();
     569              : 
     570              :       // Map the import to the glob container if it exists - this is important
     571              :       // for 2-stepped glob imports which refer to glob containers, e.g.
     572              :       //
     573              :       // enum Foo { ... }
     574              :       // pub use Foo;
     575              :       // use self::Foo::*;
     576         7788 :       auto &mappings = Analysis::Mappings::get ();
     577         7788 :       if (auto container = mappings.lookup_glob_container (
     578         7788 :             definition.definition.get_node_id ()))
     579          549 :         mappings.insert_glob_container (import_id, container.value ());
     580         7508 :     }
     581        15030 : }
     582              : 
     583              : void
     584        25564 : Early::visit (AST::UseDeclaration &decl)
     585              : {
     586              :   // We do not want to visit the use trees, we're only looking for top level
     587              :   // rebind. eg. `use something;` or `use something::other;`
     588        25564 :   if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
     589              :     {
     590        15743 :       auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
     591        15743 :       if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
     592              :         {
     593            2 :           collect_error (
     594            1 :             Error (decl.get_locus (), ErrorCode::E0429,
     595            1 :                    "%<self%> imports are only allowed within a { } list"));
     596              :         }
     597              :     }
     598              : 
     599        25564 :   auto &imports = toplevel.get_imports_to_resolve ();
     600        25564 :   auto current_import = imports.find (decl.get_node_id ());
     601        25564 :   if (current_import != imports.end ())
     602              :     {
     603        25564 :       build_import_mapping (*current_import);
     604              :     }
     605              : 
     606              :   // Once this is done, we finalize their resolution
     607        36903 :   for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
     608        11339 :     switch (mapping.import_kind.kind)
     609              :       {
     610         3824 :       case TopLevel::ImportKind::Kind::Glob:
     611         3824 :         finalize_glob_import (ctx, mapping);
     612         3824 :         break;
     613            0 :       case TopLevel::ImportKind::Kind::Simple:
     614            0 :         finalize_simple_import (mapping);
     615            0 :         break;
     616         7515 :       case TopLevel::ImportKind::Kind::Rebind:
     617         7515 :         finalize_rebind_import (mapping);
     618         7515 :         break;
     619              :       }
     620              : 
     621        25564 :   DefaultResolver::visit (decl);
     622        25564 : }
     623              : 
     624              : void
     625         7508 : Early::visit (AST::UseTreeList &use_list)
     626              : {
     627         7508 :   if (!use_list.has_path ())
     628              :     {
     629           10 :       for (auto &&tree : use_list.get_trees ())
     630              :         {
     631            6 :           if (tree->get_kind () == AST::UseTree::Kind::Rebind)
     632              :             {
     633            6 :               auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
     634            6 :               auto path_size = rebind.get_path ().get_segments ().size ();
     635            6 :               if (path_size == 1
     636            6 :                   && rebind.get_path ()
     637            6 :                        .get_final_segment ()
     638            6 :                        .is_lower_self_seg ())
     639              :                 {
     640            4 :                   collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
     641              :                                         "%<self%> import can only appear in an "
     642            4 :                                         "import list with a non-empty prefix"));
     643              :                 }
     644              :             }
     645              :         }
     646              :     }
     647         7508 :   DefaultResolver::visit (use_list);
     648         7508 : }
     649              : 
     650              : void
     651       736801 : Early::visit (AST::IdentifierPattern &identifier)
     652              : {
     653              :   // check if this is *really* a path pattern
     654       736801 :   if (!identifier.get_is_ref () && !identifier.get_is_mut ()
     655      1440689 :       && !identifier.has_subpattern ())
     656              :     {
     657       703321 :       auto res = ctx.values.get (identifier.get_ident ());
     658       703321 :       if (res)
     659              :         {
     660          945 :           if (res->is_ambiguous ())
     661            0 :             rust_error_at (identifier.get_locus (), ErrorCode::E0659,
     662              :                            "%qs is ambiguous",
     663            0 :                            identifier.get_ident ().as_string ().c_str ());
     664              :           else
     665              :             {
     666              :               // HACK: bail out if the definition is a function
     667          945 :               if (!ctx.mappings.is_function_node (res->get_node_id ()))
     668          514 :                 ident_path_to_convert.insert (identifier.get_node_id ());
     669              :             }
     670              :         }
     671       703321 :     }
     672       736801 : }
     673              : 
     674              : } // namespace Resolver2_0
     675              : } // 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.