LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-late-name-resolver-2.0.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.4 % 313 261
Test Date: 2025-11-22 14:42:49 Functions: 88.2 % 34 30
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 "optional.h"
      20                 :             : #include "rust-ast-full.h"
      21                 :             : #include "rust-diagnostics.h"
      22                 :             : #include "rust-expr.h"
      23                 :             : #include "rust-hir-map.h"
      24                 :             : #include "rust-late-name-resolver-2.0.h"
      25                 :             : #include "rust-default-resolver.h"
      26                 :             : #include "rust-name-resolution-context.h"
      27                 :             : #include "rust-resolve-builtins.h"
      28                 :             : #include "rust-path.h"
      29                 :             : #include "rust-system.h"
      30                 :             : #include "rust-tyty.h"
      31                 :             : #include "rust-hir-type-check.h"
      32                 :             : #include "rust-ice-finalizer.h"
      33                 :             : #include "rust-ast.h"
      34                 :             : 
      35                 :             : namespace Rust {
      36                 :             : namespace Resolver2_0 {
      37                 :             : 
      38                 :        4444 : Late::Late (NameResolutionContext &ctx)
      39                 :        4444 :   : DefaultResolver (ctx), funny_error (false), block_big_self (false)
      40                 :        4444 : {}
      41                 :             : 
      42                 :             : void
      43                 :        4444 : Late::go (AST::Crate &crate)
      44                 :             : {
      45                 :        4444 :   Builtins::setup_type_ctx ();
      46                 :             : 
      47                 :        4444 :   visit (crate);
      48                 :        4443 : }
      49                 :             : 
      50                 :             : void
      51                 :           0 : Late::new_label (Identifier name, NodeId id)
      52                 :             : {
      53                 :             :   // labels can always shadow, so `insert` should never fail. if it does, we're
      54                 :             :   // in big trouble!
      55                 :           0 :   auto ok = ctx.labels.insert (name, id);
      56                 :             : 
      57                 :           0 :   rust_assert (ok);
      58                 :           0 : }
      59                 :             : 
      60                 :             : void
      61                 :           0 : Late::visit (AST::ForLoopExpr &expr)
      62                 :             : {
      63                 :           0 :   visit_outer_attrs (expr);
      64                 :             : 
      65                 :           0 :   ctx.bindings.enter (BindingSource::For);
      66                 :             : 
      67                 :           0 :   visit (expr.get_pattern ());
      68                 :             : 
      69                 :           0 :   ctx.bindings.exit ();
      70                 :             : 
      71                 :           0 :   visit (expr.get_iterator_expr ());
      72                 :             : 
      73                 :           0 :   if (expr.has_loop_label ())
      74                 :           0 :     visit (expr.get_loop_label ());
      75                 :             : 
      76                 :           0 :   visit (expr.get_loop_block ());
      77                 :           0 : }
      78                 :             : 
      79                 :             : void
      80                 :          30 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
      81                 :             : {
      82                 :          30 :   ctx.bindings.enter (BindingSource::IfLet);
      83                 :             : 
      84                 :          30 :   DefaultResolver::visit_if_let_patterns (expr);
      85                 :             : 
      86                 :          30 :   ctx.bindings.exit ();
      87                 :          30 : }
      88                 :             : 
      89                 :             : void
      90                 :        2459 : Late::visit (AST::MatchArm &arm)
      91                 :             : {
      92                 :        2459 :   visit_outer_attrs (arm);
      93                 :             : 
      94                 :        2459 :   ctx.bindings.enter (BindingSource::Match);
      95                 :             : 
      96                 :        4918 :   for (auto &pattern : arm.get_patterns ())
      97                 :        2459 :     visit (pattern);
      98                 :             : 
      99                 :        2459 :   ctx.bindings.exit ();
     100                 :             : 
     101                 :        2459 :   if (arm.has_match_arm_guard ())
     102                 :           1 :     visit (arm.get_guard_expr ());
     103                 :        2459 : }
     104                 :             : 
     105                 :             : void
     106                 :       12671 : Late::visit (AST::LetStmt &let)
     107                 :             : {
     108                 :       12671 :   DefaultASTVisitor::visit_outer_attrs (let);
     109                 :       12671 :   if (let.has_type ())
     110                 :        2092 :     visit (let.get_type ());
     111                 :             :   // visit expression before pattern
     112                 :             :   // this makes variable shadowing work properly
     113                 :       12671 :   if (let.has_init_expr ())
     114                 :       11523 :     visit (let.get_init_expr ());
     115                 :             : 
     116                 :       12671 :   ctx.bindings.enter (BindingSource::Let);
     117                 :             : 
     118                 :       12671 :   visit (let.get_pattern ());
     119                 :             : 
     120                 :       12671 :   ctx.bindings.exit ();
     121                 :             : 
     122                 :       12671 :   if (let.has_else_expr ())
     123                 :           0 :     visit (let.get_init_expr ());
     124                 :             : 
     125                 :             :   // how do we deal with the fact that `let a = blipbloup` should look for a
     126                 :             :   // label and cannot go through function ribs, but `let a = blipbloup()` can?
     127                 :             : 
     128                 :             :   // how do we insert ribs here, and only pop them when we exit the current
     129                 :             :   // function?
     130                 :             :   // keep a list of ribs to pop when a scope exits? so only for blocks?
     131                 :             :   // how do we pop ribs that need to be popped not in order?
     132                 :             :   // I think it's not important if we have shadowing, correct?
     133                 :             : 
     134                 :             :   // if we have shadowing, it should work! we'll see
     135                 :             : 
     136                 :             :   // ctx.insert(Identifier name, NodeId id, Namespace ns)
     137                 :             :   // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
     138                 :             :   // Namespace::Labels,
     139                 :             :   //      let.get_node_id (), [] () {});
     140                 :       12671 : }
     141                 :             : 
     142                 :             : void
     143                 :           0 : Late::visit (AST::WhileLetLoopExpr &while_let)
     144                 :             : {
     145                 :           0 :   DefaultASTVisitor::visit_outer_attrs (while_let);
     146                 :             : 
     147                 :           0 :   if (while_let.has_loop_label ())
     148                 :           0 :     visit (while_let.get_loop_label ());
     149                 :             : 
     150                 :             :   // visit expression before pattern
     151                 :             :   // this makes variable shadowing work properly
     152                 :           0 :   visit (while_let.get_scrutinee_expr ());
     153                 :             : 
     154                 :           0 :   ctx.bindings.enter (BindingSource::WhileLet);
     155                 :             : 
     156                 :           0 :   for (auto &pattern : while_let.get_patterns ())
     157                 :           0 :     visit (pattern);
     158                 :             : 
     159                 :           0 :   ctx.bindings.exit ();
     160                 :             : 
     161                 :           0 :   visit (while_let.get_loop_block ());
     162                 :           0 : }
     163                 :             : 
     164                 :             : static void
     165                 :       24234 : visit_identifier_as_pattern (NameResolutionContext &ctx,
     166                 :             :                              const Identifier &ident, location_t locus,
     167                 :             :                              NodeId node_id, bool is_ref, bool is_mut)
     168                 :             : {
     169                 :             :   // do we insert in labels or in values
     170                 :             :   // but values does not allow shadowing... since functions cannot shadow
     171                 :             :   // do we insert functions in labels as well?
     172                 :             : 
     173                 :       24234 :   if (ctx.bindings.peek ().is_and_bound (ident))
     174                 :             :     {
     175                 :           8 :       if (ctx.bindings.peek ().get_source () == BindingSource::Param)
     176                 :           5 :         rust_error_at (
     177                 :             :           locus, ErrorCode::E0415,
     178                 :             :           "identifier %qs is bound more than once in the same parameter list",
     179                 :           5 :           ident.as_string ().c_str ());
     180                 :             :       else
     181                 :           3 :         rust_error_at (
     182                 :             :           locus, ErrorCode::E0416,
     183                 :             :           "identifier %qs is bound more than once in the same pattern",
     184                 :           3 :           ident.as_string ().c_str ());
     185                 :           8 :       return;
     186                 :             :     }
     187                 :             : 
     188                 :       48452 :   ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
     189                 :             : 
     190                 :       24226 :   if (ctx.bindings.peek ().is_or_bound (ident))
     191                 :             :     {
     192                 :          58 :       auto res = ctx.values.get (ident);
     193                 :          58 :       rust_assert (res.has_value () && !res->is_ambiguous ());
     194                 :          58 :       ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
     195                 :          58 :     }
     196                 :             :   else
     197                 :             :     {
     198                 :             :       // We do want to ignore duplicated data because some situations rely on
     199                 :             :       // it.
     200                 :       24168 :       std::ignore = ctx.values.insert_shadowable (ident, node_id);
     201                 :             :     }
     202                 :             : }
     203                 :             : 
     204                 :             : void
     205                 :       24136 : Late::visit (AST::IdentifierPattern &identifier)
     206                 :             : {
     207                 :       24136 :   DefaultResolver::visit (identifier);
     208                 :             : 
     209                 :       24136 :   visit_identifier_as_pattern (ctx, identifier.get_ident (),
     210                 :             :                                identifier.get_locus (),
     211                 :       24136 :                                identifier.get_node_id (),
     212                 :       24136 :                                identifier.get_is_ref (),
     213                 :       24136 :                                identifier.get_is_mut ());
     214                 :       24136 : }
     215                 :             : 
     216                 :             : void
     217                 :         191 : Late::visit (AST::AltPattern &pattern)
     218                 :             : {
     219                 :         191 :   ctx.bindings.peek ().push (Binding::Kind::Or);
     220                 :         591 :   for (auto &alt : pattern.get_alts ())
     221                 :             :     {
     222                 :         400 :       ctx.bindings.peek ().push (Binding::Kind::Product);
     223                 :         400 :       visit (alt);
     224                 :         400 :       ctx.bindings.peek ().merge ();
     225                 :             :     }
     226                 :         191 :   ctx.bindings.peek ().merge ();
     227                 :         191 : }
     228                 :             : 
     229                 :             : void
     230                 :       18160 : Late::visit_function_params (AST::Function &function)
     231                 :             : {
     232                 :       18160 :   ctx.bindings.enter (BindingSource::Param);
     233                 :             : 
     234                 :       37683 :   for (auto &param : function.get_function_params ())
     235                 :       19523 :     visit (param);
     236                 :             : 
     237                 :       18160 :   ctx.bindings.exit ();
     238                 :       18160 : }
     239                 :             : 
     240                 :             : void
     241                 :          98 : Late::visit (AST::StructPatternFieldIdent &field)
     242                 :             : {
     243                 :          98 :   visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
     244                 :          98 :                                field.get_node_id (), field.is_ref (),
     245                 :          98 :                                field.is_mut ());
     246                 :          98 : }
     247                 :             : 
     248                 :             : void
     249                 :        7982 : Late::visit (AST::SelfParam &param)
     250                 :             : {
     251                 :             :   // handle similar to AST::IdentifierPattern
     252                 :             : 
     253                 :        7982 :   DefaultResolver::visit (param);
     254                 :             :   // FIXME: this location should be a bit off
     255                 :             :   // ex: would point to the begining of "mut self" instead of the "self"
     256                 :       23946 :   std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
     257                 :        7982 :                                    param.get_node_id ());
     258                 :        7982 : }
     259                 :             : 
     260                 :             : void
     261                 :          89 : Late::visit (AST::BreakExpr &expr)
     262                 :             : {
     263                 :          89 :   if (expr.has_label ())
     264                 :          21 :     resolve_label (expr.get_label_unchecked ().get_lifetime ());
     265                 :             : 
     266                 :          89 :   if (expr.has_break_expr ())
     267                 :             :     {
     268                 :          22 :       auto &break_expr = expr.get_break_expr ();
     269                 :          22 :       if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
     270                 :             :         {
     271                 :             :           /* This is a break with an expression, and the expression is
     272                 :             :              just a single identifier.  See if the identifier is either
     273                 :             :              "rust" or "gcc", in which case we have "break rust" or "break
     274                 :             :              gcc", and so may need to emit our funny error.  We cannot yet
     275                 :             :              emit the error here though, because the identifier may still
     276                 :             :              be in scope, and ICE'ing on valid programs would not be very
     277                 :             :              funny.  */
     278                 :          11 :           std::string ident
     279                 :          11 :             = static_cast<AST::IdentifierExpr &> (expr.get_break_expr ())
     280                 :          11 :                 .as_string ();
     281                 :          11 :           if (ident == "rust" || ident == "gcc")
     282                 :           2 :             funny_error = true;
     283                 :          11 :         }
     284                 :             :     }
     285                 :             : 
     286                 :          89 :   DefaultResolver::visit (expr);
     287                 :             : 
     288                 :          88 :   funny_error = false;
     289                 :          88 : }
     290                 :             : 
     291                 :             : void
     292                 :          55 : Late::visit (AST::LoopLabel &label)
     293                 :             : {
     294                 :          55 :   auto &lifetime = label.get_lifetime ();
     295                 :         110 :   ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
     296                 :             :                      lifetime.get_node_id ());
     297                 :          55 : }
     298                 :             : 
     299                 :             : void
     300                 :          22 : Late::resolve_label (AST::Lifetime &lifetime)
     301                 :             : {
     302                 :          44 :   if (auto resolved = ctx.labels.get (lifetime.as_string ()))
     303                 :             :     {
     304                 :          17 :       if (resolved->get_node_id () != lifetime.get_node_id ())
     305                 :          17 :         ctx.map_usage (Usage (lifetime.get_node_id ()),
     306                 :          17 :                        Definition (resolved->get_node_id ()));
     307                 :             :     }
     308                 :             :   else
     309                 :           5 :     rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
     310                 :             :                    "use of undeclared label %qs",
     311                 :          10 :                    lifetime.as_string ().c_str ());
     312                 :          22 : }
     313                 :             : 
     314                 :             : void
     315                 :          12 : Late::visit (AST::ContinueExpr &expr)
     316                 :             : {
     317                 :          12 :   if (expr.has_label ())
     318                 :           1 :     resolve_label (expr.get_label_unchecked ());
     319                 :             : 
     320                 :          12 :   DefaultResolver::visit (expr);
     321                 :          12 : }
     322                 :             : 
     323                 :             : void
     324                 :       24296 : Late::visit (AST::IdentifierExpr &expr)
     325                 :             : {
     326                 :             :   // TODO: same thing as visit(PathInExpression) here?
     327                 :             : 
     328                 :       24296 :   tl::optional<Rib::Definition> resolved = tl::nullopt;
     329                 :       24296 :   if (auto value = ctx.values.get (expr.get_ident ()))
     330                 :             :     {
     331                 :       24276 :       resolved = value;
     332                 :             :     }
     333                 :          20 :   else if (auto type = ctx.types.get (expr.get_ident ()))
     334                 :             :     {
     335                 :          11 :       resolved = type;
     336                 :             :     }
     337                 :           9 :   else if (funny_error)
     338                 :             :     {
     339                 :           1 :       diagnostics::text_finalizer (global_dc)
     340                 :           1 :         = Resolver::funny_ice_text_finalizer;
     341                 :           1 :       emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
     342                 :             :                        "are you trying to break %s? how dare you?",
     343                 :           1 :                        expr.as_string ().c_str ());
     344                 :             :     }
     345                 :             :   else
     346                 :             :     {
     347                 :           8 :       if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
     348                 :             :         {
     349                 :           2 :           resolved = type;
     350                 :             :         }
     351                 :             :       else
     352                 :             :         {
     353                 :           6 :           rust_error_at (expr.get_locus (), ErrorCode::E0425,
     354                 :             :                          "cannot find value %qs in this scope",
     355                 :           6 :                          expr.get_ident ().as_string ().c_str ());
     356                 :           6 :           return;
     357                 :           8 :         }
     358                 :          19 :     }
     359                 :             : 
     360                 :       24289 :   if (resolved->is_ambiguous ())
     361                 :             :     {
     362                 :           0 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     363                 :           0 :                      expr.as_string ().c_str ());
     364                 :           0 :       return;
     365                 :             :     }
     366                 :             : 
     367                 :       24289 :   ctx.map_usage (Usage (expr.get_node_id ()),
     368                 :       24289 :                  Definition (resolved->get_node_id ()));
     369                 :             : 
     370                 :             :   // For empty types, do we perform a lookup in ctx.types or should the
     371                 :             :   // toplevel instead insert a name in ctx.values? (like it currently does)
     372                 :       24295 : }
     373                 :             : 
     374                 :             : void
     375                 :         216 : Late::visit (AST::StructExprFieldIdentifier &expr)
     376                 :             : {
     377                 :         216 :   tl::optional<Rib::Definition> resolved = tl::nullopt;
     378                 :             : 
     379                 :         216 :   if (auto value = ctx.values.get (expr.get_field_name ()))
     380                 :             :     {
     381                 :         216 :       resolved = value;
     382                 :             :     }
     383                 :             :   // seems like we don't need a type namespace lookup
     384                 :             :   else
     385                 :             :     {
     386                 :           0 :       rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
     387                 :           0 :                      expr.get_field_name ().as_string ().c_str ());
     388                 :           0 :       return;
     389                 :           0 :     }
     390                 :             : 
     391                 :         216 :   if (resolved->is_ambiguous ())
     392                 :             :     {
     393                 :           0 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     394                 :           0 :                      expr.as_string ().c_str ());
     395                 :           0 :       return;
     396                 :             :     }
     397                 :             : 
     398                 :         216 :   ctx.map_usage (Usage (expr.get_node_id ()),
     399                 :         216 :                  Definition (resolved->get_node_id ()));
     400                 :         216 : }
     401                 :             : 
     402                 :             : void
     403                 :       22859 : Late::visit (AST::PathInExpression &expr)
     404                 :             : {
     405                 :             :   // TODO: How do we have a nice error with `can't capture dynamic environment
     406                 :             :   // in a function item` error here?
     407                 :             :   // do we emit it in `get<Namespace::Labels>`?
     408                 :             : 
     409                 :       22859 :   DefaultResolver::visit (expr);
     410                 :             : 
     411                 :       22859 :   if (expr.is_lang_item ())
     412                 :             :     {
     413                 :         144 :       ctx.map_usage (Usage (expr.get_node_id ()),
     414                 :         144 :                      Definition (Analysis::Mappings::get ().get_lang_item_node (
     415                 :         144 :                        expr.get_lang_item ())));
     416                 :        1539 :       return;
     417                 :             :     }
     418                 :             : 
     419                 :       22715 :   auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
     420                 :             : 
     421                 :       22715 :   if (!resolved)
     422                 :             :     {
     423                 :        1394 :       if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
     424                 :           4 :         rust_error_at (expr.get_locus (), ErrorCode::E0433,
     425                 :             :                        "Cannot find path %qs in this scope",
     426                 :           4 :                        expr.as_simple_path ().as_string ().c_str ());
     427                 :        1394 :       return;
     428                 :             :     }
     429                 :             : 
     430                 :       21321 :   if (resolved->is_ambiguous ())
     431                 :             :     {
     432                 :           1 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     433                 :           1 :                      expr.as_string ().c_str ());
     434                 :           1 :       return;
     435                 :             :     }
     436                 :             : 
     437                 :       21320 :   ctx.map_usage (Usage (expr.get_node_id ()),
     438                 :       21320 :                  Definition (resolved->get_node_id ()));
     439                 :       22715 : }
     440                 :             : 
     441                 :             : void
     442                 :        5640 : Late::visit_impl_type (AST::Type &type)
     443                 :             : {
     444                 :             :   // TODO: does this have to handle reentrancy?
     445                 :        5640 :   rust_assert (!block_big_self);
     446                 :        5640 :   block_big_self = true;
     447                 :        5640 :   visit (type);
     448                 :        5640 :   block_big_self = false;
     449                 :        5640 : }
     450                 :             : 
     451                 :             : template <typename P>
     452                 :             : static void
     453                 :       55549 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
     454                 :             :                         P &type)
     455                 :             : {
     456                 :             :   // should we add type path resolution in `ForeverStack` directly? Since it's
     457                 :             :   // quite more complicated.
     458                 :             :   // maybe we can overload `resolve_path<Namespace::Types>` to only do
     459                 :             :   // typepath-like path resolution? that sounds good
     460                 :             : 
     461                 :             :   // prevent "impl Self {}" and similar
     462                 :       55549 :   if (type.get_segments ().size () == 1
     463                 :       54001 :       && !unwrap_segment_get_lang_item (type.get_segments ().front ())
     464                 :       54001 :             .has_value ()
     465                 :       53611 :       && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
     466                 :       62858 :       && block_big_self)
     467                 :             :     {
     468                 :           2 :       rust_error_at (type.get_locus (),
     469                 :             :                      "%<Self%> is not valid in the self type of an impl block");
     470                 :        1036 :       return;
     471                 :             :     }
     472                 :             : 
     473                 :             :   // this *should* mostly work
     474                 :             :   // TODO: make sure typepath-like path resolution (?) is working
     475                 :       55547 :   auto resolved = ctx.resolve_path (type, Namespace::Types);
     476                 :             : 
     477                 :       55547 :   if (!resolved.has_value ())
     478                 :             :     {
     479                 :        1034 :       if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ())))
     480                 :          23 :         rust_error_at (type.get_locus (), ErrorCode::E0412,
     481                 :             :                        "could not resolve type path %qs",
     482                 :          46 :                        unwrap_segment_error_string (type).c_str ());
     483                 :        1034 :       return;
     484                 :             :     }
     485                 :             : 
     486                 :       54513 :   if (resolved->is_ambiguous ())
     487                 :             :     {
     488                 :           0 :       rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     489                 :           0 :                      unwrap_segment_error_string (type).c_str ());
     490                 :           0 :       return;
     491                 :             :     }
     492                 :             : 
     493                 :       54513 :   if (ctx.types.forward_declared (resolved->get_node_id (),
     494                 :       54513 :                                   type.get_node_id ()))
     495                 :             :     {
     496                 :           1 :       rust_error_at (type.get_locus (), ErrorCode::E0128,
     497                 :             :                      "type parameters with a default cannot use forward "
     498                 :             :                      "declared identifiers");
     499                 :             :     }
     500                 :             : 
     501                 :       54513 :   ctx.map_usage (Usage (type.get_node_id ()),
     502                 :       54513 :                  Definition (resolved->get_node_id ()));
     503                 :       55547 : }
     504                 :             : 
     505                 :             : void
     506                 :       54146 : Late::visit (AST::TypePath &type)
     507                 :             : {
     508                 :       54146 :   DefaultResolver::visit (type);
     509                 :             : 
     510                 :       54146 :   resolve_type_path_like (ctx, block_big_self, type);
     511                 :       54146 : }
     512                 :             : 
     513                 :             : void
     514                 :       41674 : Late::visit (AST::Visibility &vis)
     515                 :             : {
     516                 :       41674 :   if (!vis.has_path ())
     517                 :       41612 :     return;
     518                 :             : 
     519                 :          65 :   AST::SimplePath &path = vis.get_path ();
     520                 :             : 
     521                 :          65 :   rust_assert (path.get_segments ().size ());
     522                 :          65 :   auto &first_seg = path.get_segments ()[0];
     523                 :             : 
     524                 :          65 :   auto mode = ResolutionMode::Normal;
     525                 :             : 
     526                 :          65 :   if (path.has_opening_scope_resolution ())
     527                 :             :     {
     528                 :           0 :       if (get_rust_edition () == Edition::E2015)
     529                 :             :         mode = ResolutionMode::FromRoot;
     530                 :             :       else
     531                 :          65 :         mode = ResolutionMode::FromExtern;
     532                 :             :     }
     533                 :          77 :   else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
     534                 :          74 :            && !first_seg.is_lower_self_seg ())
     535                 :             :     {
     536                 :           7 :       if (get_rust_edition () == Edition::E2015)
     537                 :             :         {
     538                 :             :           mode = ResolutionMode::FromRoot;
     539                 :             :         }
     540                 :             :       else
     541                 :             :         {
     542                 :           0 :           rust_error_at (path.get_locus (),
     543                 :             :                          "relative paths are not supported in visibilities in "
     544                 :             :                          "2018 edition or later");
     545                 :           0 :           return;
     546                 :             :         }
     547                 :             :     }
     548                 :             : 
     549                 :          65 :   auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
     550                 :             : 
     551                 :          65 :   if (!res.has_value ())
     552                 :             :     {
     553                 :           3 :       rust_error_at (path.get_locus (), ErrorCode::E0433,
     554                 :           3 :                      "could not resolve path %qs", path.as_string ().c_str ());
     555                 :           3 :       return;
     556                 :             :     }
     557                 :             : 
     558                 :             :   // TODO: is this possible?
     559                 :          62 :   if (res->is_ambiguous ())
     560                 :             :     {
     561                 :           0 :       rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     562                 :           0 :                      path.as_string ().c_str ());
     563                 :           0 :       return;
     564                 :             :     }
     565                 :             : 
     566                 :          62 :   ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
     567                 :          65 : }
     568                 :             : 
     569                 :             : void
     570                 :        3733 : Late::visit (AST::Trait &trait)
     571                 :             : {
     572                 :             :   // kind of weird how this is done
     573                 :             :   // names are resolved to the node id of trait.get_implicit_self ()
     574                 :             :   // which is then resolved to the node id of trait
     575                 :             :   // we set up the latter mapping here
     576                 :        3733 :   ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
     577                 :        3733 :                  Definition (trait.get_node_id ()));
     578                 :             : 
     579                 :        3733 :   DefaultResolver::visit (trait);
     580                 :        3733 : }
     581                 :             : 
     582                 :             : void
     583                 :          78 : Late::visit (AST::StructExprStruct &s)
     584                 :             : {
     585                 :          78 :   visit_outer_attrs (s);
     586                 :          78 :   visit_inner_attrs (s);
     587                 :          78 :   DefaultResolver::visit (s.get_struct_name ());
     588                 :             : 
     589                 :          78 :   resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
     590                 :          78 : }
     591                 :             : 
     592                 :             : void
     593                 :           0 : Late::visit (AST::StructExprStructBase &s)
     594                 :             : {
     595                 :           0 :   visit_outer_attrs (s);
     596                 :           0 :   visit_inner_attrs (s);
     597                 :           0 :   DefaultResolver::visit (s.get_struct_name ());
     598                 :           0 :   visit (s.get_struct_base ());
     599                 :             : 
     600                 :           0 :   resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
     601                 :           0 : }
     602                 :             : 
     603                 :             : void
     604                 :        1325 : Late::visit (AST::StructExprStructFields &s)
     605                 :             : {
     606                 :        1325 :   visit_outer_attrs (s);
     607                 :        1325 :   visit_inner_attrs (s);
     608                 :        1325 :   DefaultResolver::visit (s.get_struct_name ());
     609                 :        1325 :   if (s.has_struct_base ())
     610                 :          63 :     visit (s.get_struct_base ());
     611                 :        3609 :   for (auto &field : s.get_fields ())
     612                 :        2284 :     visit (field);
     613                 :             : 
     614                 :        1325 :   resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
     615                 :        1325 : }
     616                 :             : 
     617                 :             : // needed because Late::visit (AST::GenericArg &) is non-virtual
     618                 :             : void
     619                 :        3665 : Late::visit (AST::GenericArgs &args)
     620                 :             : {
     621                 :        3706 :   for (auto &lifetime : args.get_lifetime_args ())
     622                 :          41 :     visit (lifetime);
     623                 :             : 
     624                 :        7512 :   for (auto &generic : args.get_generic_args ())
     625                 :        3847 :     visit (generic);
     626                 :             : 
     627                 :        3737 :   for (auto &binding : args.get_binding_args ())
     628                 :          72 :     visit (binding);
     629                 :        3665 : }
     630                 :             : 
     631                 :             : void
     632                 :        3847 : Late::visit (AST::GenericArg &arg)
     633                 :             : {
     634                 :        3847 :   if (arg.get_kind () == AST::GenericArg::Kind::Either)
     635                 :             :     {
     636                 :             :       // prefer type parameter to const parameter on ambiguity
     637                 :        4678 :       auto type = ctx.types.get (arg.get_path ());
     638                 :        4678 :       auto value = ctx.values.get (arg.get_path ());
     639                 :             : 
     640                 :        2339 :       if (!type.has_value () && value.has_value ())
     641                 :          30 :         arg = arg.disambiguate_to_const ();
     642                 :             :       else
     643                 :        2309 :         arg = arg.disambiguate_to_type ();
     644                 :        3543 :     }
     645                 :             : 
     646                 :        3847 :   DefaultResolver::visit (arg);
     647                 :        3847 : }
     648                 :             : 
     649                 :             : void
     650                 :          67 : Late::visit_closure_params (AST::ClosureExpr &closure)
     651                 :             : {
     652                 :          67 :   ctx.bindings.enter (BindingSource::Param);
     653                 :             : 
     654                 :          67 :   DefaultResolver::visit_closure_params (closure);
     655                 :             : 
     656                 :          67 :   ctx.bindings.exit ();
     657                 :          67 : }
     658                 :             : 
     659                 :             : void
     660                 :          67 : Late::visit (AST::ClosureExpr &expr)
     661                 :             : {
     662                 :             :   // add captures
     663                 :          67 :   auto vals = ctx.values.peek ().get_values ();
     664                 :          88 :   for (auto &val : vals)
     665                 :             :     {
     666                 :          21 :       ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
     667                 :             :     }
     668                 :             : 
     669                 :          67 :   DefaultResolver::visit (expr);
     670                 :          67 : }
     671                 :             : 
     672                 :             : } // namespace Resolver2_0
     673                 :             : } // 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.