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