LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-path-probe.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.1 % 235 193
Test Date: 2026-02-28 14:20:25 Functions: 80.6 % 31 25
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.h"
      20              : #include "rust-hir-trait-resolve.h"
      21              : #include "rust-type-util.h"
      22              : #include "rust-hir-type-bounds.h"
      23              : #include "rust-hir-full.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Resolver {
      27              : 
      28              : // PathProbeCandidate
      29              : 
      30            3 : PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field)
      31            3 :   : enum_field (enum_field)
      32            3 : {}
      33              : 
      34         6379 : PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl)
      35         6379 : {}
      36              : 
      37         2471 : PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait)
      38         2471 :   : trait (trait)
      39         2471 : {}
      40              : 
      41            3 : PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
      42              :                                         location_t locus,
      43            3 :                                         EnumItemCandidate enum_field)
      44            3 :   : type (type), ty (ty), locus (locus), item (enum_field)
      45            3 : {}
      46              : 
      47         6379 : PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
      48              :                                         location_t locus,
      49         6379 :                                         ImplItemCandidate impl)
      50         6379 :   : type (type), ty (ty), locus (locus), item (impl)
      51         6379 : {}
      52              : 
      53         2471 : PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
      54              :                                         location_t locus,
      55         2471 :                                         TraitItemCandidate trait)
      56         2471 :   : type (type), ty (ty), locus (locus), item (trait)
      57         2471 : {}
      58              : 
      59              : std::string
      60            0 : PathProbeCandidate::as_string () const
      61              : {
      62            0 :   return "PathProbe candidate TODO - as_string";
      63              : }
      64              : 
      65              : bool
      66         1578 : PathProbeCandidate::is_enum_candidate () const
      67              : {
      68         1578 :   return type == ENUM_VARIANT;
      69              : }
      70              : 
      71              : bool
      72        11268 : PathProbeCandidate::is_impl_candidate () const
      73              : {
      74        11268 :   return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
      75              : }
      76              : 
      77              : bool
      78            0 : PathProbeCandidate::is_trait_candidate () const
      79              : {
      80            0 :   return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
      81            0 :          || type == TRAIT_FUNC;
      82              : }
      83              : 
      84              : bool
      85            0 : PathProbeCandidate::is_full_trait_item_candidate () const
      86              : {
      87            0 :   return is_trait_candidate () && item.trait.impl == nullptr;
      88              : }
      89              : 
      90              : PathProbeCandidate
      91            0 : PathProbeCandidate::get_error ()
      92              : {
      93            0 :   return PathProbeCandidate (ERROR, nullptr, UNDEF_LOCATION,
      94            0 :                              ImplItemCandidate{nullptr, nullptr});
      95              : }
      96              : 
      97              : bool
      98            0 : PathProbeCandidate::is_error () const
      99              : {
     100            0 :   return type == ERROR;
     101              : }
     102              : 
     103              : DefId
     104         5672 : PathProbeCandidate::get_defid () const
     105              : {
     106         5672 :   switch (type)
     107              :     {
     108            0 :     case ENUM_VARIANT:
     109            0 :       return item.enum_field.variant->get_defid ();
     110         4020 :       break;
     111              : 
     112         4020 :     case IMPL_CONST:
     113         4020 :     case IMPL_TYPE_ALIAS:
     114         4020 :     case IMPL_FUNC:
     115         4020 :       return item.impl.impl_item->get_impl_mappings ().get_defid ();
     116         1652 :       break;
     117              : 
     118         1652 :     case TRAIT_ITEM_CONST:
     119         1652 :     case TRAIT_TYPE_ALIAS:
     120         1652 :     case TRAIT_FUNC:
     121         1652 :       return item.trait.item_ref->get_mappings ().get_defid ();
     122            0 :       break;
     123              : 
     124            0 :     case ERROR:
     125            0 :     default:
     126            0 :       return UNKNOWN_DEFID;
     127              :     }
     128              : 
     129              :   return UNKNOWN_DEFID;
     130              : }
     131              : 
     132              : bool
     133          265 : PathProbeCandidate::operator< (const PathProbeCandidate &c) const
     134              : {
     135          265 :   return get_defid () < c.get_defid ();
     136              : }
     137              : 
     138              : // PathProbeType
     139              : 
     140         3401 : PathProbeType::PathProbeType (TyTy::BaseType *receiver,
     141              :                               const HIR::PathIdentSegment &query,
     142         3401 :                               DefId specific_trait_id)
     143         3401 :   : TypeCheckBase (), receiver (receiver), search (query),
     144         3401 :     current_impl (nullptr), specific_trait_id (specific_trait_id)
     145         3401 : {}
     146              : 
     147              : std::set<PathProbeCandidate>
     148         2245 : PathProbeType::Probe (TyTy::BaseType *receiver,
     149              :                       const HIR::PathIdentSegment &segment_name,
     150              :                       bool probe_impls, bool probe_bounds,
     151              :                       bool ignore_mandatory_trait_items,
     152              :                       DefId specific_trait_id)
     153              : {
     154         2245 :   PathProbeType probe (receiver, segment_name, specific_trait_id);
     155         2245 :   if (probe_impls)
     156              :     {
     157         1347 :       if (receiver->get_kind () == TyTy::TypeKind::ADT)
     158              :         {
     159          619 :           const TyTy::ADTType *adt
     160              :             = static_cast<const TyTy::ADTType *> (receiver);
     161          619 :           if (adt->is_enum ())
     162            6 :             probe.process_enum_item_for_candiates (adt);
     163              :         }
     164              : 
     165         1347 :       probe.process_impl_items_for_candidates ();
     166              :     }
     167              : 
     168         2245 :   if (!probe_bounds)
     169         1580 :     return probe.candidates;
     170              : 
     171          665 :   if (!probe.is_receiver_generic ())
     172              :     {
     173           59 :       std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
     174           59 :         = TypeBoundsProbe::Probe (receiver);
     175          203 :       for (auto &candidate : probed_bounds)
     176              :         {
     177          144 :           const TraitReference *trait_ref = candidate.first;
     178          144 :           if (specific_trait_id != UNKNOWN_DEFID)
     179              :             {
     180            0 :               if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
     181            0 :                 continue;
     182              :             }
     183              : 
     184          144 :           HIR::ImplBlock *impl = candidate.second;
     185          144 :           probe.process_associated_trait_for_candidates (
     186              :             trait_ref, impl, ignore_mandatory_trait_items);
     187              :         }
     188           59 :     }
     189              : 
     190         1497 :   for (const TyTy::TypeBoundPredicate &predicate :
     191         1497 :        receiver->get_specified_bounds ())
     192              :     {
     193          832 :       const TraitReference *trait_ref = predicate.get ();
     194          832 :       if (specific_trait_id != UNKNOWN_DEFID)
     195              :         {
     196            0 :           if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
     197            0 :             continue;
     198              :         }
     199              : 
     200          832 :       probe.process_predicate_for_candidates (predicate,
     201              :                                               ignore_mandatory_trait_items);
     202              :     }
     203              : 
     204          665 :   return probe.candidates;
     205         2245 : }
     206              : 
     207              : void
     208         1253 : PathProbeType::visit (HIR::TypeAlias &alias)
     209              : {
     210         1253 :   Identifier name = alias.get_new_type_name ();
     211         2506 :   if (search.to_string ().compare (name.as_string ()) == 0)
     212              :     {
     213           14 :       HirId tyid = alias.get_mappings ().get_hirid ();
     214           14 :       TyTy::BaseType *ty = nullptr;
     215           14 :       if (!query_type (tyid, &ty))
     216            0 :         return;
     217              : 
     218           14 :       PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
     219           14 :                                                                 current_impl};
     220           14 :       PathProbeCandidate candidate{
     221              :         PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
     222           14 :         alias.get_locus (), impl_item_candidate};
     223           14 :       candidates.insert (std::move (candidate));
     224              :     }
     225         1253 : }
     226              : 
     227              : void
     228           92 : PathProbeType::visit (HIR::ConstantItem &constant)
     229              : {
     230           92 :   Identifier name = constant.get_identifier ();
     231          184 :   if (search.to_string ().compare (name.as_string ()) == 0)
     232              :     {
     233           52 :       HirId tyid = constant.get_mappings ().get_hirid ();
     234           52 :       TyTy::BaseType *ty = nullptr;
     235           52 :       if (!query_type (tyid, &ty))
     236            0 :         return;
     237              : 
     238           52 :       PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
     239           52 :                                                                 current_impl};
     240           52 :       PathProbeCandidate candidate{
     241              :         PathProbeCandidate::CandidateType::IMPL_CONST, ty,
     242           52 :         constant.get_locus (), impl_item_candidate};
     243           52 :       candidates.insert (std::move (candidate));
     244              :     }
     245           92 : }
     246              : 
     247              : void
     248         7632 : PathProbeType::visit (HIR::Function &function)
     249              : {
     250         7632 :   Identifier name = function.get_function_name ();
     251        15264 :   if (search.to_string ().compare (name.as_string ()) == 0)
     252              :     {
     253         1801 :       HirId tyid = function.get_mappings ().get_hirid ();
     254         1801 :       TyTy::BaseType *ty = nullptr;
     255         1801 :       if (!query_type (tyid, &ty))
     256            0 :         return;
     257              : 
     258         1801 :       PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
     259         1801 :                                                                 current_impl};
     260         1801 :       PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC,
     261              :                                    ty, function.get_locus (),
     262         1801 :                                    impl_item_candidate};
     263         1801 :       candidates.insert (std::move (candidate));
     264              :     }
     265         7632 : }
     266              : 
     267              : void
     268            6 : PathProbeType::process_enum_item_for_candiates (const TyTy::ADTType *adt)
     269              : {
     270            6 :   if (specific_trait_id != UNKNOWN_DEFID)
     271            3 :     return;
     272              : 
     273            6 :   TyTy::VariantDef *v;
     274           12 :   if (!adt->lookup_variant (search.to_string (), &v))
     275              :     return;
     276              : 
     277            3 :   PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
     278            3 :   PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT,
     279            3 :                                receiver->clone (),
     280            3 :                                mappings.lookup_location (adt->get_ty_ref ()),
     281            3 :                                enum_item_candidate};
     282            3 :   candidates.insert (std::move (candidate));
     283              : }
     284              : 
     285              : void
     286         1347 : PathProbeType::process_impl_items_for_candidates ()
     287              : {
     288         1347 :   mappings.iterate_impl_items (
     289         1347 :     [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
     290        47385 :       process_impl_item_candidate (id, item, impl);
     291        47385 :       return true;
     292              :     });
     293         1347 : }
     294              : 
     295              : void
     296        56618 : PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
     297              :                                             HIR::ImplBlock *impl)
     298              : {
     299        56618 :   current_impl = impl;
     300        56618 :   HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
     301        56618 :   TyTy::BaseType *impl_block_ty = nullptr;
     302        56618 :   if (!query_type (impl_ty_id, &impl_block_ty))
     303        47641 :     return;
     304              : 
     305        56618 :   if (!types_compatable (TyTy::TyWithLocation (receiver),
     306        56618 :                          TyTy::TyWithLocation (impl_block_ty),
     307              :                          impl->get_locus (), false))
     308              :     return;
     309              : 
     310              :   // lets visit the impl_item
     311         8977 :   item->accept_vis (*this);
     312              : }
     313              : 
     314              : void
     315          144 : PathProbeType::process_associated_trait_for_candidates (
     316              :   const TraitReference *trait_ref, HIR::ImplBlock *impl,
     317              :   bool ignore_mandatory_trait_items)
     318              : {
     319          144 :   const TraitItemReference *trait_item_ref = nullptr;
     320          288 :   if (!trait_ref->lookup_trait_item (search.to_string (), &trait_item_ref))
     321           71 :     return;
     322              : 
     323           73 :   bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
     324           73 :   if (ignore_mandatory_trait_items && trait_item_needs_implementation)
     325              :     return;
     326              : 
     327           73 :   PathProbeCandidate::CandidateType candidate_type;
     328           73 :   switch (trait_item_ref->get_trait_item_type ())
     329              :     {
     330              :     case TraitItemReference::TraitItemType::FN:
     331              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
     332              :       break;
     333              :     case TraitItemReference::TraitItemType::CONST:
     334              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
     335              :       break;
     336              :     case TraitItemReference::TraitItemType::TYPE:
     337              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
     338              :       break;
     339              : 
     340            0 :     case TraitItemReference::TraitItemType::ERROR:
     341            0 :     default:
     342            0 :       rust_unreachable ();
     343           73 :       break;
     344              :     }
     345              : 
     346           73 :   const TyTy::TypeBoundPredicate p (*trait_ref, BoundPolarity::RegularBound,
     347           73 :                                     UNDEF_LOCATION);
     348          146 :   TyTy::TypeBoundPredicateItem item (p, trait_item_ref);
     349              : 
     350           73 :   TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
     351           73 :   if (receiver->get_kind () != TyTy::DYNAMIC)
     352           73 :     trait_item_tyty = item.get_tyty_for_receiver (receiver);
     353              : 
     354           73 :   PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
     355              :                                                               trait_item_ref,
     356           73 :                                                               impl};
     357           73 :   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
     358              :                                trait_item_ref->get_locus (),
     359           73 :                                trait_item_candidate};
     360           73 :   candidates.insert (std::move (candidate));
     361              : }
     362              : 
     363              : void
     364          832 : PathProbeType::process_predicate_for_candidates (
     365              :   const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items)
     366              : {
     367          832 :   const TraitReference *trait_ref = predicate.get ();
     368              : 
     369          832 :   tl::optional<TyTy::TypeBoundPredicateItem> item
     370         1664 :     = predicate.lookup_associated_item (search.to_string ());
     371          832 :   if (!item.has_value ())
     372              :     return;
     373              : 
     374          605 :   if (ignore_mandatory_trait_items && item->needs_implementation ())
     375              :     return;
     376              : 
     377          605 :   const TraitItemReference *trait_item_ref = item->get_raw_item ();
     378          605 :   PathProbeCandidate::CandidateType candidate_type;
     379          605 :   switch (trait_item_ref->get_trait_item_type ())
     380              :     {
     381              :     case TraitItemReference::TraitItemType::FN:
     382              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
     383              :       break;
     384              :     case TraitItemReference::TraitItemType::CONST:
     385              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
     386              :       break;
     387              :     case TraitItemReference::TraitItemType::TYPE:
     388              :       candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
     389              :       break;
     390              : 
     391            0 :     case TraitItemReference::TraitItemType::ERROR:
     392            0 :     default:
     393            0 :       rust_unreachable ();
     394          605 :       break;
     395              :     }
     396              : 
     397          605 :   TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty ();
     398          605 :   if (receiver->get_kind () != TyTy::DYNAMIC)
     399          232 :     trait_item_tyty = item->get_tyty_for_receiver (receiver);
     400              : 
     401          605 :   PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
     402              :                                                               trait_item_ref,
     403          605 :                                                               nullptr};
     404          605 :   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
     405              :                                trait_item_ref->get_locus (),
     406          605 :                                trait_item_candidate};
     407          605 :   candidates.insert (std::move (candidate));
     408          832 : }
     409              : 
     410              : std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
     411            0 : PathProbeType::union_bounds (
     412              :   const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>> a,
     413              :   const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
     414              :   const
     415              : {
     416            0 :   std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
     417            0 :   for (auto &ref : a)
     418              :     {
     419            0 :       mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
     420              :     }
     421            0 :   for (auto &ref : b)
     422              :     {
     423            0 :       mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
     424              :     }
     425              : 
     426            0 :   std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
     427              : 
     428            0 :   for (auto it = mapper.begin (); it != mapper.end (); it++)
     429            0 :     union_set.emplace_back (it->second.first, it->second.second);
     430              : 
     431            0 :   return union_set;
     432            0 : }
     433              : 
     434              : bool
     435          665 : PathProbeType::is_receiver_generic () const
     436              : {
     437          665 :   const TyTy::BaseType *root = receiver->get_root ();
     438          665 :   bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
     439          665 :   bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
     440          665 :   return receiver_is_type_param || receiver_is_dyn;
     441              : }
     442              : 
     443              : // PathProbImplTrait
     444              : 
     445         1156 : PathProbeImplTrait::PathProbeImplTrait (TyTy::BaseType *receiver,
     446              :                                         const HIR::PathIdentSegment &query,
     447         1156 :                                         const TraitReference *trait_reference)
     448              :   : PathProbeType (receiver, query, UNKNOWN_DEFID),
     449         1156 :     trait_reference (trait_reference)
     450         1156 : {}
     451              : 
     452              : std::set<PathProbeCandidate>
     453         1156 : PathProbeImplTrait::Probe (TyTy::BaseType *receiver,
     454              :                            const HIR::PathIdentSegment &segment_name,
     455              :                            const TraitReference *trait_reference)
     456              : {
     457         1156 :   PathProbeImplTrait probe (receiver, segment_name, trait_reference);
     458              :   // iterate all impls for this trait and receiver
     459              :   // then search for possible candidates using base class behaviours
     460         1156 :   probe.process_trait_impl_items_for_candidates ();
     461         1156 :   return probe.candidates;
     462         1156 : }
     463              : 
     464              : void
     465         1156 : PathProbeImplTrait::process_trait_impl_items_for_candidates ()
     466              : {
     467         1156 :   mappings.iterate_impl_items (
     468         1156 :     [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
     469              :       // just need to check if this is an impl block for this trait the next
     470              :       // function checks the receiver
     471        30105 :       if (!impl->has_trait_ref ())
     472              :         return true;
     473              : 
     474        21600 :       TraitReference *resolved = TraitResolver::Lookup (impl->get_trait_ref ());
     475        21600 :       if (!trait_reference->is_equal (*resolved))
     476              :         return true;
     477              : 
     478         9233 :       process_impl_item_candidate (id, item, impl);
     479         9233 :       return true;
     480              :     });
     481         1156 : }
     482              : 
     483              : } // namespace Resolver
     484              : } // 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.