LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-trait-resolve.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.8 % 417 387
Test Date: 2026-07-11 15:47:05 Functions: 91.3 % 23 21
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2021-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-trait-resolve.h"
      20              : #include "rust-hir-trait-reference.h"
      21              : #include "rust-hir-type-check-expr.h"
      22              : #include "rust-rib.h"
      23              : #include "rust-substitution-mapper.h"
      24              : #include "rust-type-util.h"
      25              : #include "rust-finalized-name-resolution-context.h"
      26              : 
      27              : namespace Rust {
      28              : namespace Resolver {
      29              : 
      30              : TraitItemReference
      31         3355 : ResolveTraitItemToRef::Resolve (
      32              :   HIR::TraitItem &item, TyTy::BaseType *self,
      33              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
      34              : {
      35         3355 :   ResolveTraitItemToRef resolver (self, std::move (substitutions));
      36         3355 :   item.accept_vis (resolver);
      37         3355 :   return std::move (resolver.resolved);
      38         3355 : }
      39              : 
      40              : void
      41          739 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
      42              : {
      43              :   // create trait-item-ref
      44          739 :   location_t locus = type.get_locus ();
      45          739 :   bool is_optional = false;
      46         1478 :   std::string identifier = type.get_name ().as_string ();
      47              : 
      48          739 :   resolved = TraitItemReference (identifier, is_optional,
      49              :                                  TraitItemReference::TraitItemType::TYPE, &type,
      50         2217 :                                  self, substitutions, locus);
      51          739 : }
      52              : 
      53              : void
      54           39 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
      55              : {
      56              :   // create trait-item-ref
      57           39 :   location_t locus = cst.get_locus ();
      58           39 :   bool is_optional = cst.has_expr ();
      59           78 :   std::string identifier = cst.get_name ().as_string ();
      60              : 
      61           39 :   resolved = TraitItemReference (identifier, is_optional,
      62              :                                  TraitItemReference::TraitItemType::CONST, &cst,
      63          117 :                                  self, substitutions, locus);
      64           39 : }
      65              : 
      66              : void
      67         2577 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
      68              : {
      69              :   // create trait-item-ref
      70         2577 :   location_t locus = fn.get_locus ();
      71         2577 :   bool is_optional = fn.has_definition ();
      72         5154 :   std::string identifier = fn.get_decl ().get_function_name ().as_string ();
      73              : 
      74         2577 :   resolved = TraitItemReference (identifier, is_optional,
      75              :                                  TraitItemReference::TraitItemType::FN, &fn,
      76         7731 :                                  self, std::move (substitutions), locus);
      77         2577 : }
      78              : 
      79         3355 : ResolveTraitItemToRef::ResolveTraitItemToRef (
      80              :   TyTy::BaseType *self,
      81         3355 :   std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
      82         3355 :   : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
      83         3355 :     substitutions (std::move (substitutions))
      84         3355 : {}
      85              : 
      86              : // TraitItemReference items
      87              : 
      88              : TraitReference *
      89       496306 : TraitResolver::Resolve (HIR::TypePath &path)
      90              : {
      91       496306 :   TraitResolver resolver;
      92       496306 :   return resolver.resolve_path (path);
      93       496306 : }
      94              : 
      95              : TraitReference *
      96        96871 : TraitResolver::Resolve (HIR::Trait &trait)
      97              : {
      98        96871 :   TraitResolver resolver;
      99        96871 :   return resolver.resolve_trait (&trait);
     100        96871 : }
     101              : 
     102              : TraitReference *
     103        21990 : TraitResolver::Lookup (HIR::TypePath &path)
     104              : {
     105        21990 :   TraitResolver resolver;
     106        21990 :   return resolver.lookup_path (path);
     107        21990 : }
     108              : 
     109              : HIR::Trait *
     110      2234012 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
     111              : {
     112      2234012 :   TraitResolver resolver;
     113              : 
     114      2234012 :   HIR::Trait *lookup = nullptr;
     115      2234012 :   bool ok = resolver.resolve_path_to_trait (path, &lookup);
     116      2234012 :   return ok ? lookup : nullptr;
     117      2234012 : }
     118              : 
     119      2849179 : TraitResolver::TraitResolver () : TypeCheckBase () {}
     120              : 
     121              : bool
     122      2752308 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
     123              :                                       HIR::Trait **resolved) const
     124              : {
     125      2752308 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     126              : 
     127      2752308 :   NodeId ref;
     128      2752308 :   if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid (),
     129      2752308 :                                     Resolver2_0::Namespace::Types))
     130              :     {
     131      2752308 :       ref = *ref_opt;
     132              :     }
     133              :   else
     134              :     {
     135            0 :       rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
     136            0 :       return false;
     137              :     }
     138              : 
     139      2752308 :   auto hid = mappings.lookup_node_to_hir (ref);
     140      2752308 :   if (!hid)
     141              :     {
     142            0 :       rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
     143            0 :       return false;
     144              :     }
     145              : 
     146      2752308 :   auto resolved_item = mappings.lookup_hir_item (hid.value ());
     147      2752308 :   if (!resolved_item.has_value ())
     148              :     {
     149            0 :       rust_error_at (path.get_locus (),
     150              :                      "Failed to resolve trait by looking up hir node");
     151            0 :       return false;
     152              :     }
     153              : 
     154      2752308 :   if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
     155              :     {
     156            3 :       rich_location r (line_table, path.get_locus ());
     157            3 :       r.add_fixit_replace ("not a trait");
     158            3 :       rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
     159            6 :                      path.as_simple_path ().as_string ().c_str ());
     160            3 :       return false;
     161            3 :     }
     162              : 
     163      2752305 :   *resolved = static_cast<HIR::Trait *> (*resolved_item);
     164      2752305 :   return true;
     165              : }
     166              : 
     167              : TraitReference *
     168       496306 : TraitResolver::resolve_path (HIR::TypePath &path)
     169              : {
     170       496306 :   HIR::Trait *resolved_trait_reference;
     171       496306 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     172       496306 :   if (!ok)
     173            3 :     return &TraitReference::error_node ();
     174              : 
     175       496303 :   return resolve_trait (resolved_trait_reference);
     176              : }
     177              : 
     178              : TraitReference *
     179       593174 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
     180              : {
     181       593174 :   TraitReference *tref = &TraitReference::error_node ();
     182       593174 :   if (context->lookup_trait_reference (
     183       593174 :         trait_reference->get_mappings ().get_defid (), &tref))
     184              :     {
     185       589236 :       return tref;
     186              :     }
     187              : 
     188         3938 :   DefId trait_id = trait_reference->get_mappings ().get_defid ();
     189         3938 :   if (context->trait_query_in_progress (trait_id))
     190              :     {
     191            4 :       rust_error_at (
     192              :         trait_reference->get_locus (), ErrorCode::E0391,
     193              :         "cycle detected when computing the super predicates of %qs",
     194            4 :         trait_reference->get_name ().as_string ().c_str ());
     195            4 :       return &TraitReference::error_node ();
     196              :     }
     197              : 
     198         3934 :   TraitQueryGuard guard (trait_id);
     199         3934 :   TyTy::BaseType *self = nullptr;
     200         3934 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     201              : 
     202              :   // this needs to be special cased for the sized trait to not auto implemented
     203              :   // Sized on Self
     204         8514 :   for (auto &generic_param : trait_reference->get_generic_params ())
     205              :     {
     206         4580 :       switch (generic_param.get ()->get_kind ())
     207              :         {
     208              :         case HIR::GenericParam::GenericKind::LIFETIME:
     209              :         case HIR::GenericParam::GenericKind::CONST:
     210              :           // FIXME: Skipping Lifetime and Const completely until better
     211              :           // handling.
     212              :           break;
     213              : 
     214         4578 :         case HIR::GenericParam::GenericKind::TYPE:
     215         4578 :           {
     216         4578 :             auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
     217         4578 :             bool is_self
     218         4578 :               = typaram.get_type_representation ().as_string ().compare ("Self")
     219         4578 :                 == 0;
     220              : 
     221              :             // https://doc.rust-lang.org/std/marker/trait.Sized.html
     222              :             // The one exception is the implicit Self type of a trait
     223         4578 :             bool apply_sized = !is_self;
     224         4578 :             auto param_type
     225         4578 :               = TypeResolveGenericParam::Resolve (*generic_param, true,
     226         4578 :                                                   apply_sized);
     227              : 
     228         4578 :             context->insert_type (generic_param->get_mappings (), param_type);
     229         4578 :             substitutions.emplace_back (typaram, param_type);
     230              : 
     231         4578 :             if (is_self)
     232              :               {
     233         3934 :                 rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
     234         3934 :                 TyTy::ParamType *p
     235              :                   = static_cast<TyTy::ParamType *> (param_type);
     236         3934 :                 p->set_implicit_self_trait ();
     237         3934 :                 self = p;
     238              :               }
     239              :           }
     240         4578 :           break;
     241              :         }
     242              :     }
     243         3934 :   rust_assert (self != nullptr);
     244              : 
     245              :   // Check if there is a super-trait, and apply this bound to the Self
     246              :   // TypeParam
     247         7868 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     248              : 
     249              :   // copy the substitition mappings
     250         3934 :   std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
     251         3934 :   self_subst_copy.reserve (substitutions.size ());
     252              : 
     253         8512 :   for (auto &sub : substitutions)
     254         4578 :     self_subst_copy.push_back (sub.clone ());
     255              : 
     256              :   // They also inherit themselves as a bound this enables a trait item to
     257              :   // reference other Self::trait_items
     258         3934 :   specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
     259              :                                  std::move (self_subst_copy),
     260         7868 :                                  BoundPolarity::RegularBound,
     261         3934 :                                  trait_reference->get_locus ());
     262              : 
     263              :   // look for any
     264         7868 :   std::vector<TyTy::TypeBoundPredicate> super_traits;
     265         3934 :   if (trait_reference->has_type_param_bounds ())
     266              :     {
     267         1154 :       for (auto &bound : trait_reference->get_type_param_bounds ())
     268              :         {
     269          626 :           if (bound->get_bound_type ()
     270              :               == HIR::TypeParamBound::BoundType::TRAITBOUND)
     271              :             {
     272          626 :               HIR::TraitBound *b
     273          626 :                 = static_cast<HIR::TraitBound *> (bound.get ());
     274              : 
     275          626 :               auto predicate = get_predicate_from_bound (
     276              :                 b->get_path (),
     277              :                 tl::nullopt /*this will setup a PLACEHOLDER for self*/,
     278          626 :                 BoundPolarity::RegularBound, false, true);
     279          626 :               if (predicate.is_error ())
     280           19 :                 return &TraitReference::error_node ();
     281              : 
     282          607 :               specified_bounds.push_back (predicate);
     283          607 :               super_traits.push_back (predicate);
     284          626 :             }
     285              :         }
     286              :     }
     287         3915 :   self->inherit_bounds (specified_bounds);
     288              : 
     289         3915 :   context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
     290         7830 :   std::vector<TraitItemReference> item_refs;
     291         7270 :   for (auto &item : trait_reference->get_trait_items ())
     292              :     {
     293              :       // make a copy of the substs
     294         3355 :       std::vector<TyTy::SubstitutionParamMapping> item_subst;
     295         3355 :       item_subst.reserve (substitutions.size ());
     296              : 
     297         8136 :       for (auto &sub : substitutions)
     298         4781 :         item_subst.push_back (sub.clone ());
     299              : 
     300         3355 :       TraitItemReference trait_item_ref
     301         3355 :         = ResolveTraitItemToRef::Resolve (*item.get (), self,
     302         3355 :                                           std::move (item_subst));
     303         3355 :       item_refs.push_back (std::move (trait_item_ref));
     304         3355 :     }
     305              : 
     306         3915 :   TraitReference trait_object (trait_reference, item_refs, super_traits,
     307         3915 :                                std::move (substitutions));
     308         3915 :   context->insert_trait_reference (
     309         3915 :     trait_reference->get_mappings ().get_defid (), std::move (trait_object));
     310              : 
     311         3915 :   tref = &TraitReference::error_node ();
     312         3915 :   bool ok = context->lookup_trait_reference (
     313         3915 :     trait_reference->get_mappings ().get_defid (), &tref);
     314         3915 :   rust_assert (ok);
     315              : 
     316              :   // hook to allow the trait to resolve its optional item blocks, we cant
     317              :   // resolve the blocks of functions etc because it can end up in a recursive
     318              :   // loop of trying to resolve traits as required by the types
     319         3915 :   tref->on_resolved ();
     320         3915 :   context->block_context ().exit ();
     321              : 
     322         3915 :   return tref;
     323         3934 : }
     324              : 
     325              : TraitReference *
     326        21990 : TraitResolver::lookup_path (HIR::TypePath &path)
     327              : {
     328        21990 :   HIR::Trait *resolved_trait_reference;
     329        21990 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     330        21990 :   if (!ok)
     331            0 :     return &TraitReference::error_node ();
     332              : 
     333        21990 :   TraitReference *tref = &TraitReference::error_node ();
     334        21990 :   if (context->lookup_trait_reference (
     335        21990 :         resolved_trait_reference->get_mappings ().get_defid (), &tref))
     336              :     {
     337        21990 :       return tref;
     338              :     }
     339            0 :   return &TraitReference::error_node ();
     340              : }
     341              : 
     342              : void
     343         3355 : TraitItemReference::on_resolved (const TraitReference *tref)
     344              : {
     345         3355 :   switch (type)
     346              :     {
     347           39 :     case CONST:
     348           39 :       resolve_item (tref, static_cast<HIR::TraitItemConst &> (*hir_trait_item));
     349           39 :       break;
     350              : 
     351          739 :     case TYPE:
     352          739 :       resolve_item (tref, static_cast<HIR::TraitItemType &> (*hir_trait_item));
     353          739 :       break;
     354              : 
     355         2577 :     case FN:
     356         2577 :       resolve_item (tref, static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
     357         2577 :       break;
     358              : 
     359              :     default:
     360              :       break;
     361              :     }
     362         3355 : }
     363              : 
     364              : void
     365          739 : TraitItemReference::resolve_item (const TraitReference *tref,
     366              :                                   HIR::TraitItemType &type)
     367              : {
     368          739 :   auto substitutions = inherited_substitutions;
     369          739 :   if (type.has_generics ())
     370              :     {
     371           17 :       auto binder_pin = context->push_lifetime_binder ();
     372           17 :       TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::TypeAlias,
     373              :                                            type.get_locus (),
     374           17 :                                            type.get_generic_params (),
     375              :                                            substitutions, false, ABI::RUST);
     376           17 :     }
     377              : 
     378          739 :   size_t inherited_count = inherited_substitutions.size ();
     379          739 :   auto projection
     380          739 :     = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), nullptr,
     381          739 :                                 tref, type.get_mappings ().get_defid (),
     382              :                                 substitutions, self,
     383         1478 :                                 TyTy::SubstitutionArgumentMappings::error (),
     384         1478 :                                 {}, {}, inherited_count);
     385              : 
     386              :   // Attach the bounds declared on the associated type itself:
     387              :   //
     388              :   //     type IntoIter: Iterator<Item = Self::Item>
     389              :   //
     390              :   // so satisfies_bound finds them in specified_bounds
     391          739 :   if (type.has_type_param_bounds ())
     392              :     {
     393           36 :       std::vector<TyTy::TypeBoundPredicate> trait_item_bounds;
     394           72 :       for (auto &bound : type.get_type_param_bounds ())
     395              :         {
     396           36 :           if (bound->get_bound_type ()
     397              :               != HIR::TypeParamBound::BoundType::TRAITBOUND)
     398            0 :             continue;
     399           36 :           auto *b = static_cast<HIR::TraitBound *> (bound.get ());
     400           36 :           auto predicate = TypeCheckBase::ResolvePredicateFromBound (
     401              :             b->get_path (),
     402              :             tl::nullopt /*this will setup a PLACEHOLDER for self*/,
     403           36 :             BoundPolarity::RegularBound, false, true);
     404           36 :           if (!predicate.is_error ())
     405           36 :             trait_item_bounds.push_back (std::move (predicate));
     406           36 :         }
     407           36 :       if (!trait_item_bounds.empty ())
     408           36 :         projection->inherit_bounds (trait_item_bounds);
     409           36 :     }
     410              : 
     411          739 :   context->insert_type (type.get_mappings (), projection);
     412          739 : }
     413              : 
     414              : void
     415           39 : TraitItemReference::resolve_item (const TraitReference *tref,
     416              :                                   HIR::TraitItemConst &constant)
     417              : {
     418           39 :   TyTy::BaseType *ty = nullptr;
     419           39 :   if (constant.has_type ())
     420           11 :     ty = TypeCheckType::Resolve (constant.get_type ());
     421              : 
     422           39 :   TyTy::BaseType *expr = nullptr;
     423           39 :   if (constant.has_expr ())
     424           11 :     expr = TypeCheckExpr::Resolve (constant.get_expr ());
     425              : 
     426           50 :   bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
     427           50 :   bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
     428              : 
     429           10 :   if (have_specified_ty && have_expr_ty)
     430              :     {
     431           20 :       coercion_site (constant.get_mappings ().get_hirid (),
     432              :                      TyTy::TyWithLocation (ty,
     433           10 :                                            constant.get_type ().get_locus ()),
     434              :                      TyTy::TyWithLocation (expr,
     435           10 :                                            constant.get_expr ().get_locus ()),
     436              :                      constant.get_locus ());
     437              :     }
     438           39 : }
     439              : 
     440              : void
     441         2577 : TraitItemReference::resolve_item (const TraitReference *tref,
     442              :                                   HIR::TraitItemFunc &func)
     443              : {
     444         2577 :   TyTy::BaseType *item_tyty = get_tyty ();
     445         2577 :   if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
     446              :     return;
     447              : 
     448         2575 :   if (!is_optional ())
     449              :     return;
     450              : 
     451              :   // check the block and return types
     452          858 :   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
     453              : 
     454              :   // need to get the return type from this
     455          858 :   TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
     456          858 :   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
     457          858 :   context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
     458              : 
     459          858 :   auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
     460              : 
     461          858 :   location_t fn_return_locus
     462          858 :     = func.get_decl ().has_return_type ()
     463          858 :         ? func.get_decl ().get_return_type ().get_locus ()
     464          193 :         : func.get_locus ();
     465              : 
     466         1716 :   coercion_site (func.get_mappings ().get_hirid (),
     467          858 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     468          858 :                  TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
     469              : 
     470          858 :   context->pop_return_type ();
     471              : }
     472              : 
     473              : TyTy::SubstitutionArgumentMappings
     474         3220 : AssociatedImplTrait::bind_impl_for_projection (TyTy::ProjectionType &proj,
     475              :                                                location_t locus)
     476              : {
     477         3220 :   std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
     478         6158 :   for (auto &generic_param : impl->get_generic_params ())
     479              :     {
     480         2938 :       if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE)
     481          232 :         continue;
     482         2938 :       TyTy::BaseType *l = nullptr;
     483         2938 :       bool ok
     484         2938 :         = context->lookup_type (generic_param->get_mappings ().get_hirid (),
     485              :                                 &l);
     486         2938 :       if (!ok || l->get_kind () != TyTy::TypeKind::PARAM)
     487          232 :         continue;
     488         2706 :       impl_substitutions.emplace_back (static_cast<HIR::TypeParam &> (
     489         2706 :                                          *generic_param),
     490         2706 :                                        static_cast<TyTy::ParamType *> (l));
     491              :     }
     492              : 
     493              :   // Build infer args for each impl param so we dont mutate the impls own
     494              :   // ParamTys when unifying. param_mappings records impl_param_symbol ->
     495              :   // hirid_of_fresh_infer_var so we can read out what each param resolved to
     496              :   // after unification.
     497         3220 :   std::vector<TyTy::SubstitutionArg> infer_arg_vec;
     498         3220 :   std::map<std::string, HirId> param_mappings;
     499         5926 :   for (auto &p : impl_substitutions)
     500              :     {
     501         2706 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     502         2706 :       TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
     503         2706 :       TyTy::BaseType *resolved = infer_var.get_tyty ();
     504         2706 :       infer_arg_vec.emplace_back (&p, resolved);
     505         2706 :       param_mappings[symbol] = resolved->get_ref ();
     506         2706 :     }
     507         3220 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     508              :     std::move (infer_arg_vec), {} /*binding_args*/,
     509         3220 :     TyTy::RegionParamList (0) /*regions*/, locus);
     510              : 
     511         3220 :   TyTy::BaseType *impl_self_infer
     512         3220 :     = !self->is_concrete ()
     513         3220 :         ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
     514          843 :         : self->clone ();
     515              : 
     516              :   // sub the impls trait predicate args with infers:
     517              :   //   SliceIndex<[Y]> -> SliceIndex<[?Y]>
     518         3220 :   const TyTy::TypeBoundPredicate &impl_predicate = predicate;
     519         3220 :   std::vector<TyTy::BaseType *> impl_predicate_args;
     520         3675 :   for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
     521              :     {
     522          455 :       auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
     523          455 :       TyTy::BaseType *r = p->resolve ();
     524          455 :       if (!r->is_concrete ())
     525          364 :         r = SubstMapperInternal::Resolve (r, infer_arguments);
     526          455 :       impl_predicate_args.push_back (r);
     527              :     }
     528              : 
     529              :   // Read the projections own (trait-coord) substs and skip Self at index 0.
     530              :   // The projection's substs match by symbol in handle_substitions, so a
     531              :   // fn-level substitution that binds T won't have walked into the
     532              :   // projections X slot whose resolved value is [T]. Re-apply the
     533              :   // projections own used_arguments to each arg so any stale impl-coord
     534              :   // params inside (the T inside [T]) are followed through to their
     535              :   // current bindings
     536         3220 :   TyTy::SubstitutionArgumentMappings proj_used
     537         3220 :     = proj.get_substitution_arguments ();
     538         3220 :   std::vector<TyTy::BaseType *> proj_args;
     539         3682 :   for (size_t i = 1; i < proj.get_substs ().size (); i++)
     540              :     {
     541          462 :       auto p = proj.get_substs ().at (i).get_param_ty ();
     542          462 :       TyTy::BaseType *r = p->resolve ();
     543          462 :       if (!r->is_concrete () && !proj_used.is_empty ())
     544           14 :         r = SubstMapperInternal::Resolve (r, proj_used);
     545          462 :       proj_args.push_back (r);
     546              :     }
     547              : 
     548         3220 :   if (impl_predicate_args.size () != proj_args.size ())
     549            7 :     return TyTy::SubstitutionArgumentMappings::error ();
     550              : 
     551              :   // unify trait args [?Y] -> [{integer}]
     552         3668 :   for (size_t i = 0; i < proj_args.size (); i++)
     553              :     {
     554          455 :       TyTy::BaseType *proj_arg = proj_args[i];
     555          455 :       if (impl_predicate_args[i]->get_kind () == TyTy::TypeKind::SLICE
     556          455 :           && proj_arg->get_kind () != TyTy::TypeKind::SLICE)
     557              :         {
     558          252 :           auto &mappings = Analysis::Mappings::get ();
     559          252 :           HirId id = mappings.get_next_hir_id ();
     560          252 :           auto *wrapped
     561              :             = new TyTy::SliceType (id, proj_arg->get_locus (),
     562          252 :                                    TyTy::TyVar (proj_arg->get_ref ()));
     563          252 :           context->insert_implicit_type (id, wrapped);
     564          252 :           proj_arg = wrapped;
     565              :         }
     566              : 
     567          455 :       auto *res = unify_site_and (0 /*id*/,
     568          455 :                                   TyTy::TyWithLocation (impl_predicate_args[i]),
     569          455 :                                   TyTy::TyWithLocation (proj_arg), locus,
     570              :                                   false /*emit_errors*/, true /*commit_if_ok*/,
     571              :                                   true /*infer*/, true /*cleanup_on_fail*/,
     572              :                                   false /*check_bounds*/);
     573          455 :       if (res->get_kind () == TyTy::TypeKind::ERROR)
     574            0 :         return TyTy::SubstitutionArgumentMappings::error ();
     575              :     }
     576              : 
     577              :   // unify self Range<{integer}> -> Range<usize>
     578         3213 :   auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
     579         3213 :                               TyTy::TyWithLocation (proj.get_self ()),
     580         3213 :                               TyTy::TyWithLocation (impl_self_infer), locus,
     581              :                               false /*emit_errors*/, true /*commit_if_ok*/,
     582              :                               true /*infer*/, true /*cleanup_on_fail*/,
     583              :                               false /*check_bounds*/);
     584         3213 :   if (res->get_kind () == TyTy::TypeKind::ERROR)
     585            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     586              : 
     587         3213 :   std::vector<TyTy::SubstitutionArg> resolved_args;
     588         5919 :   for (auto &p : impl_substitutions)
     589              :     {
     590         2706 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     591         2706 :       auto it = param_mappings.find (symbol);
     592         2706 :       if (it == param_mappings.end ())
     593            0 :         continue;
     594         2706 :       TyTy::BaseType *r = nullptr;
     595         2706 :       bool ok = context->lookup_type (it->second, &r);
     596         2706 :       if (!ok)
     597            0 :         continue;
     598         2706 :       resolved_args.emplace_back (&p, r);
     599         2706 :     }
     600              : 
     601         3213 :   return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
     602              :                                              {} /*binding_args*/,
     603         3213 :                                              TyTy::RegionParamList (0)
     604              :                                              /*regions*/,
     605         6426 :                                              locus);
     606         6433 : }
     607              : 
     608              : TyTy::SubstitutionArgumentMappings
     609         1966 : AssociatedImplTrait::bind_impl_for_bound (TyTy::BaseType *receiver,
     610              :                                           const TyTy::TypeBoundPredicate &bound,
     611              :                                           location_t locus)
     612              : {
     613              :   // Same shape as bind_impl_for_projection but the receiver/trait-args are
     614              :   // taken from the (binding, bound) pair instead of a ProjectionType.
     615         1966 :   std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
     616         2280 :   for (auto &generic_param : impl->get_generic_params ())
     617              :     {
     618          314 :       if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE)
     619           15 :         continue;
     620          299 :       TyTy::BaseType *l = nullptr;
     621          299 :       bool ok
     622          299 :         = context->lookup_type (generic_param->get_mappings ().get_hirid (),
     623              :                                 &l);
     624          299 :       if (!ok || l->get_kind () != TyTy::TypeKind::PARAM)
     625            0 :         continue;
     626          299 :       impl_substitutions.emplace_back (static_cast<HIR::TypeParam &> (
     627          299 :                                          *generic_param),
     628          299 :                                        static_cast<TyTy::ParamType *> (l));
     629              :     }
     630              : 
     631         1966 :   std::vector<TyTy::SubstitutionArg> infer_arg_vec;
     632         1966 :   std::map<std::string, HirId> param_mappings;
     633         2265 :   for (auto &p : impl_substitutions)
     634              :     {
     635          299 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     636          299 :       TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
     637          299 :       TyTy::BaseType *resolved = infer_var.get_tyty ();
     638          299 :       infer_arg_vec.emplace_back (&p, resolved);
     639          299 :       param_mappings[symbol] = resolved->get_ref ();
     640          299 :     }
     641         1966 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     642              :     std::move (infer_arg_vec), {} /*binding_args*/,
     643         1966 :     TyTy::RegionParamList (0) /*regions*/, locus);
     644              : 
     645         1966 :   TyTy::BaseType *impl_self_infer
     646         1966 :     = !self->is_concrete ()
     647         1966 :         ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
     648         1802 :         : self->clone ();
     649              : 
     650         1966 :   const TyTy::TypeBoundPredicate &impl_predicate = predicate;
     651         1966 :   std::vector<TyTy::BaseType *> impl_predicate_args;
     652         2848 :   for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
     653              :     {
     654          882 :       auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
     655          882 :       TyTy::BaseType *r = p->resolve ();
     656          882 :       if (!r->is_concrete ())
     657          235 :         r = SubstMapperInternal::Resolve (r, infer_arguments);
     658          882 :       impl_predicate_args.push_back (r);
     659              :     }
     660              : 
     661              :   // Trait args from the bound predicate the caller passed in (skip Self).
     662              :   // Apply the bound's own used_arguments so any stale impl-coord params
     663              :   // inside follow through to their current bindings.
     664         1966 :   TyTy::SubstitutionArgumentMappings bound_used
     665         1966 :     = bound.get_substitution_arguments ();
     666         1966 :   std::vector<TyTy::BaseType *> bound_args;
     667         2848 :   for (size_t i = 1; i < bound.get_substs ().size (); i++)
     668              :     {
     669          882 :       auto p = bound.get_substs ().at (i).get_param_ty ();
     670          882 :       TyTy::BaseType *r = p->resolve ();
     671          882 :       if (!r->is_concrete () && !bound_used.is_empty ())
     672            0 :         r = SubstMapperInternal::Resolve (r, bound_used);
     673          882 :       bound_args.push_back (r);
     674              :     }
     675              : 
     676         1966 :   if (impl_predicate_args.size () != bound_args.size ())
     677            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     678              : 
     679         2848 :   for (size_t i = 0; i < bound_args.size (); i++)
     680              :     {
     681         1764 :       auto *res = unify_site_and (0 /*id*/,
     682          882 :                                   TyTy::TyWithLocation (impl_predicate_args[i]),
     683          882 :                                   TyTy::TyWithLocation (bound_args[i]), locus,
     684              :                                   false /*emit_errors*/, true /*commit_if_ok*/,
     685              :                                   true /*infer*/, true /*cleanup_on_fail*/,
     686              :                                   false /*check_bounds*/);
     687          882 :       if (res->get_kind () == TyTy::TypeKind::ERROR)
     688            0 :         return TyTy::SubstitutionArgumentMappings::error ();
     689              :     }
     690              : 
     691         1966 :   auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
     692         1966 :                               TyTy::TyWithLocation (receiver),
     693         1966 :                               TyTy::TyWithLocation (impl_self_infer), locus,
     694              :                               false /*emit_errors*/, true /*commit_if_ok*/,
     695              :                               true /*infer*/, true /*cleanup_on_fail*/,
     696              :                               false /*check_bounds*/);
     697         1966 :   if (res->get_kind () == TyTy::TypeKind::ERROR)
     698            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     699              : 
     700         1966 :   std::vector<TyTy::SubstitutionArg> resolved_args;
     701         2265 :   for (auto &p : impl_substitutions)
     702              :     {
     703          299 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     704          299 :       auto it = param_mappings.find (symbol);
     705          299 :       if (it == param_mappings.end ())
     706            0 :         continue;
     707          299 :       TyTy::BaseType *r = nullptr;
     708          299 :       bool ok = context->lookup_type (it->second, &r);
     709          299 :       if (!ok)
     710            0 :         continue;
     711          299 :       resolved_args.emplace_back (&p, r);
     712          299 :     }
     713              : 
     714         1966 :   return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
     715              :                                              {} /*binding_args*/,
     716         1966 :                                              TyTy::RegionParamList (0)
     717              :                                              /*regions*/,
     718         3932 :                                              locus);
     719         3932 : }
     720              : 
     721              : location_t
     722            0 : AssociatedImplTrait::get_locus () const
     723              : {
     724            0 :   return impl->get_locus ();
     725              : }
     726              : 
     727              : Analysis::NodeMapping
     728            0 : TraitItemReference::get_parent_trait_mappings () const
     729              : {
     730            0 :   auto &mappings = Analysis::Mappings::get ();
     731              : 
     732            0 :   HIR::Trait *trait
     733            0 :     = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
     734            0 :   rust_assert (trait != nullptr);
     735              : 
     736            0 :   return trait->get_mappings ();
     737              : }
     738              : 
     739              : bool
     740         1833 : TraitItemReference::is_object_safe () const
     741              : {
     742              :   // https://doc.rust-lang.org/reference/items/traits.html#object-safety
     743         1833 :   switch (get_trait_item_type ())
     744              :     {
     745         1831 :     case TraitItemReference::TraitItemType::FN:
     746         1831 :       {
     747              :         // lets be boring and just check that this is indeed a method will do
     748              :         // for now
     749         1831 :         const HIR::TraitItem *item = get_hir_trait_item ();
     750         1831 :         const HIR::TraitItemFunc *fn
     751              :           = static_cast<const HIR::TraitItemFunc *> (item);
     752         1831 :         return fn->get_decl ().is_method ();
     753              :       }
     754              : 
     755              :       // constants are not available via dyn dispatch and so is not object safe
     756              :     case TraitItemReference::TraitItemType::CONST:
     757              :       return false;
     758              : 
     759              :       // types are object safe since they are not available via dyn dispatch
     760            0 :     case TraitItemReference::TraitItemType::TYPE:
     761            0 :       return true;
     762              : 
     763              :       // this is just an error so lets just fail it
     764              :     case TraitItemReference::TraitItemType::ERROR:
     765              :       return false;
     766              :     }
     767              :   return false;
     768              : }
     769              : 
     770              : } // namespace Resolver
     771              : } // 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.