LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-path-probe-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.2 % 148 138
Test Date: 2026-10-03 16:17:38 Functions: 100.0 % 12 12
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-hir-path-probe-expr.h"
      20              : #include "rust-hir-item.h"
      21              : #include "rust-type-util.h"
      22              : #include "rust-hir-type-bounds.h"
      23              : 
      24              : namespace Rust {
      25              : namespace Resolver {
      26              : 
      27         1555 : PathProbeExpr::PathProbeExpr (TyTy::BaseType *receiver,
      28              :                               const HIR::PathIdentSegment &query)
      29         1555 :   : TypeCheckBase (), receiver (receiver), search (query)
      30         1555 : {}
      31              : 
      32              : std::set<PathProbeCandidate>
      33         1555 : PathProbeExpr::Probe (TyTy::BaseType *receiver,
      34              :                       const HIR::PathIdentSegment &segment_name)
      35              : {
      36         1555 :   PathProbeExpr probe (receiver, segment_name);
      37         1555 :   return probe.probe ();
      38         1555 : }
      39              : 
      40              : std::set<PathProbeCandidate>
      41         1555 : PathProbeExpr::probe ()
      42              : {
      43         1555 :   switch (receiver->get_kind ())
      44              :     {
      45           92 :     case TyTy::TypeKind::PARAM:
      46           92 :       probe_bounds ();
      47           92 :       return std::move (candidates);
      48              : 
      49          617 :     case TyTy::TypeKind::ADT:
      50          617 :       {
      51          617 :         auto *adt = static_cast<TyTy::ADTType *> (receiver);
      52          617 :         if (adt->is_enum ())
      53            4 :           process_enum_item_for_candidates (adt);
      54          617 :         probe_adt_impls (adt);
      55          617 :         break;
      56              :       }
      57              : 
      58          846 :     default:
      59          846 :       probe_fallback_impls ();
      60          846 :       break;
      61              :     }
      62              : 
      63         1463 :   if (candidates.empty ())
      64          462 :     probe_bounds ();
      65              : 
      66         1463 :   return std::move (candidates);
      67              : }
      68              : 
      69              : void
      70          617 : PathProbeExpr::probe_adt_impls (TyTy::ADTType *adt)
      71              : {
      72          617 :   auto adt_item = mappings.lookup_defid (adt->get_id ());
      73          617 :   if (!adt_item.has_value ())
      74              :     {
      75            0 :       probe_fallback_impls ();
      76          478 :       return;
      77              :     }
      78              : 
      79          617 :   DefId adt_id = adt_item.value ()->get_mappings ().get_defid ();
      80          617 :   mappings.iterate_adt_impl_items (
      81              :     adt_id,
      82          617 :     [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
      83         3158 :       if (impl->has_trait_ref ())
      84              :         return true;
      85              : 
      86         1625 :       return process_impl_item_candidate (id, item, impl);
      87              :     });
      88              : 
      89          617 :   if (!candidates.empty ())
      90              :     return;
      91              : 
      92          139 :   mappings.iterate_adt_impl_items (
      93              :     adt_id,
      94          278 :     [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
      95          247 :       if (!impl->has_trait_ref ())
      96              :         return true;
      97              : 
      98          247 :       return process_impl_item_candidate (id, item, impl);
      99              :     });
     100              : }
     101              : 
     102              : void
     103          846 : PathProbeExpr::probe_fallback_impls ()
     104              : {
     105          846 :   mappings.iterate_impl_items (
     106          846 :     [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
     107        54654 :       if (impl->has_trait_ref ())
     108              :         return true;
     109              : 
     110        24040 :       return process_impl_item_candidate (id, item, impl);
     111              :     });
     112              : 
     113          846 :   if (!candidates.empty ())
     114              :     return;
     115              : 
     116          445 :   mappings.iterate_impl_items (
     117          890 :     [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
     118        18203 :       if (!impl->has_trait_ref ())
     119              :         return true;
     120              : 
     121        13246 :       return process_impl_item_candidate (id, item, impl);
     122              :     });
     123              : }
     124              : 
     125              : void
     126            4 : PathProbeExpr::process_enum_item_for_candidates (const TyTy::ADTType *adt)
     127              : {
     128            4 :   TyTy::VariantDef *v;
     129            8 :   if (!adt->lookup_variant (search.to_string (), &v))
     130              :     return;
     131              : 
     132            1 :   PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
     133            1 :   PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT,
     134            1 :                                receiver->clone (),
     135            1 :                                mappings.lookup_location (adt->get_ty_ref ()),
     136            1 :                                enum_item_candidate};
     137            1 :   candidates.insert (std::move (candidate));
     138              : }
     139              : 
     140              : bool
     141        39158 : PathProbeExpr::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
     142              :                                             HIR::ImplBlock *impl)
     143              : {
     144        78316 :   if (search.to_string () != item->get_impl_item_name ())
     145              :     return true;
     146              : 
     147         5770 :   HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
     148         5770 :   TyTy::BaseType *impl_block_ty = nullptr;
     149         5770 :   if (!query_type (impl_ty_id, &impl_block_ty))
     150              :     return true;
     151              : 
     152         5770 :   if (!types_compatable (TyTy::TyWithLocation (receiver),
     153         5770 :                          TyTy::TyWithLocation (impl_block_ty),
     154              :                          impl->get_locus (), false))
     155              :     return true;
     156              : 
     157         1001 :   PathProbeCandidate::CandidateType candidate_type;
     158         1001 :   switch (item->get_impl_item_type ())
     159              :     {
     160              :     case HIR::ImplItem::FUNCTION:
     161              :       candidate_type = PathProbeCandidate::CandidateType::IMPL_FUNC;
     162              :       break;
     163           54 :     case HIR::ImplItem::CONSTANT:
     164           54 :       candidate_type = PathProbeCandidate::CandidateType::IMPL_CONST;
     165           54 :       break;
     166              :     case HIR::ImplItem::TYPE_ALIAS:
     167              :     default:
     168              :       return true;
     169              :     }
     170              : 
     171         1001 :   TyTy::BaseType *item_ty = nullptr;
     172         1001 :   if (!query_type (id, &item_ty))
     173              :     return true;
     174              : 
     175         1001 :   PathProbeCandidate::ImplItemCandidate impl_candidate{item, impl};
     176         1001 :   insert_candidate (
     177         1001 :     {candidate_type, item_ty, item->get_locus (), impl_candidate});
     178              : 
     179         1001 :   return true;
     180              : }
     181              : 
     182              : void
     183          554 : PathProbeExpr::probe_bounds ()
     184              : {
     185          554 :   if (!is_receiver_generic ())
     186              :     {
     187           61 :       auto probed_bounds = TypeBoundsProbe::Probe (receiver);
     188          206 :       for (auto &candidate : probed_bounds)
     189              :         {
     190          145 :           const TraitReference *trait_ref = candidate.first;
     191          145 :           process_associated_trait_for_candidates (trait_ref, candidate.second);
     192              :         }
     193           61 :     }
     194              : 
     195          579 :   for (const TyTy::TypeBoundPredicate &predicate :
     196         1133 :        receiver->get_specified_bounds ())
     197              :     {
     198          579 :       process_predicate_for_candidates (predicate);
     199              :     }
     200          554 : }
     201              : 
     202              : void
     203          145 : PathProbeExpr::process_associated_trait_for_candidates (
     204              :   const TraitReference *trait_ref, HIR::ImplBlock *impl)
     205              : {
     206          145 :   const TraitItemReference *trait_item_ref = nullptr;
     207          290 :   if (!trait_ref->lookup_trait_item (search.to_string (), &trait_item_ref))
     208           72 :     return;
     209              : 
     210           73 :   PathProbeCandidate::CandidateType candidate_type;
     211           73 :   switch (trait_item_ref->get_trait_item_type ())
     212              :     {
     213              :     case TraitItemReference::TraitItemType::FN:
     214              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
     215              :       break;
     216            0 :     case TraitItemReference::TraitItemType::CONST:
     217            0 :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
     218            0 :       break;
     219              :     case TraitItemReference::TraitItemType::TYPE:
     220              :       return;
     221              : 
     222            0 :     case TraitItemReference::TraitItemType::ERROR:
     223            0 :     default:
     224            0 :       rust_unreachable ();
     225           73 :       break;
     226              :     }
     227              : 
     228           73 :   const TyTy::TypeBoundPredicate p (*trait_ref, BoundPolarity::RegularBound,
     229           73 :                                     UNDEF_LOCATION);
     230          146 :   TyTy::TypeBoundPredicateItem item (p, trait_item_ref);
     231              : 
     232           73 :   TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
     233           73 :   if (receiver->get_kind () != TyTy::DYNAMIC)
     234           73 :     trait_item_tyty = item.get_tyty_for_receiver (receiver);
     235              : 
     236           73 :   PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
     237              :                                                               trait_item_ref,
     238           73 :                                                               impl};
     239           73 :   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
     240              :                                trait_item_ref->get_locus (),
     241           73 :                                trait_item_candidate};
     242           73 :   insert_candidate (std::move (candidate));
     243              : }
     244              : 
     245              : void
     246          579 : PathProbeExpr::process_predicate_for_candidates (
     247              :   const TyTy::TypeBoundPredicate &predicate)
     248              : {
     249          579 :   const TraitReference *trait_ref = predicate.get ();
     250              : 
     251          579 :   tl::optional<TyTy::TypeBoundPredicateItem> item
     252         1158 :     = predicate.lookup_associated_item (search.to_string ());
     253          579 :   if (!item.has_value ())
     254              :     return;
     255              : 
     256          493 :   const TraitItemReference *trait_item_ref = item->get_raw_item ();
     257          493 :   PathProbeCandidate::CandidateType candidate_type;
     258          493 :   switch (trait_item_ref->get_trait_item_type ())
     259              :     {
     260              :     case TraitItemReference::TraitItemType::FN:
     261              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
     262              :       break;
     263            1 :     case TraitItemReference::TraitItemType::CONST:
     264            1 :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
     265            1 :       break;
     266              :     case TraitItemReference::TraitItemType::TYPE:
     267              :       return;
     268              : 
     269            0 :     case TraitItemReference::TraitItemType::ERROR:
     270            0 :     default:
     271            0 :       rust_unreachable ();
     272          493 :       break;
     273              :     }
     274              : 
     275          493 :   TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty ();
     276          493 :   if (receiver->get_kind () != TyTy::DYNAMIC)
     277           92 :     trait_item_tyty = item->get_tyty_for_receiver (receiver);
     278              : 
     279          493 :   PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
     280              :                                                               trait_item_ref,
     281          493 :                                                               nullptr};
     282          493 :   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
     283              :                                trait_item_ref->get_locus (),
     284          493 :                                trait_item_candidate};
     285          493 :   insert_candidate (std::move (candidate));
     286          579 : }
     287              : 
     288              : void
     289         1567 : PathProbeExpr::insert_candidate (PathProbeCandidate candidate)
     290              : {
     291         1567 :   bool is_type
     292         1567 :     = candidate.type == PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS
     293         1567 :       || candidate.type == PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
     294         1567 :   if (!candidate.is_error () && !is_type)
     295         1567 :     candidates.insert (std::move (candidate));
     296         1567 : }
     297              : 
     298              : bool
     299          554 : PathProbeExpr::is_receiver_generic () const
     300              : {
     301          554 :   const TyTy::BaseType *root = receiver->get_root ();
     302          554 :   bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
     303          554 :   bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
     304          554 :   return receiver_is_type_param || receiver_is_dyn;
     305              : }
     306              : 
     307              : } // namespace Resolver
     308              : } // 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.