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: 81.4 % 355 289
Test Date: 2026-07-11 15:47:05 Functions: 88.2 % 34 30
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 "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-rib.h"
      30              : #include "rust-system.h"
      31              : #include "rust-tyty.h"
      32              : #include "rust-hir-type-check.h"
      33              : #include "rust-ice-finalizer.h"
      34              : #include "rust-ast.h"
      35              : 
      36              : namespace Rust {
      37              : namespace Resolver2_0 {
      38              : 
      39         4767 : Late::Late (NameResolutionContext &ctx)
      40         4767 :   : DefaultResolver (ctx), funny_error (false), block_big_self (false)
      41         4767 : {}
      42              : 
      43              : void
      44         4767 : Late::go (AST::Crate &crate)
      45              : {
      46         4767 :   Builtins::setup_type_ctx ();
      47              : 
      48         4767 :   visit (crate);
      49         4765 : }
      50              : 
      51              : void
      52            0 : Late::new_label (Identifier name, NodeId id)
      53              : {
      54              :   // labels can always shadow, so `insert` should never fail. if it does, we're
      55              :   // in big trouble!
      56            0 :   auto ok = ctx.labels.insert (name, id);
      57              : 
      58            0 :   rust_assert (ok);
      59            0 : }
      60              : 
      61              : void
      62            0 : Late::visit (AST::ForLoopExpr &expr)
      63              : {
      64            0 :   visit_outer_attrs (expr);
      65              : 
      66            0 :   ctx.bindings.enter (BindingSource::For);
      67              : 
      68            0 :   visit (expr.get_pattern ());
      69              : 
      70            0 :   ctx.bindings.exit ();
      71              : 
      72            0 :   visit (expr.get_iterator_expr ());
      73              : 
      74            0 :   if (expr.has_loop_label ())
      75            0 :     visit (expr.get_loop_label ());
      76              : 
      77            0 :   visit (expr.get_loop_block ());
      78            0 : }
      79              : 
      80              : void
      81           30 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
      82              : {
      83           30 :   ctx.bindings.enter (BindingSource::IfLet);
      84              : 
      85           30 :   DefaultResolver::visit_if_let_patterns (expr);
      86              : 
      87           30 :   ctx.bindings.exit ();
      88           30 : }
      89              : 
      90              : void
      91         2518 : Late::visit (AST::MatchArm &arm)
      92              : {
      93         2518 :   visit_outer_attrs (arm);
      94              : 
      95         2518 :   ctx.bindings.enter (BindingSource::Match);
      96              : 
      97         2518 :   visit (arm.get_pattern ());
      98              : 
      99         2518 :   ctx.bindings.exit ();
     100              : 
     101         2518 :   if (arm.has_match_arm_guard ())
     102            1 :     visit (arm.get_guard_expr ());
     103         2518 : }
     104              : 
     105              : void
     106        12967 : Late::visit (AST::LetStmt &let)
     107              : {
     108        12967 :   DefaultASTVisitor::visit_outer_attrs (let);
     109        12967 :   if (let.has_type ())
     110         2167 :     visit (let.get_type ());
     111              :   // visit expression before pattern
     112              :   // this makes variable shadowing work properly
     113        12967 :   if (let.has_init_expr ())
     114        11819 :     visit (let.get_init_expr ());
     115              : 
     116        12966 :   ctx.bindings.enter (BindingSource::Let);
     117              : 
     118        12966 :   visit (let.get_pattern ());
     119              : 
     120        12966 :   ctx.bindings.exit ();
     121              : 
     122        12966 :   if (let.has_else_expr ())
     123            5 :     visit (let.get_else_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        12966 : }
     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 :   visit (while_let.get_pattern ());
     157              : 
     158            0 :   ctx.bindings.exit ();
     159              : 
     160            0 :   visit (while_let.get_loop_block ());
     161            0 : }
     162              : 
     163              : static void
     164        24755 : visit_identifier_as_pattern (NameResolutionContext &ctx,
     165              :                              const Identifier &ident, location_t locus,
     166              :                              NodeId node_id, bool is_ref, bool is_mut)
     167              : {
     168              :   // do we insert in labels or in values
     169              :   // but values does not allow shadowing... since functions cannot shadow
     170              :   // do we insert functions in labels as well?
     171              : 
     172        24755 :   if (ctx.bindings.peek ().is_and_bound (ident))
     173              :     {
     174            8 :       if (ctx.bindings.peek ().get_source () == BindingSource::Param)
     175            5 :         rust_error_at (
     176              :           locus, ErrorCode::E0415,
     177              :           "identifier %qs is bound more than once in the same parameter list",
     178            5 :           ident.as_string ().c_str ());
     179              :       else
     180            3 :         rust_error_at (
     181              :           locus, ErrorCode::E0416,
     182              :           "identifier %qs is bound more than once in the same pattern",
     183            3 :           ident.as_string ().c_str ());
     184            8 :       return;
     185              :     }
     186              : 
     187        49494 :   ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
     188              : 
     189        24747 :   if (ctx.bindings.peek ().is_or_bound (ident))
     190              :     {
     191           58 :       auto res = ctx.values.get (ident);
     192           58 :       rust_assert (res.has_value () && !res->is_ambiguous ());
     193           58 :       ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()),
     194              :                      Namespace::Values);
     195           58 :     }
     196              :   else
     197              :     {
     198              :       // We do want to ignore duplicated data because some situations rely on
     199              :       // it.
     200        24689 :       std::ignore = ctx.values.insert_shadowable (ident, node_id);
     201              :     }
     202              : }
     203              : 
     204              : void
     205        24655 : Late::visit (AST::IdentifierPattern &identifier)
     206              : {
     207        24655 :   DefaultResolver::visit (identifier);
     208              : 
     209        24655 :   visit_identifier_as_pattern (ctx, identifier.get_ident (),
     210              :                                identifier.get_locus (),
     211        24655 :                                identifier.get_node_id (),
     212        24655 :                                identifier.get_is_ref (),
     213        24655 :                                identifier.get_is_mut ());
     214        24655 : }
     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        18981 : Late::visit_function_params (AST::Function &function)
     231              : {
     232        18981 :   ctx.bindings.enter (BindingSource::Param);
     233              : 
     234        38919 :   for (auto &param : function.get_function_params ())
     235        19938 :     visit (param);
     236              : 
     237        18981 :   ctx.bindings.exit ();
     238        18981 : }
     239              : 
     240              : void
     241          100 : Late::visit (AST::StructPatternFieldIdent &field)
     242              : {
     243              :   // We need to check if the Identifier resolves to a variant or empty struct
     244          100 :   auto path = AST::SimplePath (field.get_identifier ());
     245              : 
     246          100 :   if (auto resolved = ctx.resolve_path (path, Namespace::Types))
     247              :     {
     248            0 :       ctx.map_usage (Usage (field.get_node_id ()),
     249            0 :                      Definition (resolved->definition.get_node_id ()),
     250              :                      Namespace::Types);
     251            0 :       return;
     252            0 :     }
     253              : 
     254          100 :   visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
     255          100 :                                field.get_node_id (), field.is_ref (),
     256          100 :                                field.is_mut ());
     257          100 : }
     258              : 
     259              : void
     260         8113 : Late::visit (AST::SelfParam &param)
     261              : {
     262              :   // handle similar to AST::IdentifierPattern
     263              : 
     264         8113 :   DefaultResolver::visit (param);
     265              :   // FIXME: this location should be a bit off
     266              :   // ex: would point to the beginning of "mut self" instead of the "self"
     267        24339 :   std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
     268         8113 :                                    param.get_node_id ());
     269         8113 : }
     270              : 
     271              : void
     272           99 : Late::visit (AST::BreakExpr &expr)
     273              : {
     274           99 :   if (expr.has_label ())
     275           27 :     resolve_label (expr.get_label_unchecked ().get_lifetime ());
     276              : 
     277           99 :   if (expr.has_break_expr ())
     278              :     {
     279           26 :       auto &break_expr = expr.get_break_expr_unchecked ();
     280           26 :       if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
     281              :         {
     282              :           /* This is a break with an expression, and the expression is
     283              :              just a single identifier.  See if the identifier is either
     284              :              "rust" or "gcc", in which case we have "break rust" or "break
     285              :              gcc", and so may need to emit our funny error.  We cannot yet
     286              :              emit the error here though, because the identifier may still
     287              :              be in scope, and ICE'ing on valid programs would not be very
     288              :              funny.  */
     289           11 :           std::string ident = static_cast<AST::IdentifierExpr &> (
     290           11 :                                 expr.get_break_expr_unchecked ())
     291           11 :                                 .as_string ();
     292           11 :           if (ident == "rust" || ident == "gcc")
     293            2 :             funny_error = true;
     294           11 :         }
     295              :     }
     296              : 
     297           99 :   DefaultResolver::visit (expr);
     298              : 
     299           98 :   funny_error = false;
     300           98 : }
     301              : 
     302              : void
     303           71 : Late::visit (AST::LoopLabel &label)
     304              : {
     305           71 :   auto resolved
     306           71 :     = ctx.lookup (label.get_lifetime ().get_node_id (), Namespace::Labels);
     307           71 :   if (resolved.has_value ())
     308           23 :     return;
     309           48 :   auto &lifetime = label.get_lifetime ();
     310           96 :   ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
     311              :                      lifetime.get_node_id ());
     312              : }
     313              : 
     314              : void
     315           30 : Late::resolve_label (AST::Lifetime &lifetime)
     316              : {
     317           60 :   if (auto resolved = ctx.labels.get (lifetime.as_string ()))
     318              :     {
     319           25 :       if (resolved->get_node_id () != lifetime.get_node_id ())
     320           25 :         ctx.map_usage (Usage (lifetime.get_node_id ()),
     321           25 :                        Definition (resolved->get_node_id ()),
     322              :                        Namespace::Labels);
     323              :     }
     324              :   else
     325            5 :     rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
     326              :                    "use of undeclared label %qs",
     327           10 :                    lifetime.as_string ().c_str ());
     328           30 : }
     329              : 
     330              : void
     331           17 : Late::visit (AST::ContinueExpr &expr)
     332              : {
     333           17 :   if (expr.has_label ())
     334            3 :     resolve_label (expr.get_label_unchecked ());
     335              : 
     336           17 :   DefaultResolver::visit (expr);
     337           17 : }
     338              : 
     339              : void
     340        24676 : Late::visit (AST::IdentifierExpr &expr)
     341              : {
     342              :   // TODO: same thing as visit(PathInExpression) here?
     343              : 
     344        24676 :   tl::optional<Rib::Definition> resolved = tl::nullopt;
     345        24676 :   tl::optional<Namespace> ns = tl::nullopt;
     346              : 
     347        24676 :   if (auto value = ctx.values.get (expr.get_ident ()))
     348              :     {
     349        24664 :       resolved = value;
     350        24664 :       ns = Namespace::Values;
     351              :     }
     352           12 :   else if (auto type = ctx.types.get (expr.get_ident ()))
     353              :     {
     354            0 :       resolved = type;
     355            0 :       ns = Namespace::Types;
     356              :     }
     357           12 :   else if (funny_error)
     358              :     {
     359            1 :       diagnostics::text_finalizer (global_dc)
     360            1 :         = Resolver::funny_ice_text_finalizer;
     361            1 :       emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
     362              :                        "are you trying to break %s? how dare you?",
     363            1 :                        expr.as_string ().c_str ());
     364              :     }
     365              :   else
     366              :     {
     367           11 :       if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
     368              :         {
     369            2 :           resolved = type;
     370            2 :           ns = Namespace::Types;
     371              :         }
     372            9 :       else if (!resolved && ctx.prelude)
     373              :         {
     374            0 :           resolved
     375            0 :             = ctx.values.get_from_prelude (*ctx.prelude, expr.get_ident ());
     376            0 :           ns = Namespace::Values;
     377              : 
     378            0 :           if (!resolved)
     379            0 :             resolved
     380            0 :               = ctx.types.get_from_prelude (*ctx.prelude, expr.get_ident ());
     381            0 :           ns = Namespace::Types;
     382           11 :         }
     383              : 
     384           11 :       if (!resolved)
     385              :         {
     386            9 :           rust_error_at (expr.get_locus (), ErrorCode::E0425,
     387              :                          "cannot find value %qs in this scope",
     388            9 :                          expr.get_ident ().as_string ().c_str ());
     389            9 :           return;
     390              :         }
     391           11 :     }
     392              : 
     393        24666 :   if (resolved->is_ambiguous ())
     394              :     {
     395            0 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     396            0 :                      expr.as_string ().c_str ());
     397            0 :       return;
     398              :     }
     399              : 
     400        24666 :   ctx.map_usage (Usage (expr.get_node_id ()),
     401        24666 :                  Definition (resolved->get_node_id ()), ns.value ());
     402              : 
     403              :   // For empty types, do we perform a lookup in ctx.types or should the
     404              :   // toplevel instead insert a name in ctx.values? (like it currently does)
     405        24675 : }
     406              : 
     407              : void
     408          216 : Late::visit (AST::StructExprFieldIdentifier &expr)
     409              : {
     410          216 :   tl::optional<Rib::Definition> resolved = tl::nullopt;
     411              : 
     412          216 :   if (auto value = ctx.values.get (expr.get_field_name ()))
     413              :     {
     414          216 :       resolved = value;
     415              :     }
     416              :   // seems like we don't need a type namespace lookup
     417              :   else
     418              :     {
     419            0 :       rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
     420            0 :                      expr.get_field_name ().as_string ().c_str ());
     421            0 :       return;
     422            0 :     }
     423              : 
     424          216 :   if (resolved->is_ambiguous ())
     425              :     {
     426            0 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     427            0 :                      expr.as_string ().c_str ());
     428            0 :       return;
     429              :     }
     430              : 
     431          216 :   ctx.map_usage (Usage (expr.get_node_id ()),
     432          216 :                  Definition (resolved->get_node_id ()), Namespace::Values);
     433          216 : }
     434              : 
     435              : void
     436        24585 : Late::visit (AST::PathInExpression &expr)
     437              : {
     438              :   // TODO: How do we have a nice error with `can't capture dynamic environment
     439              :   // in a function item` error here?
     440              :   // do we emit it in `get<Namespace::Labels>`?
     441              : 
     442        24585 :   DefaultResolver::visit (expr);
     443              : 
     444              :   // TODO: do we need a namespace associated with each lang item?
     445        24585 :   if (expr.is_lang_item ())
     446              :     {
     447          144 :       ctx.map_usage (Usage (expr.get_node_id ()),
     448          145 :                      Definition (Analysis::Mappings::get ().get_lang_item_node (
     449          145 :                        expr.get_lang_item ())),
     450              :                      Namespace::Values);
     451         1552 :       return;
     452              :     }
     453              : 
     454              :   // TODO: we need to know which namespace that was in actually
     455        24440 :   auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
     456              : 
     457        24440 :   if (!resolved)
     458              :     {
     459         1407 :       if (!ctx.lookup (expr.get_segments ().front ().get_node_id (),
     460              :                        Namespace::Values, Namespace::Types))
     461           16 :         rust_error_at (expr.get_locus (), ErrorCode::E0433,
     462              :                        "Cannot find path %qs in this scope",
     463           16 :                        expr.as_simple_path ().as_string ().c_str ());
     464         1407 :       return;
     465              :     }
     466              : 
     467        23033 :   if (resolved->definition.is_ambiguous ())
     468              :     {
     469            1 :       rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     470            1 :                      expr.as_string ().c_str ());
     471            1 :       return;
     472              :     }
     473              : 
     474        23032 :   ctx.map_usage (Usage (expr.get_node_id ()),
     475        23032 :                  Definition (resolved->definition.get_node_id ()),
     476        23032 :                  resolved->ns);
     477        24440 : }
     478              : 
     479              : void
     480         5749 : Late::visit_impl_type (AST::Type &type)
     481              : {
     482              :   // TODO: does this have to handle reentrancy?
     483         5749 :   rust_assert (!block_big_self);
     484         5749 :   block_big_self = true;
     485         5749 :   visit (type);
     486         5749 :   block_big_self = false;
     487         5749 : }
     488              : 
     489              : template <typename P>
     490              : static void
     491        55633 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
     492              :                         P &type)
     493              : {
     494              :   // should we add type path resolution in `ForeverStack` directly? Since it's
     495              :   // quite more complicated.
     496              :   // maybe we can overload `resolve_path<Namespace::Types>` to only do
     497              :   // typepath-like path resolution? that sounds good
     498              : 
     499              :   // prevent "impl Self {}" and similar
     500        55633 :   if (type.get_segments ().size () == 1
     501        54160 :       && !unwrap_segment_get_lang_item (type.get_segments ().front ())
     502        54160 :             .has_value ()
     503        53768 :       && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
     504        62911 :       && block_big_self)
     505              :     {
     506            2 :       rust_error_at (type.get_locus (),
     507              :                      "%<Self%> is not valid in the self type of an impl block");
     508         1066 :       return;
     509              :     }
     510              : 
     511              :   // this *should* mostly work
     512              :   // TODO: make sure typepath-like path resolution (?) is working
     513        55631 :   auto resolved = ctx.resolve_path (type, Namespace::Types);
     514              : 
     515        55631 :   if (!resolved.has_value ())
     516              :     {
     517         1061 :       if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()),
     518              :                        Namespace::Types))
     519           26 :         rust_error_at (type.get_locus (), ErrorCode::E0412,
     520              :                        "could not resolve type path %qs",
     521           52 :                        unwrap_segment_error_string (type).c_str ());
     522         1061 :       return;
     523              :     }
     524              : 
     525        54570 :   if (resolved->definition.is_ambiguous ())
     526              :     {
     527            0 :       rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     528            0 :                      unwrap_segment_error_string (type).c_str ());
     529            0 :       return;
     530              :     }
     531              : 
     532        54570 :   if (ctx.types.forward_declared (resolved->definition.get_node_id (),
     533        54570 :                                   type.get_node_id ()))
     534              :     {
     535            1 :       rust_error_at (type.get_locus (), ErrorCode::E0128,
     536              :                      "type parameters with a default cannot use forward "
     537              :                      "declared identifiers");
     538              :     }
     539              : 
     540       109140 :   if (Analysis::Mappings::get ().is_module (
     541        54570 :         resolved->definition.get_node_id ()))
     542              :     {
     543            3 :       if (type.get_segments ().size () == 1)
     544              :         {
     545            3 :           if (auto resolved
     546            3 :               = Builtins::find_builtin_node_id (type.as_string ()))
     547              :             {
     548            2 :               ctx.map_usage (Usage (type.get_node_id ()),
     549            2 :                              Definition (*resolved), Namespace::Types);
     550              : 
     551              :               // In that specific case, we also override the segment resolution
     552              :               // as it causes issues later down the line during typechecking
     553            2 :               ctx.map_usage (Usage (unwrap_segment_node_id (
     554            2 :                                type.get_segments ().front ())),
     555            2 :                              Definition (*resolved), Namespace::Types);
     556              :             }
     557              :           else
     558              :             {
     559            1 :               rust_error_at (type.get_locus (), ErrorCode::E0573,
     560              :                              "expected type, found module %qs",
     561            2 :                              unwrap_segment_error_string (type).c_str ());
     562              :             }
     563              :         }
     564              : 
     565            3 :       return;
     566              :     }
     567              : 
     568        54567 :   ctx.map_usage (Usage (type.get_node_id ()),
     569        54567 :                  Definition (resolved->definition.get_node_id ()),
     570              :                  Namespace::Types);
     571        55631 : }
     572              : 
     573              : void
     574        55551 : Late::visit (AST::TypePath &type)
     575              : {
     576        55551 :   DefaultResolver::visit (type);
     577              : 
     578        55551 :   resolve_type_path_like (ctx, block_big_self, type);
     579        55551 : }
     580              : 
     581              : void
     582        43433 : Late::visit (AST::Visibility &vis)
     583              : {
     584        43433 :   if (!vis.has_path ())
     585        43371 :     return;
     586              : 
     587           65 :   AST::SimplePath &path = vis.get_path ();
     588              : 
     589           65 :   rust_assert (path.get_segments ().size ());
     590           65 :   auto &first_seg = path.get_segments ()[0];
     591              : 
     592           65 :   auto mode = ResolutionMode::Normal;
     593              : 
     594           65 :   if (path.has_opening_scope_resolution ())
     595              :     {
     596            0 :       if (get_rust_edition () == Edition::E2015)
     597              :         mode = ResolutionMode::FromRoot;
     598              :       else
     599           65 :         mode = ResolutionMode::FromExtern;
     600              :     }
     601           77 :   else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
     602           74 :            && !first_seg.is_lower_self_seg ())
     603              :     {
     604            7 :       if (get_rust_edition () == Edition::E2015)
     605              :         {
     606              :           mode = ResolutionMode::FromRoot;
     607              :         }
     608              :       else
     609              :         {
     610            0 :           rust_error_at (path.get_locus (),
     611              :                          "relative paths are not supported in visibilities in "
     612              :                          "2018 edition or later");
     613            0 :           return;
     614              :         }
     615              :     }
     616              : 
     617           65 :   auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
     618              : 
     619           65 :   if (!res.has_value ())
     620              :     {
     621            3 :       rust_error_at (path.get_locus (), ErrorCode::E0433,
     622            3 :                      "could not resolve path %qs", path.as_string ().c_str ());
     623            3 :       return;
     624              :     }
     625              : 
     626              :   // TODO: is this possible?
     627           62 :   if (res->definition.is_ambiguous ())
     628              :     {
     629            0 :       rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
     630            0 :                      path.as_string ().c_str ());
     631            0 :       return;
     632              :     }
     633              : 
     634           62 :   ctx.map_usage (Usage (path.get_node_id ()),
     635           62 :                  Definition (res->definition.get_node_id ()), res->ns);
     636           65 : }
     637              : 
     638              : void
     639         3999 : Late::visit (AST::Trait &trait)
     640              : {
     641              :   // kind of weird how this is done
     642              :   // names are resolved to the node id of trait.get_implicit_self ()
     643              :   // which is then resolved to the node id of trait
     644              :   // we set up the latter mapping here
     645         3999 :   ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
     646         3999 :                  Definition (trait.get_node_id ()), Namespace::Types);
     647              : 
     648         3999 :   DefaultResolver::visit (trait);
     649         3999 : }
     650              : 
     651              : void
     652           82 : Late::visit (AST::StructExprStruct &s)
     653              : {
     654           82 :   visit_outer_attrs (s);
     655           82 :   visit_inner_attrs (s);
     656           82 :   DefaultResolver::visit (s.get_struct_name ());
     657              : 
     658           82 :   resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
     659           82 : }
     660              : 
     661              : void
     662            0 : Late::visit (AST::StructExprStructBase &s)
     663              : {
     664            0 :   visit_outer_attrs (s);
     665            0 :   visit_inner_attrs (s);
     666            0 :   DefaultResolver::visit (s.get_struct_name ());
     667            0 :   visit (s.get_struct_base ());
     668              : 
     669            0 :   resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
     670            0 : }
     671              : 
     672              : void
     673         1372 : Late::visit (AST::StructExprStructFields &s)
     674              : {
     675         1372 :   visit_outer_attrs (s);
     676         1372 :   visit_inner_attrs (s);
     677              : 
     678         1372 :   auto &path = s.get_struct_name ();
     679              : 
     680         1372 :   DefaultResolver::visit (path);
     681         1372 :   if (s.has_struct_base ())
     682           63 :     visit (s.get_struct_base ());
     683         3710 :   for (auto &field : s.get_fields ())
     684         2338 :     visit (field);
     685              : 
     686         1372 :   auto resolved = ctx.resolve_path (path, Namespace::Types);
     687              : 
     688         1372 :   if (!resolved)
     689              :     {
     690            0 :       rust_error_at (path.get_locus (), ErrorCode::E0433,
     691            0 :                      "could not resolve path %qs", path.as_string ().c_str ());
     692            0 :       return;
     693              :     }
     694              : 
     695         1372 :   ctx.map_usage (Usage (path.get_node_id ()),
     696         1372 :                  Definition (resolved->definition.get_node_id ()),
     697              :                  Namespace::Types);
     698         1372 : }
     699              : 
     700              : // needed because Late::visit (AST::GenericArg &) is non-virtual
     701              : void
     702         3722 : Late::visit (AST::GenericArgs &args)
     703              : {
     704         3756 :   for (auto &lifetime : args.get_lifetime_args ())
     705           34 :     visit (lifetime);
     706              : 
     707         7638 :   for (auto &generic : args.get_generic_args ())
     708         3916 :     visit (generic);
     709              : 
     710         3794 :   for (auto &binding : args.get_binding_args ())
     711           72 :     visit (binding);
     712         3722 : }
     713              : 
     714              : void
     715         3916 : Late::visit (AST::GenericArg &arg)
     716              : {
     717         3916 :   if (arg.get_kind () == AST::GenericArg::Kind::Either)
     718              :     {
     719              :       // prefer type parameter to const parameter on ambiguity
     720         4800 :       auto type = ctx.types.get (arg.get_path ());
     721         4800 :       auto value = ctx.values.get (arg.get_path ());
     722              : 
     723         2400 :       if (!type.has_value () && value.has_value ())
     724           31 :         arg = arg.disambiguate_to_const ();
     725              :       else
     726         2369 :         arg = arg.disambiguate_to_type ();
     727         3634 :     }
     728              : 
     729         3916 :   DefaultResolver::visit (arg);
     730         3916 : }
     731              : 
     732              : void
     733           67 : Late::visit_closure_params (AST::ClosureExpr &closure)
     734              : {
     735           67 :   ctx.bindings.enter (BindingSource::Param);
     736              : 
     737           67 :   DefaultResolver::visit_closure_params (closure);
     738              : 
     739           67 :   ctx.bindings.exit ();
     740           67 : }
     741              : 
     742              : void
     743           67 : Late::visit (AST::ClosureExpr &expr)
     744              : {
     745              :   // add captures
     746           67 :   auto vals = ctx.values.peek ().get_values ();
     747           88 :   for (auto &val : vals)
     748              :     {
     749           21 :       ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
     750              :     }
     751              : 
     752           67 :   DefaultResolver::visit (expr);
     753           67 : }
     754              : 
     755              : } // namespace Resolver2_0
     756              : } // 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.