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: 2025-08-30 13:27:53 Functions: 90.9 % 22 20
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (C) 2020-2025 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                 :       32717 : BindingLayer::BindingLayer (BindingSource source) : source (source)
      27                 :             : {
      28                 :       32717 :   push (Binding::Kind::Product);
      29                 :       32717 : }
      30                 :             : 
      31                 :             : bool
      32                 :       47696 : BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
      33                 :             : {
      34                 :       95732 :   for (auto &bind : bindings)
      35                 :             :     {
      36                 :       48102 :       if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
      37                 :       48102 :           && bind.kind == kind)
      38                 :             :         {
      39                 :       47696 :           return true;
      40                 :             :         }
      41                 :             :     }
      42                 :             :   return false;
      43                 :             : }
      44                 :             : 
      45                 :             : void
      46                 :       33299 : BindingLayer::push (Binding::Kind kind)
      47                 :             : {
      48                 :       33299 :   bindings.push_back (Binding (kind));
      49                 :       33299 : }
      50                 :             : 
      51                 :             : bool
      52                 :       23852 : BindingLayer::is_and_bound (Identifier ident)
      53                 :             : {
      54                 :       23852 :   return bind_test (ident, Binding::Kind::Product);
      55                 :             : }
      56                 :             : 
      57                 :             : bool
      58                 :       23844 : BindingLayer::is_or_bound (Identifier ident)
      59                 :             : {
      60                 :       23844 :   return bind_test (ident, Binding::Kind::Or);
      61                 :             : }
      62                 :             : 
      63                 :             : void
      64                 :       23844 : BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
      65                 :             :                             bool is_mut)
      66                 :             : {
      67                 :       23844 :   bindings.back ().idents.emplace (
      68                 :       23844 :     std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
      69                 :       23844 : }
      70                 :             : 
      71                 :             : void
      72                 :         582 : BindingLayer::merge ()
      73                 :             : {
      74                 :         582 :   auto last_binding = std::move (bindings.back ());
      75                 :         582 :   bindings.pop_back ();
      76                 :             : 
      77                 :         582 :   if (bindings.back ().has_expected_bindings)
      78                 :             :     {
      79                 :         262 :       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                 :         756 :   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                 :         582 :   if (bindings.back ().kind == Binding::Kind::Or)
     123                 :         393 :     bindings.back ().has_expected_bindings = true;
     124                 :         582 : }
     125                 :             : 
     126                 :             : BindingSource
     127                 :           8 : BindingLayer::get_source () const
     128                 :             : {
     129                 :           8 :   return source;
     130                 :             : }
     131                 :             : 
     132                 :             : Resolver::CanonicalPath
     133                 :       73606 : CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
     134                 :             : {
     135                 :      147212 :   auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
     136                 :       73606 :   ret.set_crate_num (crate_num);
     137                 :       73606 :   return ret;
     138                 :             : }
     139                 :             : 
     140                 :             : Resolver::CanonicalPath
     141                 :      145997 : CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
     142                 :             : {
     143                 :      145997 :   auto parent_path = get_parent ().as_path (ctx);
     144                 :      291994 :   return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
     145                 :      145997 : }
     146                 :             : 
     147                 :             : Resolver::CanonicalPath
     148                 :       27217 : CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
     149                 :             : {
     150                 :       27217 :   if (!cache)
     151                 :             :     {
     152                 :       17100 :       auto res = ctx.lookup (lookup_id).and_then (
     153                 :       33104 :         [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
     154                 :             : 
     155                 :       17100 :       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                 :       12178 :           return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
     162                 :             :         }
     163                 :             : 
     164                 :        4922 :       cache = res.value ();
     165                 :             :     }
     166                 :       15039 :   return cache->as_path (ctx);
     167                 :             : }
     168                 :             : 
     169                 :             : Resolver::CanonicalPath
     170                 :        6767 : CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
     171                 :             : {
     172                 :        6767 :   auto parent_path = get_parent ().as_path (ctx);
     173                 :        6767 :   return parent_path.append (
     174                 :       13534 :     Resolver::CanonicalPath::inherent_impl_seg (impl_id,
     175                 :       20301 :                                                 type_record.as_path (ctx)));
     176                 :        6767 : }
     177                 :             : 
     178                 :             : Resolver::CanonicalPath
     179                 :       10225 : CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
     180                 :             : {
     181                 :       10225 :   auto parent_path = get_parent ().as_path (ctx);
     182                 :       10225 :   return parent_path.append (
     183                 :       20450 :     Resolver::CanonicalPath::trait_impl_projection_seg (
     184                 :       30675 :       impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
     185                 :       10225 : }
     186                 :             : 
     187                 :        4290 : NameResolutionContext::NameResolutionContext ()
     188                 :        4290 :   : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
     189                 :        4290 : {}
     190                 :             : 
     191                 :             : tl::expected<NodeId, DuplicateNameError>
     192                 :      146810 : NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
     193                 :             : {
     194                 :      146810 :   switch (ns)
     195                 :             :     {
     196                 :       67638 :     case Namespace::Values:
     197                 :       67638 :       return values.insert (name, id);
     198                 :       79005 :     case Namespace::Types:
     199                 :       79005 :       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                 :        3280 : NameResolutionContext::insert_variant (Identifier name, NodeId id)
     211                 :             : {
     212                 :        3280 :   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                 :          28 : NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
     236                 :             : {
     237                 :          28 :   switch (ns)
     238                 :             :     {
     239                 :          10 :     case Namespace::Values:
     240                 :          10 :       return values.insert_globbed (name, id);
     241                 :          18 :     case Namespace::Types:
     242                 :          18 :       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                 :      194128 : NameResolutionContext::map_usage (Usage usage, Definition definition)
     254                 :             : {
     255                 :      194128 :   auto inserted = resolved_nodes.emplace (usage, definition).second;
     256                 :             : 
     257                 :             :   // is that valid?
     258                 :      194128 :   rust_assert (inserted);
     259                 :      194128 : }
     260                 :             : 
     261                 :             : tl::optional<NodeId>
     262                 :     1265849 : NameResolutionContext::lookup (NodeId usage) const
     263                 :             : {
     264                 :     1265849 :   auto it = resolved_nodes.find (Usage (usage));
     265                 :             : 
     266                 :     1265849 :   if (it == resolved_nodes.end ())
     267                 :        8472 :     return tl::nullopt;
     268                 :             : 
     269                 :     1257377 :   return it->second.id;
     270                 :             : }
     271                 :             : 
     272                 :             : void
     273                 :      492586 : 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                 :      492586 :   values.push (rib_kind, id, path);
     279                 :      492586 :   types.push (rib_kind, id, path);
     280                 :      492586 :   macros.push (rib_kind, id, path);
     281                 :             :   // labels.push (rib, id);
     282                 :             : 
     283                 :      492586 :   lambda ();
     284                 :             : 
     285                 :      492584 :   values.pop ();
     286                 :      492584 :   types.pop ();
     287                 :      492584 :   macros.pop ();
     288                 :             :   // labels.pop (rib);
     289                 :      492584 : }
     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.1-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.