LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-name-resolution-context.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 72.4 % 152 110
Test Date: 2026-02-28 14:20:25 Functions: 90.9 % 22 20
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-name-resolution-context.h"
      20              : #include "optional.h"
      21              : #include "rust-mapping-common.h"
      22              : 
      23              : namespace Rust {
      24              : namespace Resolver2_0 {
      25              : 
      26        33542 : BindingLayer::BindingLayer (BindingSource source) : source (source)
      27              : {
      28        33542 :   push (Binding::Kind::Product);
      29        33542 : }
      30              : 
      31              : bool
      32        48584 : BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
      33              : {
      34        97508 :   for (auto &bind : bindings)
      35              :     {
      36        48990 :       if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
      37        48990 :           && bind.kind == kind)
      38              :         {
      39        48584 :           return true;
      40              :         }
      41              :     }
      42              :   return false;
      43              : }
      44              : 
      45              : void
      46        34133 : BindingLayer::push (Binding::Kind kind)
      47              : {
      48        34133 :   bindings.push_back (Binding (kind));
      49        34133 : }
      50              : 
      51              : bool
      52        24296 : BindingLayer::is_and_bound (Identifier ident)
      53              : {
      54        24296 :   return bind_test (ident, Binding::Kind::Product);
      55              : }
      56              : 
      57              : bool
      58        24288 : BindingLayer::is_or_bound (Identifier ident)
      59              : {
      60        24288 :   return bind_test (ident, Binding::Kind::Or);
      61              : }
      62              : 
      63              : void
      64        24288 : BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
      65              :                             bool is_mut)
      66              : {
      67        24288 :   bindings.back ().idents.emplace (
      68        24288 :     std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
      69        24288 : }
      70              : 
      71              : void
      72          591 : BindingLayer::merge ()
      73              : {
      74          591 :   auto last_binding = std::move (bindings.back ());
      75          591 :   bindings.pop_back ();
      76              : 
      77          591 :   if (bindings.back ().has_expected_bindings)
      78              :     {
      79          267 :       for (auto &value : bindings.back ().idents)
      80              :         {
      81           58 :           auto ident = value.first;
      82           58 :           if (last_binding.idents.find (ident) == last_binding.idents.end ())
      83              :             {
      84            0 :               location_t locus = value.second.first;
      85            0 :               rust_error_at (locus, ErrorCode::E0408,
      86              :                              "variable %qs is not bound in all patterns",
      87              :                              ident.c_str ());
      88              :             }
      89           58 :         }
      90              :     }
      91              : 
      92          765 :   for (auto &value : last_binding.idents)
      93              :     {
      94          174 :       auto res = bindings.back ().idents.emplace (value);
      95          174 :       if (res.second)
      96              :         {
      97          116 :           if (bindings.back ().has_expected_bindings)
      98              :             {
      99           14 :               auto &ident = value.first;
     100           14 :               location_t locus = value.second.first;
     101           14 :               rust_error_at (locus, ErrorCode::E0408,
     102              :                              "variable %qs is not bound in all patterns",
     103              :                              ident.c_str ());
     104              :             }
     105              :         }
     106              :       else
     107              :         {
     108           58 :           auto this_mode = value.second.second;
     109           58 :           auto other_mode = res.first->second.second;
     110          232 :           if (this_mode != other_mode)
     111              :             {
     112            7 :               auto &ident = value.first;
     113            7 :               location_t locus = value.second.first;
     114            7 :               rust_error_at (locus, ErrorCode::E0409,
     115              :                              "variable %qs is bound inconsistently across "
     116              :                              "pattern alternatives",
     117              :                              ident.c_str ());
     118              :             }
     119              :         }
     120              :     }
     121              : 
     122          591 :   if (bindings.back ().kind == Binding::Kind::Or)
     123          400 :     bindings.back ().has_expected_bindings = true;
     124          591 : }
     125              : 
     126              : BindingSource
     127            8 : BindingLayer::get_source () const
     128              : {
     129            8 :   return source;
     130              : }
     131              : 
     132              : Resolver::CanonicalPath
     133        74527 : CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
     134              : {
     135       149054 :   auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
     136        74527 :   ret.set_crate_num (crate_num);
     137        74527 :   return ret;
     138              : }
     139              : 
     140              : Resolver::CanonicalPath
     141       147394 : CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
     142              : {
     143       147394 :   auto parent_path = get_parent ().as_path (ctx);
     144       294788 :   return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
     145       147394 : }
     146              : 
     147              : Resolver::CanonicalPath
     148        27377 : CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
     149              : {
     150        27377 :   if (!cache)
     151              :     {
     152        17165 :       auto res = ctx.lookup (lookup_id).and_then (
     153        33226 :         [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
     154              : 
     155        17165 :       if (!res)
     156              :         {
     157              :           // HACK: use a dummy value
     158              :           // this should bring us roughly to parity with nr1.0
     159              :           // since nr1.0 doesn't seem to handle canonical paths for generics
     160              :           //   quite right anyways
     161        12189 :           return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
     162              :         }
     163              : 
     164         4976 :       cache = res.value ();
     165              :     }
     166        15188 :   return cache->as_path (ctx);
     167              : }
     168              : 
     169              : Resolver::CanonicalPath
     170         6855 : CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
     171              : {
     172         6855 :   auto parent_path = get_parent ().as_path (ctx);
     173         6855 :   return parent_path.append (
     174        13710 :     Resolver::CanonicalPath::inherent_impl_seg (impl_id,
     175        20565 :                                                 type_record.as_path (ctx)));
     176         6855 : }
     177              : 
     178              : Resolver::CanonicalPath
     179        10261 : CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
     180              : {
     181        10261 :   auto parent_path = get_parent ().as_path (ctx);
     182        10261 :   return parent_path.append (
     183        20522 :     Resolver::CanonicalPath::trait_impl_projection_seg (
     184        30783 :       impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
     185        10261 : }
     186              : 
     187         4510 : NameResolutionContext::NameResolutionContext ()
     188         4510 :   : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
     189         4510 : {}
     190              : 
     191              : tl::expected<NodeId, DuplicateNameError>
     192       149873 : NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
     193              : {
     194       149873 :   switch (ns)
     195              :     {
     196        69245 :     case Namespace::Values:
     197        69245 :       return values.insert (name, id);
     198        80461 :     case Namespace::Types:
     199        80461 :       return types.insert (name, id);
     200          167 :     case Namespace::Macros:
     201          167 :       return macros.insert (name, id);
     202            0 :     case Namespace::Labels:
     203            0 :     default:
     204              :       // return labels.insert (name, id);
     205            0 :       rust_unreachable ();
     206              :     }
     207              : }
     208              : 
     209              : tl::expected<NodeId, DuplicateNameError>
     210         3332 : NameResolutionContext::insert_variant (Identifier name, NodeId id)
     211              : {
     212         3332 :   return types.insert_variant (name, id);
     213              : }
     214              : 
     215              : tl::expected<NodeId, DuplicateNameError>
     216            0 : NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
     217              :                                           Namespace ns)
     218              : {
     219            0 :   switch (ns)
     220              :     {
     221            0 :     case Namespace::Values:
     222            0 :       return values.insert_shadowable (name, id);
     223            0 :     case Namespace::Types:
     224            0 :       return types.insert_shadowable (name, id);
     225            0 :     case Namespace::Macros:
     226            0 :       return macros.insert_shadowable (name, id);
     227            0 :     case Namespace::Labels:
     228            0 :     default:
     229              :       // return labels.insert (name, id);
     230            0 :       rust_unreachable ();
     231              :     }
     232              : }
     233              : 
     234              : tl::expected<NodeId, DuplicateNameError>
     235           30 : NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
     236              : {
     237           30 :   switch (ns)
     238              :     {
     239           10 :     case Namespace::Values:
     240           10 :       return values.insert_globbed (name, id);
     241           20 :     case Namespace::Types:
     242           20 :       return types.insert_globbed (name, id);
     243            0 :     case Namespace::Macros:
     244            0 :       return macros.insert_globbed (name, id);
     245            0 :     case Namespace::Labels:
     246            0 :     default:
     247              :       // return labels.insert (name, id);
     248            0 :       rust_unreachable ();
     249              :     }
     250              : }
     251              : 
     252              : void
     253       199723 : NameResolutionContext::map_usage (Usage usage, Definition definition)
     254              : {
     255       199723 :   auto inserted = resolved_nodes.emplace (usage, definition).second;
     256              : 
     257              :   // is that valid?
     258       199723 :   rust_assert (inserted);
     259       199723 : }
     260              : 
     261              : tl::optional<NodeId>
     262      2603282 : NameResolutionContext::lookup (NodeId usage) const
     263              : {
     264      2603282 :   auto it = resolved_nodes.find (Usage (usage));
     265              : 
     266      2603282 :   if (it == resolved_nodes.end ())
     267         6099 :     return tl::nullopt;
     268              : 
     269      2597183 :   return it->second.id;
     270              : }
     271              : 
     272              : void
     273       502811 : NameResolutionContext::scoped (Rib::Kind rib_kind, NodeId id,
     274              :                                std::function<void (void)> lambda,
     275              :                                tl::optional<Identifier> path)
     276              : {
     277              :   // NOTE: You must be at the root node when pushing the prelude rib.
     278       502811 :   values.push (rib_kind, id, path);
     279       502811 :   types.push (rib_kind, id, path);
     280       502811 :   macros.push (rib_kind, id, path);
     281              :   // labels.push (rib, id);
     282              : 
     283       502811 :   lambda ();
     284              : 
     285       502809 :   values.pop ();
     286       502809 :   types.pop ();
     287       502809 :   macros.pop ();
     288              :   // labels.pop (rib);
     289       502809 : }
     290              : 
     291              : void
     292            0 : NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns,
     293              :                                NodeId scope_id,
     294              :                                std::function<void (void)> lambda,
     295              :                                tl::optional<Identifier> path)
     296              : {
     297              :   // This could work... I'm not sure why you would want to do this though.
     298            0 :   rust_assert (rib_kind != Rib::Kind::Prelude);
     299              : 
     300            0 :   switch (ns)
     301              :     {
     302            0 :     case Namespace::Values:
     303            0 :       values.push (rib_kind, scope_id, path);
     304            0 :       break;
     305            0 :     case Namespace::Types:
     306            0 :       types.push (rib_kind, scope_id, path);
     307            0 :       break;
     308            0 :     case Namespace::Labels:
     309            0 :     case Namespace::Macros:
     310            0 :       gcc_unreachable ();
     311              :     }
     312              : 
     313            0 :   lambda ();
     314              : 
     315            0 :   switch (ns)
     316              :     {
     317            0 :     case Namespace::Values:
     318            0 :       values.pop ();
     319            0 :       break;
     320            0 :     case Namespace::Types:
     321            0 :       types.pop ();
     322            0 :       break;
     323              :     case Namespace::Labels:
     324              :     case Namespace::Macros:
     325              :       gcc_unreachable ();
     326              :     }
     327            0 : }
     328              : 
     329              : } // namespace Resolver2_0
     330              : } // 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.