LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.3 % 264 241
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-diagnostics.h"
      20              : #include "rust-hir-map.h"
      21              : #include "rust-hir-path.h"
      22              : #include "rust-hir-type-check-expr.h"
      23              : #include "rust-hir-type-check-type.h"
      24              : #include "rust-hir-type-check-item.h"
      25              : #include "rust-hir-trait-resolve.h"
      26              : #include "rust-substitution-mapper.h"
      27              : #include "rust-hir-path-probe.h"
      28              : #include "rust-type-util.h"
      29              : #include "rust-hir-type-bounds.h"
      30              : #include "rust-hir-item.h"
      31              : #include "rust-session-manager.h"
      32              : #include "rust-immutable-name-resolution-context.h"
      33              : 
      34              : namespace Rust {
      35              : namespace Resolver {
      36              : 
      37              : void
      38          114 : TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
      39              : {
      40          114 :   HIR::QualifiedPathType qual_path_type = expr.get_path_type ();
      41          114 :   TyTy::BaseType *root = TypeCheckType::Resolve (qual_path_type.get_type ());
      42          114 :   if (root->get_kind () == TyTy::TypeKind::ERROR)
      43              :     return;
      44              : 
      45          114 :   if (!qual_path_type.has_as_clause ())
      46              :     {
      47           34 :       NodeId root_resolved_node_id = UNKNOWN_NODEID;
      48           34 :       resolve_segments (root_resolved_node_id, expr.get_segments (), 0, root,
      49              :                         expr.get_mappings (), expr.get_locus ());
      50           34 :       return;
      51              :     }
      52              : 
      53              :   // Resolve the trait now
      54           80 :   HIR::TypePath &trait_path_ref = qual_path_type.get_trait ();
      55           80 :   TraitReference *trait_ref = TraitResolver::Resolve (trait_path_ref);
      56           80 :   if (trait_ref->is_error ())
      57              :     return;
      58              : 
      59              :   // does this type actually implement this type-bound?
      60           80 :   if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
      61              :     return;
      62              : 
      63              :   // then we need to look at the next segment to create perform the correct
      64              :   // projection type
      65           80 :   if (expr.get_segments ().empty ())
      66              :     return;
      67              : 
      68              :   // get the predicate for the bound
      69           80 :   auto specified_bound
      70           80 :     = get_predicate_from_bound (trait_path_ref, qual_path_type.get_type ());
      71           80 :   if (specified_bound.is_error ())
      72              :     return;
      73              : 
      74              :   // inherit the bound
      75          160 :   root->inherit_bounds ({specified_bound});
      76              : 
      77              :   // lookup the associated item from the specified bound
      78           80 :   HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
      79           80 :   HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
      80           80 :   tl::optional<TyTy::TypeBoundPredicateItem> item
      81           80 :     = specified_bound.lookup_associated_item (item_seg_identifier.to_string ());
      82           80 :   if (!item.has_value ())
      83              :     {
      84            0 :       rust_error_at (item_seg.get_locus (), "unknown associated item");
      85            0 :       return;
      86              :     }
      87              : 
      88              :   // we try to look for the real impl item if possible
      89           80 :   HIR::ImplItem *impl_item = nullptr;
      90              : 
      91              :   // lookup the associated impl trait for this if we can (it might be generic)
      92           80 :   AssociatedImplTrait *associated_impl_trait
      93           80 :     = lookup_associated_impl_block (specified_bound, root);
      94           80 :   if (associated_impl_trait != nullptr)
      95              :     {
      96           54 :       associated_impl_trait->setup_associated_types (root, specified_bound);
      97              : 
      98           76 :       for (auto &i :
      99           76 :            associated_impl_trait->get_impl_block ()->get_impl_items ())
     100              :         {
     101           39 :           bool found = i->get_impl_item_name ().compare (
     102           39 :                          item_seg_identifier.to_string ())
     103           39 :                        == 0;
     104           39 :           if (found)
     105              :             {
     106           17 :               impl_item = i.get ();
     107           17 :               break;
     108              :             }
     109              :         }
     110              :     }
     111              : 
     112          117 :   NodeId root_resolved_node_id = UNKNOWN_NODEID;
     113           54 :   if (impl_item == nullptr)
     114              :     {
     115              :       // this may be valid as there could be a default trait implementation here
     116              :       // and we dont need to worry if the trait item is actually implemented or
     117              :       // not because this will have already been validated as part of the trait
     118              :       // impl block
     119           63 :       infered = item->get_tyty_for_receiver (root);
     120           63 :       root_resolved_node_id
     121           63 :         = item->get_raw_item ()->get_mappings ().get_nodeid ();
     122              :     }
     123              :   else
     124              :     {
     125           17 :       HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
     126           17 :       bool ok = query_type (impl_item_id, &infered);
     127           17 :       if (!ok)
     128              :         {
     129              :           // FIXME
     130              :           // I think query_type should error if required here anyway
     131              :           return;
     132              :         }
     133              : 
     134           17 :       root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid ();
     135              :     }
     136              : 
     137              :   // turbo-fish segment path::<ty>
     138           80 :   if (item_seg.has_generic_args ())
     139              :     {
     140            0 :       if (!infered->has_substitutions_defined ())
     141              :         {
     142            0 :           rust_error_at (item_seg.get_locus (),
     143              :                          "substitutions not supported for %s",
     144            0 :                          infered->as_string ().c_str ());
     145            0 :           infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     146            0 :           return;
     147              :         }
     148            0 :       std::vector<TyTy::Region> regions;
     149              : 
     150            0 :       infered = SubstMapper::Resolve (infered, expr.get_locus (),
     151            0 :                                       &item_seg.get_generic_args (),
     152            0 :                                       context->regions_from_generic_args (
     153            0 :                                         item_seg.get_generic_args ()));
     154            0 :     }
     155              : 
     156              :   // continue on as a path-in-expression
     157           80 :   bool fully_resolved = expr.get_segments ().size () <= 1;
     158           80 :   if (fully_resolved)
     159              :     {
     160           80 :       auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
     161           80 :         Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
     162              : 
     163           80 :       nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
     164           80 :                         Resolver2_0::Definition (root_resolved_node_id));
     165           80 :       return;
     166              :     }
     167              : 
     168            0 :   resolve_segments (root_resolved_node_id, expr.get_segments (), 1, infered,
     169              :                     expr.get_mappings (), expr.get_locus ());
     170          194 : }
     171              : 
     172              : void
     173        48536 : TypeCheckExpr::visit (HIR::PathInExpression &expr)
     174              : {
     175        48536 :   NodeId resolved_node_id = UNKNOWN_NODEID;
     176        48536 :   if (expr.is_lang_item ())
     177              :     {
     178          139 :       auto lookup
     179          139 :         = Analysis::Mappings::get ().get_lang_item_node (expr.get_lang_item ());
     180          139 :       auto hir_id = mappings.lookup_node_to_hir (lookup);
     181              : 
     182              :       // We can type resolve the path in expression easily as it is a lang
     183              :       // item path, but we still need to setup the various generics and
     184              :       // substitutions
     185              : 
     186              :       // FIXME: We probably need to check *if* the type needs substitutions
     187              :       // or not
     188          139 :       if (LangItem::IsEnumVariant (expr.get_lang_item ()))
     189              :         {
     190          106 :           std::pair<HIR::Enum *, HIR::EnumItem *> enum_item_lookup
     191          106 :             = mappings.lookup_hir_enumitem (*hir_id);
     192          212 :           bool enum_item_ok = enum_item_lookup.first != nullptr
     193          106 :                               && enum_item_lookup.second != nullptr;
     194            0 :           rust_assert (enum_item_ok);
     195              : 
     196          106 :           HirId variant_id
     197          106 :             = enum_item_lookup.second->get_mappings ().get_hirid ();
     198              : 
     199          106 :           HIR::EnumItem *enum_item = enum_item_lookup.second;
     200          106 :           resolved_node_id = enum_item->get_mappings ().get_nodeid ();
     201              : 
     202              :           // insert the id of the variant we are resolved to
     203          106 :           context->insert_variant_definition (expr.get_mappings ().get_hirid (),
     204              :                                               variant_id);
     205              : 
     206          106 :           query_type (variant_id, &infered);
     207          106 :           infered = SubstMapper::InferSubst (infered, expr.get_locus ());
     208              :         }
     209              :       else
     210              :         {
     211           33 :           TyTy::BaseType *resolved = nullptr;
     212           33 :           context->lookup_type (*hir_id, &resolved);
     213              : 
     214           33 :           rust_assert (resolved);
     215              : 
     216           33 :           query_type (*hir_id, &infered);
     217              : 
     218           33 :           infered = SubstMapper::InferSubst (resolved, expr.get_locus ());
     219              :         }
     220              : 
     221              :       // FIXME: also we probably need to insert resolved types in the name
     222              :       // resolver here
     223              :     }
     224              :   else
     225              :     {
     226        48397 :       size_t offset = -1;
     227        48397 :       TyTy::BaseType *tyseg
     228        48397 :         = resolve_root_path (expr, &offset, &resolved_node_id);
     229        48397 :       if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
     230        47016 :         return;
     231              : 
     232        48383 :       bool fully_resolved = offset == expr.get_segments ().size ();
     233        48383 :       if (fully_resolved)
     234              :         {
     235        47002 :           infered = tyseg;
     236        47002 :           return;
     237              :         }
     238              : 
     239         1381 :       resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg,
     240              :                         expr.get_mappings (), expr.get_locus ());
     241              :     }
     242              : }
     243              : 
     244              : TyTy::BaseType *
     245        48397 : TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
     246              :                                   NodeId *root_resolved_node_id)
     247              : {
     248        48397 :   TyTy::BaseType *root_tyty = nullptr;
     249        48397 :   *offset = 0;
     250       104442 :   for (size_t i = 0; i < expr.get_num_segments (); i++)
     251              :     {
     252        57437 :       HIR::PathExprSegment &seg = expr.get_segments ().at (i);
     253              : 
     254        57437 :       bool have_more_segments = (expr.get_num_segments () - 1 != i);
     255        57437 :       bool is_root = *offset == 0;
     256        57437 :       NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
     257              : 
     258        57437 :       auto &nr_ctx
     259        57437 :         = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     260              : 
     261              :       // lookup the reference_node_id
     262        57437 :       NodeId ref_node_id;
     263        57437 :       if (auto res = nr_ctx.lookup (ast_node_id))
     264              :         {
     265        56054 :           ref_node_id = *res;
     266              :         }
     267              :       else
     268              :         {
     269         1383 :           if (root_tyty != nullptr && *offset > 0)
     270              :             {
     271              :               // then we can let the impl path probe take over now
     272         1383 :               return root_tyty;
     273              :             }
     274              : 
     275            2 :           rust_error_at (seg.get_locus (),
     276              :                          "failed to type resolve root segment");
     277            2 :           return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     278              :         }
     279              : 
     280              :       // node back to HIR
     281        56054 :       tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
     282        56054 :       if (!hid.has_value ())
     283              :         {
     284            0 :           rust_error_at (seg.get_locus (), "456 reverse lookup failure");
     285            0 :           rust_debug_loc (seg.get_locus (),
     286              :                           "failure with [%s] mappings [%s] ref_node_id [%u]",
     287            0 :                           seg.to_string ().c_str (),
     288            0 :                           seg.get_mappings ().as_string ().c_str (),
     289              :                           ref_node_id);
     290              : 
     291            0 :           return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     292              :         }
     293        56054 :       auto ref = hid.value ();
     294              : 
     295        56054 :       auto seg_is_module = mappings.lookup_module (ref).has_value ();
     296        56054 :       auto seg_is_crate = mappings.is_local_hirid_crate (ref);
     297        56054 :       auto seg_is_pattern = mappings.lookup_hir_pattern (ref).has_value ();
     298        56054 :       auto seg_is_self = is_root && !have_more_segments
     299        96860 :                          && seg.get_segment ().to_string () == "self";
     300        56054 :       if (seg_is_module || seg_is_crate)
     301              :         {
     302              :           // A::B::C::this_is_a_module::D::E::F
     303              :           //          ^^^^^^^^^^^^^^^^
     304              :           //          Currently handling this.
     305         3629 :           if (have_more_segments)
     306              :             {
     307         3628 :               (*offset)++;
     308         3628 :               continue;
     309              :             }
     310              : 
     311              :           // In the case of :
     312              :           // A::B::C::this_is_a_module
     313              :           //          ^^^^^^^^^^^^^^^^
     314              :           // This is an error, we are not expecting a module.
     315            1 :           rust_error_at (seg.get_locus (), "expected value");
     316            1 :           return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     317              :         }
     318              : 
     319        52425 :       TyTy::BaseType *lookup = nullptr;
     320        52425 :       if (!query_type (ref, &lookup))
     321              :         {
     322            4 :           if (is_root || root_tyty == nullptr)
     323              :             {
     324            8 :               rust_error_at (expr.get_locus (), ErrorCode::E0425,
     325              :                              "cannot find value %qs in this scope",
     326            8 :                              expr.as_simple_path ().as_string ().c_str ());
     327              : 
     328            4 :               return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     329              :             }
     330              :           return root_tyty;
     331              :         }
     332              : 
     333              :       // is it an enum item?
     334        52421 :       std::pair<HIR::Enum *, HIR::EnumItem *> enum_item_lookup
     335        52421 :         = mappings.lookup_hir_enumitem (ref);
     336       108975 :       bool is_enum_item = enum_item_lookup.first != nullptr
     337        52421 :                           && enum_item_lookup.second != nullptr;
     338         4133 :       if (is_enum_item)
     339              :         {
     340         4133 :           HirId expr_id = expr.get_mappings ().get_hirid ();
     341         4133 :           HirId variant_id
     342         4133 :             = enum_item_lookup.second->get_mappings ().get_hirid ();
     343         4133 :           context->insert_variant_definition (expr_id, variant_id);
     344              :         }
     345              : 
     346              :       // if we have a previous segment type
     347        52421 :       if (root_tyty != nullptr)
     348              :         {
     349              :           // if this next segment needs substitution we must apply the
     350              :           // previous type arguments
     351              :           //
     352              :           // such as: GenericStruct::<_>::new(123, 456)
     353         4031 :           if (lookup->needs_generic_substitutions ())
     354              :             {
     355         1639 :               if (!root_tyty->needs_generic_substitutions ())
     356              :                 {
     357         1639 :                   auto used_args_in_prev_segment
     358         1639 :                     = GetUsedSubstArgs::From (root_tyty);
     359         1639 :                   lookup
     360         1639 :                     = SubstMapperInternal::Resolve (lookup,
     361              :                                                     used_args_in_prev_segment);
     362         1639 :                 }
     363              :             }
     364              :         }
     365              : 
     366              :       // turbo-fish segment path::<ty>
     367        52421 :       if (seg.has_generic_args ())
     368              :         {
     369          836 :           lookup = SubstMapper::Resolve (lookup, expr.get_locus (),
     370          836 :                                          &seg.get_generic_args (),
     371          836 :                                          context->regions_from_generic_args (
     372          836 :                                            seg.get_generic_args ()));
     373          836 :           if (lookup->get_kind () == TyTy::TypeKind::ERROR)
     374            4 :             return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     375              :         }
     376        51585 :       else if (lookup->needs_generic_substitutions () && !seg_is_pattern
     377        51585 :                && !seg_is_self)
     378              :         {
     379         4686 :           lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
     380              :         }
     381              : 
     382        52417 :       *root_resolved_node_id = ref_node_id;
     383        52417 :       *offset = *offset + 1;
     384        52417 :       root_tyty = lookup;
     385              :     }
     386              : 
     387              :   return root_tyty;
     388              : }
     389              : 
     390              : void
     391         1415 : TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
     392              :                                  std::vector<HIR::PathExprSegment> &segments,
     393              :                                  size_t offset, TyTy::BaseType *tyseg,
     394              :                                  const Analysis::NodeMapping &expr_mappings,
     395              :                                  location_t expr_locus)
     396              : {
     397         1415 :   NodeId resolved_node_id = root_resolved_node_id;
     398         1415 :   TyTy::BaseType *prev_segment = tyseg;
     399         1415 :   bool receiver_is_generic = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
     400         1415 :   bool receiver_is_dyn = prev_segment->get_kind () == TyTy::TypeKind::DYNAMIC;
     401              : 
     402         2828 :   for (size_t i = offset; i < segments.size (); i++)
     403              :     {
     404         1415 :       HIR::PathExprSegment &seg = segments.at (i);
     405         1415 :       bool probe_impls = !receiver_is_generic;
     406              : 
     407              :       // probe the path is done in two parts one where we search impls if no
     408              :       // candidate is found then we search extensions from traits
     409         1415 :       auto candidates
     410         1415 :         = PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
     411              :                                 false /*probe_bounds*/,
     412         1415 :                                 true /*ignore_mandatory_trait_items*/);
     413         1415 :       if (candidates.size () == 0)
     414              :         {
     415          516 :           candidates
     416          516 :             = PathProbeType::Probe (prev_segment, seg.get_segment (), false,
     417              :                                     true /*probe_bounds*/,
     418          516 :                                     false /*ignore_mandatory_trait_items*/);
     419              : 
     420          516 :           if (candidates.size () == 0)
     421              :             {
     422            0 :               rust_error_at (
     423              :                 seg.get_locus (),
     424              :                 "failed to resolve path segment using an impl Probe");
     425            0 :               return;
     426              :             }
     427              :         }
     428              : 
     429         1415 :       if (candidates.size () > 1)
     430              :         {
     431            1 :           ReportMultipleCandidateError::Report (candidates, seg.get_segment (),
     432              :                                                 seg.get_locus ());
     433            1 :           return;
     434              :         }
     435              : 
     436         1414 :       auto &candidate = *candidates.begin ();
     437         1414 :       prev_segment = tyseg;
     438         1414 :       tyseg = candidate.ty;
     439              : 
     440         1414 :       HIR::ImplBlock *associated_impl_block = nullptr;
     441         1414 :       if (candidate.is_enum_candidate ())
     442              :         {
     443            1 :           const TyTy::VariantDef *variant = candidate.item.enum_field.variant;
     444              : 
     445            1 :           HirId variant_id = variant->get_id ();
     446            1 :           std::pair<HIR::Enum *, HIR::EnumItem *> enum_item_lookup
     447            1 :             = mappings.lookup_hir_enumitem (variant_id);
     448            2 :           bool enum_item_ok = enum_item_lookup.first != nullptr
     449            1 :                               && enum_item_lookup.second != nullptr;
     450            0 :           rust_assert (enum_item_ok);
     451              : 
     452            1 :           HIR::EnumItem *enum_item = enum_item_lookup.second;
     453            1 :           resolved_node_id = enum_item->get_mappings ().get_nodeid ();
     454              : 
     455              :           // insert the id of the variant we are resolved to
     456            1 :           context->insert_variant_definition (expr_mappings.get_hirid (),
     457              :                                               variant_id);
     458              :         }
     459         1413 :       else if (candidate.is_impl_candidate ())
     460              :         {
     461          897 :           resolved_node_id
     462          897 :             = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid ();
     463              : 
     464          897 :           associated_impl_block = candidate.item.impl.parent;
     465              :         }
     466              :       else
     467              :         {
     468          516 :           resolved_node_id
     469          516 :             = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
     470              : 
     471              :           // lookup the associated-impl-trait
     472          516 :           HIR::ImplBlock *impl = candidate.item.trait.impl;
     473          516 :           if (impl != nullptr)
     474              :             {
     475              :               // get the associated impl block
     476              :               associated_impl_block = impl;
     477              :             }
     478              :         }
     479              : 
     480         1414 :       if (associated_impl_block != nullptr && !receiver_is_dyn)
     481              :         {
     482              :           // associated types
     483          941 :           HirId impl_block_id
     484          941 :             = associated_impl_block->get_mappings ().get_hirid ();
     485              : 
     486          941 :           AssociatedImplTrait *associated = nullptr;
     487          941 :           bool found_impl_trait
     488          941 :             = context->lookup_associated_trait_impl (impl_block_id,
     489              :                                                      &associated);
     490              : 
     491          941 :           auto mappings = TyTy::SubstitutionArgumentMappings::error ();
     492          941 :           TyTy::BaseType *impl_block_ty
     493          941 :             = TypeCheckItem::ResolveImplBlockSelfWithInference (
     494              :               *associated_impl_block, seg.get_locus (), &mappings);
     495              : 
     496              :           // we need to apply the arguments to the segment type so they get
     497              :           // unified properly
     498          941 :           if (!mappings.is_error ())
     499          172 :             tyseg = SubstMapperInternal::Resolve (tyseg, mappings);
     500              : 
     501         1882 :           prev_segment = unify_site (seg.get_mappings ().get_hirid (),
     502          941 :                                      TyTy::TyWithLocation (prev_segment),
     503          941 :                                      TyTy::TyWithLocation (impl_block_ty),
     504              :                                      seg.get_locus ());
     505          941 :           bool ok = prev_segment->get_kind () != TyTy::TypeKind::ERROR;
     506          941 :           if (!ok)
     507            1 :             return;
     508              : 
     509          940 :           if (found_impl_trait)
     510              :             {
     511              :               // we need to setup with apropriate bounds
     512          165 :               HIR::TypePath &bound_path
     513          165 :                 = associated->get_impl_block ()->get_trait_ref ();
     514          165 :               const auto &trait_ref = *TraitResolver::Resolve (bound_path);
     515          165 :               rust_assert (!trait_ref.is_error ());
     516              : 
     517          165 :               const auto &predicate
     518          165 :                 = impl_block_ty->lookup_predicate (trait_ref.get_defid ());
     519          165 :               if (!predicate.is_error ())
     520          150 :                 associated->setup_associated_types (prev_segment, predicate,
     521              :                                                     nullptr, false);
     522          165 :             }
     523          941 :         }
     524              : 
     525         1413 :       if (seg.has_generic_args ())
     526              :         {
     527           46 :           rust_debug_loc (seg.get_locus (), "applying segment generics: %s",
     528           46 :                           tyseg->as_string ().c_str ());
     529           46 :           tyseg
     530           46 :             = SubstMapper::Resolve (tyseg, expr_locus, &seg.get_generic_args (),
     531           46 :                                     context->regions_from_generic_args (
     532           46 :                                       seg.get_generic_args ()));
     533           46 :           if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
     534              :             return;
     535              :         }
     536         1367 :       else if (tyseg->needs_generic_substitutions () && !receiver_is_generic)
     537              :         {
     538          417 :           location_t locus = seg.get_locus ();
     539          417 :           tyseg = SubstMapper::InferSubst (tyseg, locus);
     540          417 :           if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
     541              :             return;
     542              :         }
     543         1415 :     }
     544              : 
     545         1413 :   rust_assert (resolved_node_id != UNKNOWN_NODEID);
     546              : 
     547         1413 :   auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
     548         1413 :     Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
     549              : 
     550         1413 :   nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()),
     551         1413 :                     Resolver2_0::Definition (resolved_node_id));
     552              : 
     553         1413 :   infered = tyseg;
     554              : }
     555              : 
     556              : } // namespace Resolver
     557              : } // 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.