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: 93.5 % 397 371
Test Date: 2025-06-21 16:26:05 Functions: 88.9 % 27 24
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (C) 2021-2025 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-type-check-expr.h"
      21                 :             : #include "rust-substitution-mapper.h"
      22                 :             : #include "rust-type-util.h"
      23                 :             : #include "rust-immutable-name-resolution-context.h"
      24                 :             : 
      25                 :             : // used for flag_name_resolution_2_0
      26                 :             : #include "options.h"
      27                 :             : 
      28                 :             : namespace Rust {
      29                 :             : namespace Resolver {
      30                 :             : 
      31                 :             : TraitItemReference
      32                 :        2494 : ResolveTraitItemToRef::Resolve (
      33                 :             :   HIR::TraitItem &item, TyTy::BaseType *self,
      34                 :             :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
      35                 :             : {
      36                 :        2494 :   ResolveTraitItemToRef resolver (self, std::move (substitutions));
      37                 :        2494 :   item.accept_vis (resolver);
      38                 :        2494 :   return std::move (resolver.resolved);
      39                 :        2494 : }
      40                 :             : 
      41                 :             : void
      42                 :         715 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
      43                 :             : {
      44                 :             :   // create trait-item-ref
      45                 :         715 :   location_t locus = type.get_locus ();
      46                 :         715 :   bool is_optional = false;
      47                 :        1430 :   std::string identifier = type.get_name ().as_string ();
      48                 :             : 
      49                 :         715 :   resolved = TraitItemReference (identifier, is_optional,
      50                 :             :                                  TraitItemReference::TraitItemType::TYPE, &type,
      51                 :        2145 :                                  self, substitutions, locus);
      52                 :         715 : }
      53                 :             : 
      54                 :             : void
      55                 :          48 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
      56                 :             : {
      57                 :             :   // create trait-item-ref
      58                 :          48 :   location_t locus = cst.get_locus ();
      59                 :          48 :   bool is_optional = cst.has_expr ();
      60                 :          96 :   std::string identifier = cst.get_name ().as_string ();
      61                 :             : 
      62                 :          48 :   resolved = TraitItemReference (identifier, is_optional,
      63                 :             :                                  TraitItemReference::TraitItemType::CONST, &cst,
      64                 :         144 :                                  self, substitutions, locus);
      65                 :          48 : }
      66                 :             : 
      67                 :             : void
      68                 :        1731 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
      69                 :             : {
      70                 :             :   // create trait-item-ref
      71                 :        1731 :   location_t locus = fn.get_locus ();
      72                 :        1731 :   bool is_optional = fn.has_definition ();
      73                 :        3462 :   std::string identifier = fn.get_decl ().get_function_name ().as_string ();
      74                 :             : 
      75                 :        1731 :   resolved = TraitItemReference (identifier, is_optional,
      76                 :             :                                  TraitItemReference::TraitItemType::FN, &fn,
      77                 :        5193 :                                  self, std::move (substitutions), locus);
      78                 :        1731 : }
      79                 :             : 
      80                 :        2494 : ResolveTraitItemToRef::ResolveTraitItemToRef (
      81                 :             :   TyTy::BaseType *self,
      82                 :        2494 :   std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
      83                 :        2494 :   : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
      84                 :        2494 :     substitutions (std::move (substitutions))
      85                 :        2494 : {}
      86                 :             : 
      87                 :             : // TraitItemReference items
      88                 :             : 
      89                 :             : TraitReference *
      90                 :      162535 : TraitResolver::Resolve (HIR::TypePath &path)
      91                 :             : {
      92                 :      162535 :   TraitResolver resolver;
      93                 :      162535 :   return resolver.resolve_path (path);
      94                 :      162535 : }
      95                 :             : 
      96                 :             : TraitReference *
      97                 :       35961 : TraitResolver::Resolve (HIR::Trait &trait)
      98                 :             : {
      99                 :       35961 :   TraitResolver resolver;
     100                 :       35961 :   return resolver.resolve_trait (&trait);
     101                 :       35961 : }
     102                 :             : 
     103                 :             : TraitReference *
     104                 :       16998 : TraitResolver::Lookup (HIR::TypePath &path)
     105                 :             : {
     106                 :       16998 :   TraitResolver resolver;
     107                 :       16998 :   return resolver.lookup_path (path);
     108                 :       16998 : }
     109                 :             : 
     110                 :             : HIR::Trait *
     111                 :      552090 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
     112                 :             : {
     113                 :      552090 :   TraitResolver resolver;
     114                 :             : 
     115                 :      552090 :   HIR::Trait *lookup = nullptr;
     116                 :      552090 :   bool ok = resolver.resolve_path_to_trait (path, &lookup);
     117                 :      552090 :   return ok ? lookup : nullptr;
     118                 :      552090 : }
     119                 :             : 
     120                 :      767584 : TraitResolver::TraitResolver () : TypeCheckBase () {}
     121                 :             : 
     122                 :             : bool
     123                 :      731623 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
     124                 :             :                                       HIR::Trait **resolved) const
     125                 :             : {
     126                 :      731623 :   NodeId ref;
     127                 :      731623 :   bool ok;
     128                 :      731623 :   if (flag_name_resolution_2_0)
     129                 :             :     {
     130                 :       98983 :       auto &nr_ctx
     131                 :       98983 :         = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     132                 :             : 
     133                 :       98983 :       auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ());
     134                 :             : 
     135                 :       98983 :       if ((ok = ref_opt.has_value ()))
     136                 :       98983 :         ref = *ref_opt;
     137                 :             :     }
     138                 :             :   else
     139                 :             :     {
     140                 :      632640 :       auto path_nodeid = path.get_mappings ().get_nodeid ();
     141                 :      632640 :       ok = resolver->lookup_resolved_type (path_nodeid, &ref)
     142                 :           2 :            || resolver->lookup_resolved_name (path_nodeid, &ref)
     143                 :      632640 :            || resolver->lookup_resolved_macro (path_nodeid, &ref);
     144                 :             :     }
     145                 :             : 
     146                 :       98983 :   if (!ok)
     147                 :             :     {
     148                 :           0 :       rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
     149                 :           0 :       return false;
     150                 :             :     }
     151                 :             : 
     152                 :      731623 :   auto hid = mappings.lookup_node_to_hir (ref);
     153                 :      731623 :   if (!hid)
     154                 :             :     {
     155                 :           0 :       rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
     156                 :           0 :       return false;
     157                 :             :     }
     158                 :             : 
     159                 :      731623 :   auto resolved_item = mappings.lookup_hir_item (hid.value ());
     160                 :      731623 :   if (!resolved_item.has_value ())
     161                 :             :     {
     162                 :           0 :       rust_error_at (path.get_locus (),
     163                 :             :                      "Failed to resolve trait by looking up hir node");
     164                 :           0 :       return false;
     165                 :             :     }
     166                 :             : 
     167                 :      731623 :   if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
     168                 :             :     {
     169                 :           4 :       rich_location r (line_table, path.get_locus ());
     170                 :           4 :       r.add_fixit_replace ("not a trait");
     171                 :           4 :       rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
     172                 :           8 :                      path.as_simple_path ().as_string ().c_str ());
     173                 :           4 :       return false;
     174                 :           4 :     }
     175                 :             : 
     176                 :      731619 :   *resolved = static_cast<HIR::Trait *> (*resolved_item);
     177                 :      731619 :   return true;
     178                 :             : }
     179                 :             : 
     180                 :             : TraitReference *
     181                 :      162535 : TraitResolver::resolve_path (HIR::TypePath &path)
     182                 :             : {
     183                 :      162535 :   HIR::Trait *resolved_trait_reference;
     184                 :      162535 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     185                 :      162535 :   if (!ok)
     186                 :           4 :     return &TraitReference::error_node ();
     187                 :             : 
     188                 :      162531 :   return resolve_trait (resolved_trait_reference);
     189                 :             : }
     190                 :             : 
     191                 :             : TraitReference *
     192                 :      198492 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
     193                 :             : {
     194                 :      198492 :   TraitReference *tref = &TraitReference::error_node ();
     195                 :      198492 :   if (context->lookup_trait_reference (
     196                 :      198492 :         trait_reference->get_mappings ().get_defid (), &tref))
     197                 :             :     {
     198                 :      195329 :       return tref;
     199                 :             :     }
     200                 :             : 
     201                 :        3163 :   DefId trait_id = trait_reference->get_mappings ().get_defid ();
     202                 :        3163 :   if (context->trait_query_in_progress (trait_id))
     203                 :             :     {
     204                 :           8 :       rust_error_at (
     205                 :             :         trait_reference->get_locus (), ErrorCode::E0391,
     206                 :             :         "cycle detected when computing the super predicates of %qs",
     207                 :           8 :         trait_reference->get_name ().as_string ().c_str ());
     208                 :           8 :       return &TraitReference::error_node ();
     209                 :             :     }
     210                 :             : 
     211                 :        3155 :   TraitQueryGuard guard (trait_id);
     212                 :        3155 :   TyTy::BaseType *self = nullptr;
     213                 :        3155 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     214                 :             : 
     215                 :             :   // this needs to be special cased for the sized trait to not auto implemented
     216                 :             :   // Sized on Self
     217                 :        6789 :   for (auto &generic_param : trait_reference->get_generic_params ())
     218                 :             :     {
     219                 :        3634 :       switch (generic_param.get ()->get_kind ())
     220                 :             :         {
     221                 :             :         case HIR::GenericParam::GenericKind::LIFETIME:
     222                 :             :         case HIR::GenericParam::GenericKind::CONST:
     223                 :             :           // FIXME: Skipping Lifetime and Const completely until better
     224                 :             :           // handling.
     225                 :             :           break;
     226                 :             : 
     227                 :        3624 :           case HIR::GenericParam::GenericKind::TYPE: {
     228                 :        3624 :             auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
     229                 :        3624 :             bool is_self
     230                 :        3624 :               = typaram.get_type_representation ().as_string ().compare ("Self")
     231                 :        3624 :                 == 0;
     232                 :             : 
     233                 :             :             // https://doc.rust-lang.org/std/marker/trait.Sized.html
     234                 :             :             // The one exception is the implicit Self type of a trait
     235                 :        3624 :             bool apply_sized = !is_self;
     236                 :        3624 :             auto param_type
     237                 :        3624 :               = TypeResolveGenericParam::Resolve (*generic_param, true,
     238                 :             :                                                   apply_sized);
     239                 :             : 
     240                 :        3624 :             context->insert_type (generic_param->get_mappings (), param_type);
     241                 :        7248 :             substitutions.push_back (
     242                 :        3624 :               TyTy::SubstitutionParamMapping (typaram, param_type));
     243                 :             : 
     244                 :        3624 :             if (is_self)
     245                 :             :               {
     246                 :        3155 :                 rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
     247                 :        3155 :                 TyTy::ParamType *p
     248                 :             :                   = static_cast<TyTy::ParamType *> (param_type);
     249                 :        3155 :                 p->set_implicit_self_trait ();
     250                 :        3155 :                 self = p;
     251                 :             :               }
     252                 :             :           }
     253                 :             :           break;
     254                 :             :         }
     255                 :             :     }
     256                 :        3155 :   rust_assert (self != nullptr);
     257                 :             : 
     258                 :             :   // Check if there is a super-trait, and apply this bound to the Self
     259                 :             :   // TypeParam
     260                 :        6310 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     261                 :             : 
     262                 :             :   // copy the substitition mappings
     263                 :        3155 :   std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
     264                 :        6779 :   for (auto &sub : substitutions)
     265                 :        3624 :     self_subst_copy.push_back (sub.clone ());
     266                 :             : 
     267                 :             :   // They also inherit themselves as a bound this enables a trait item to
     268                 :             :   // reference other Self::trait_items
     269                 :        3155 :   auto self_hrtb
     270                 :        3155 :     = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
     271                 :             :                                 std::move (self_subst_copy),
     272                 :             :                                 BoundPolarity::RegularBound,
     273                 :        6310 :                                 trait_reference->get_locus ());
     274                 :        3155 :   specified_bounds.push_back (self_hrtb);
     275                 :             : 
     276                 :             :   // look for any
     277                 :        6310 :   std::vector<TyTy::TypeBoundPredicate> super_traits;
     278                 :        3155 :   if (trait_reference->has_type_param_bounds ())
     279                 :             :     {
     280                 :         682 :       for (auto &bound : trait_reference->get_type_param_bounds ())
     281                 :             :         {
     282                 :         350 :           if (bound->get_bound_type ()
     283                 :             :               == HIR::TypeParamBound::BoundType::TRAITBOUND)
     284                 :             :             {
     285                 :         350 :               HIR::TraitBound *b
     286                 :         350 :                 = static_cast<HIR::TraitBound *> (bound.get ());
     287                 :             : 
     288                 :         350 :               auto predicate = get_predicate_from_bound (
     289                 :             :                 b->get_path (),
     290                 :         350 :                 tl::nullopt /*this will setup a PLACEHOLDER for self*/);
     291                 :         350 :               if (predicate.is_error ())
     292                 :          16 :                 return &TraitReference::error_node ();
     293                 :             : 
     294                 :         334 :               specified_bounds.push_back (predicate);
     295                 :         334 :               super_traits.push_back (predicate);
     296                 :         350 :             }
     297                 :             :         }
     298                 :             :     }
     299                 :        3139 :   self->inherit_bounds (specified_bounds);
     300                 :             : 
     301                 :        3139 :   context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
     302                 :        6278 :   std::vector<TraitItemReference> item_refs;
     303                 :        5633 :   for (auto &item : trait_reference->get_trait_items ())
     304                 :             :     {
     305                 :             :       // make a copy of the substs
     306                 :        2494 :       std::vector<TyTy::SubstitutionParamMapping> item_subst;
     307                 :        5862 :       for (auto &sub : substitutions)
     308                 :        3368 :         item_subst.push_back (sub.clone ());
     309                 :             : 
     310                 :        2494 :       TraitItemReference trait_item_ref
     311                 :        2494 :         = ResolveTraitItemToRef::Resolve (*item.get (), self,
     312                 :        2494 :                                           std::move (item_subst));
     313                 :        2494 :       item_refs.push_back (std::move (trait_item_ref));
     314                 :        2494 :     }
     315                 :             : 
     316                 :        3139 :   TraitReference trait_object (trait_reference, item_refs, super_traits,
     317                 :        3139 :                                std::move (substitutions));
     318                 :        3139 :   context->insert_trait_reference (
     319                 :        3139 :     trait_reference->get_mappings ().get_defid (), std::move (trait_object));
     320                 :             : 
     321                 :        3139 :   tref = &TraitReference::error_node ();
     322                 :        3139 :   bool ok = context->lookup_trait_reference (
     323                 :        3139 :     trait_reference->get_mappings ().get_defid (), &tref);
     324                 :        3139 :   rust_assert (ok);
     325                 :             : 
     326                 :             :   // hook to allow the trait to resolve its optional item blocks, we cant
     327                 :             :   // resolve the blocks of functions etc because it can end up in a recursive
     328                 :             :   // loop of trying to resolve traits as required by the types
     329                 :        3139 :   tref->on_resolved ();
     330                 :        3139 :   context->block_context ().exit ();
     331                 :             : 
     332                 :        3139 :   return tref;
     333                 :        3155 : }
     334                 :             : 
     335                 :             : TraitReference *
     336                 :       16998 : TraitResolver::lookup_path (HIR::TypePath &path)
     337                 :             : {
     338                 :       16998 :   HIR::Trait *resolved_trait_reference;
     339                 :       16998 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     340                 :       16998 :   if (!ok)
     341                 :           0 :     return &TraitReference::error_node ();
     342                 :             : 
     343                 :       16998 :   TraitReference *tref = &TraitReference::error_node ();
     344                 :       16998 :   if (context->lookup_trait_reference (
     345                 :       16998 :         resolved_trait_reference->get_mappings ().get_defid (), &tref))
     346                 :             :     {
     347                 :       16998 :       return tref;
     348                 :             :     }
     349                 :           0 :   return &TraitReference::error_node ();
     350                 :             : }
     351                 :             : 
     352                 :             : void
     353                 :        2494 : TraitItemReference::on_resolved ()
     354                 :             : {
     355                 :        2494 :   switch (type)
     356                 :             :     {
     357                 :          48 :     case CONST:
     358                 :          48 :       resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
     359                 :          48 :       break;
     360                 :             : 
     361                 :         715 :     case TYPE:
     362                 :         715 :       resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
     363                 :         715 :       break;
     364                 :             : 
     365                 :        1731 :     case FN:
     366                 :        1731 :       resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
     367                 :        1731 :       break;
     368                 :             : 
     369                 :             :     default:
     370                 :             :       break;
     371                 :             :     }
     372                 :        2494 : }
     373                 :             : 
     374                 :             : void
     375                 :         715 : TraitItemReference::resolve_item (HIR::TraitItemType &type)
     376                 :             : {
     377                 :         715 :   TyTy::BaseType *ty
     378                 :         715 :     = new TyTy::PlaceholderType (type.get_name ().as_string (),
     379                 :         715 :                                  type.get_mappings ().get_defid (),
     380                 :        1430 :                                  type.get_mappings ().get_hirid ());
     381                 :         715 :   context->insert_type (type.get_mappings (), ty);
     382                 :         715 : }
     383                 :             : 
     384                 :             : void
     385                 :          48 : TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
     386                 :             : {
     387                 :          48 :   TyTy::BaseType *ty = nullptr;
     388                 :          48 :   if (constant.has_type ())
     389                 :          13 :     ty = TypeCheckType::Resolve (constant.get_type ());
     390                 :             : 
     391                 :          48 :   TyTy::BaseType *expr = nullptr;
     392                 :          48 :   if (constant.has_expr ())
     393                 :          13 :     expr = TypeCheckExpr::Resolve (constant.get_expr ());
     394                 :             : 
     395                 :          61 :   bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
     396                 :          61 :   bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
     397                 :             : 
     398                 :          11 :   if (have_specified_ty && have_expr_ty)
     399                 :             :     {
     400                 :          22 :       coercion_site (constant.get_mappings ().get_hirid (),
     401                 :             :                      TyTy::TyWithLocation (ty,
     402                 :          11 :                                            constant.get_type ().get_locus ()),
     403                 :             :                      TyTy::TyWithLocation (expr,
     404                 :          11 :                                            constant.get_expr ().get_locus ()),
     405                 :             :                      constant.get_locus ());
     406                 :             :     }
     407                 :          48 : }
     408                 :             : 
     409                 :             : void
     410                 :        1731 : TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
     411                 :             : {
     412                 :        1731 :   TyTy::BaseType *item_tyty = get_tyty ();
     413                 :        1731 :   if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
     414                 :             :     return;
     415                 :             : 
     416                 :        1727 :   if (!is_optional ())
     417                 :             :     return;
     418                 :             : 
     419                 :             :   // check the block and return types
     420                 :         251 :   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
     421                 :             : 
     422                 :             :   // need to get the return type from this
     423                 :         251 :   TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
     424                 :         251 :   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
     425                 :         251 :   context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
     426                 :             : 
     427                 :         251 :   auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
     428                 :             : 
     429                 :         251 :   location_t fn_return_locus
     430                 :         251 :     = func.get_decl ().has_return_type ()
     431                 :         251 :         ? func.get_decl ().get_return_type ().get_locus ()
     432                 :         133 :         : func.get_locus ();
     433                 :             : 
     434                 :         502 :   coercion_site (func.get_mappings ().get_hirid (),
     435                 :         251 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     436                 :         251 :                  TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
     437                 :             : 
     438                 :         251 :   context->pop_return_type ();
     439                 :             : }
     440                 :             : 
     441                 :             : void
     442                 :        3028 : TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
     443                 :             : {
     444                 :        3028 :   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
     445                 :             : 
     446                 :        3028 :   TyTy::BaseType *item_ty = get_tyty ();
     447                 :        3028 :   rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
     448                 :        3028 :   TyTy::PlaceholderType *placeholder
     449                 :             :     = static_cast<TyTy::PlaceholderType *> (item_ty);
     450                 :             : 
     451                 :        3028 :   placeholder->set_associated_type (ty->get_ty_ref ());
     452                 :        3028 : }
     453                 :             : 
     454                 :             : void
     455                 :        1392 : TraitItemReference::associated_type_reset (bool only_projections) const
     456                 :             : {
     457                 :        1392 :   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
     458                 :             : 
     459                 :        1392 :   TyTy::BaseType *item_ty = get_tyty ();
     460                 :        1392 :   rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
     461                 :        1392 :   TyTy::PlaceholderType *placeholder
     462                 :             :     = static_cast<TyTy::PlaceholderType *> (item_ty);
     463                 :             : 
     464                 :        1392 :   if (!only_projections)
     465                 :             :     {
     466                 :        1204 :       placeholder->clear_associated_type ();
     467                 :             :     }
     468                 :             :   else
     469                 :             :     {
     470                 :         188 :       if (!placeholder->can_resolve ())
     471                 :             :         return;
     472                 :             : 
     473                 :          45 :       const TyTy::BaseType *r = placeholder->resolve ();
     474                 :          45 :       if (r->get_kind () == TyTy::TypeKind::PROJECTION)
     475                 :             :         {
     476                 :          14 :           placeholder->clear_associated_type ();
     477                 :             :         }
     478                 :             :     }
     479                 :             : }
     480                 :             : 
     481                 :             : void
     482                 :        3139 : AssociatedImplTrait::setup_raw_associated_types ()
     483                 :             : {
     484                 :        3139 :   auto &impl_items = impl->get_impl_items ();
     485                 :        8265 :   for (auto &impl_item : impl_items)
     486                 :             :     {
     487                 :        5126 :       bool is_type_alias = impl_item->get_impl_item_type ()
     488                 :        5126 :                            == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
     489                 :        5126 :       if (!is_type_alias)
     490                 :        4144 :         continue;
     491                 :             : 
     492                 :         982 :       HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
     493                 :             : 
     494                 :         982 :       TraitItemReference *resolved_trait_item = nullptr;
     495                 :         982 :       bool ok
     496                 :         982 :         = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
     497                 :             :                                     &resolved_trait_item);
     498                 :         982 :       if (!ok)
     499                 :           0 :         continue;
     500                 :         982 :       if (resolved_trait_item->get_trait_item_type ()
     501                 :             :           != TraitItemReference::TraitItemType::TYPE)
     502                 :           0 :         continue;
     503                 :             : 
     504                 :         982 :       TyTy::BaseType *lookup;
     505                 :         982 :       ok = context->lookup_type (type.get_mappings ().get_hirid (), &lookup);
     506                 :         982 :       rust_assert (ok);
     507                 :             : 
     508                 :         982 :       resolved_trait_item->associated_type_set (lookup);
     509                 :             :     }
     510                 :        3139 : }
     511                 :             : 
     512                 :             : TyTy::BaseType *
     513                 :        1459 : AssociatedImplTrait::setup_associated_types (
     514                 :             :   const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
     515                 :             :   TyTy::SubstitutionArgumentMappings *args, bool infer)
     516                 :             : {
     517                 :             :   // compute the constrained impl block generic arguments based on self and the
     518                 :             :   // higher ranked trait bound
     519                 :        1459 :   TyTy::BaseType *receiver = self->clone ();
     520                 :             : 
     521                 :             :   // impl<Y> SliceIndex<[Y]> for Range<usize>
     522                 :             :   // vs
     523                 :             :   // I: SliceIndex<[<integer>]> and Range<<integer>>
     524                 :             :   //
     525                 :             :   // we need to figure out what Y is
     526                 :             : 
     527                 :        1459 :   TyTy::BaseType *associated_self = get_self ();
     528                 :             : 
     529                 :        1459 :   rust_debug ("setup_associated_types for: %s->%s bound %s",
     530                 :             :               associated_self->debug_str ().c_str (),
     531                 :             :               self->debug_str ().c_str (), bound.as_string ().c_str ());
     532                 :             : 
     533                 :             :   // grab the parameters
     534                 :        1459 :   HIR::ImplBlock &impl_block = *get_impl_block ();
     535                 :        1459 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     536                 :        1875 :   for (auto &generic_param : impl_block.get_generic_params ())
     537                 :             :     {
     538                 :         416 :       switch (generic_param.get ()->get_kind ())
     539                 :             :         {
     540                 :             :         case HIR::GenericParam::GenericKind::LIFETIME:
     541                 :             :         case HIR::GenericParam::GenericKind::CONST:
     542                 :             :           // FIXME: Skipping Lifetime and Const completely until better
     543                 :             :           // handling.
     544                 :             :           break;
     545                 :             : 
     546                 :         402 :           case HIR::GenericParam::GenericKind::TYPE: {
     547                 :         402 :             TyTy::BaseType *l = nullptr;
     548                 :         402 :             bool ok = context->lookup_type (
     549                 :         402 :               generic_param->get_mappings ().get_hirid (), &l);
     550                 :         402 :             if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
     551                 :             :               {
     552                 :         402 :                 substitutions.push_back (TyTy::SubstitutionParamMapping (
     553                 :         402 :                   static_cast<HIR::TypeParam &> (*generic_param),
     554                 :         402 :                   static_cast<TyTy::ParamType *> (l)));
     555                 :             :               }
     556                 :             :           }
     557                 :         402 :           break;
     558                 :             :         }
     559                 :             :     }
     560                 :             : 
     561                 :             :   // this callback gives us the parameters that get substituted so we can
     562                 :             :   // compute the constrained type parameters for this impl block
     563                 :        2918 :   std::map<std::string, HirId> param_mappings;
     564                 :        1459 :   TyTy::ParamSubstCb param_subst_cb
     565                 :        1459 :     = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
     566                 :         598 :         param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
     567                 :        1459 :       };
     568                 :             : 
     569                 :             :   // generate inference variables for these bound arguments so we can compute
     570                 :             :   // their values
     571                 :        1459 :   location_t locus = UNKNOWN_LOCATION;
     572                 :        2918 :   std::vector<TyTy::SubstitutionArg> subst_args;
     573                 :        1861 :   for (auto &p : substitutions)
     574                 :             :     {
     575                 :         402 :       if (p.needs_substitution () && infer)
     576                 :             :         {
     577                 :         342 :           TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
     578                 :         684 :           subst_args.push_back (
     579                 :         342 :             TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
     580                 :             :         }
     581                 :             :       else
     582                 :             :         {
     583                 :          60 :           TyTy::ParamType *param = p.get_param_ty ();
     584                 :          60 :           TyTy::BaseType *resolved = param->destructure ();
     585                 :          60 :           subst_args.push_back (TyTy::SubstitutionArg (&p, resolved));
     586                 :          60 :           param_mappings[param->get_symbol ()] = resolved->get_ref ();
     587                 :             :         }
     588                 :             :     }
     589                 :             : 
     590                 :        1459 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     591                 :             :     std::move (subst_args), {},
     592                 :        2918 :     TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
     593                 :        4377 :     locus, param_subst_cb);
     594                 :        1459 :   TyTy::BaseType *impl_self_infer
     595                 :        1459 :     = (!associated_self->is_concrete ())
     596                 :        1459 :         ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
     597                 :             :         : associated_self;
     598                 :             : 
     599                 :        1459 :   const TyTy::TypeBoundPredicate &impl_predicate
     600                 :        1459 :     = associated_self->lookup_predicate (bound.get_id ());
     601                 :        1459 :   rust_assert (!impl_predicate.is_error ());
     602                 :             : 
     603                 :             :   // infer the arguments on the predicate
     604                 :        2918 :   std::vector<TyTy::BaseType *> impl_trait_predicate_args;
     605                 :             : 
     606                 :        3441 :   for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
     607                 :             :     {
     608                 :        1982 :       const auto &arg = impl_predicate.get_substs ().at (i);
     609                 :        1982 :       if (i == 0)
     610                 :        1459 :         continue;
     611                 :             : 
     612                 :         523 :       const TyTy::ParamType *p = arg.get_param_ty ();
     613                 :         523 :       TyTy::BaseType *r = p->resolve ();
     614                 :         523 :       if (!r->is_concrete ())
     615                 :             :         {
     616                 :         319 :           r = SubstMapperInternal::Resolve (r, infer_arguments);
     617                 :             :         }
     618                 :         523 :       impl_trait_predicate_args.push_back (r);
     619                 :             :     }
     620                 :             : 
     621                 :             :   // unify the bounds arguments
     622                 :        2918 :   std::vector<TyTy::BaseType *> hrtb_bound_arguments;
     623                 :        3441 :   for (size_t i = 0; i < bound.get_substs ().size (); i++)
     624                 :             :     {
     625                 :        1982 :       const auto &arg = bound.get_substs ().at (i);
     626                 :        1982 :       if (i == 0)
     627                 :        1459 :         continue;
     628                 :             : 
     629                 :         523 :       const TyTy::ParamType *p = arg.get_param_ty ();
     630                 :         523 :       TyTy::BaseType *r = p->resolve ();
     631                 :         523 :       if (!r->is_concrete ())
     632                 :             :         {
     633                 :           2 :           r = SubstMapperInternal::Resolve (r, infer_arguments);
     634                 :             :         }
     635                 :         523 :       hrtb_bound_arguments.push_back (r);
     636                 :             :     }
     637                 :             : 
     638                 :        1459 :   rust_assert (impl_trait_predicate_args.size ()
     639                 :             :                == hrtb_bound_arguments.size ());
     640                 :        1982 :   for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
     641                 :             :     {
     642                 :         523 :       TyTy::BaseType *a = impl_trait_predicate_args.at (i);
     643                 :         523 :       TyTy::BaseType *b = hrtb_bound_arguments.at (i);
     644                 :             : 
     645                 :         523 :       TyTy::BaseType *result
     646                 :         523 :         = unify_site_and (a->get_ref (), TyTy::TyWithLocation (a),
     647                 :         523 :                           TyTy::TyWithLocation (b), impl_predicate.get_locus (),
     648                 :             :                           true /*emit-errors*/, true /*commit-if-ok*/,
     649                 :             :                           true /*infer*/, true /*cleanup-on-fail*/);
     650                 :         523 :       rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
     651                 :             :     }
     652                 :             : 
     653                 :             :   // we need to unify the receiver with the impl-block Self so that we compute
     654                 :             :   // the type correctly as our receiver may be generic and we are inferring its
     655                 :             :   // generic arguments and this Self might be the concrete version or vice
     656                 :             :   // versa.
     657                 :        2918 :   auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
     658                 :        1459 :                                 TyTy::TyWithLocation (receiver),
     659                 :        1459 :                                 TyTy::TyWithLocation (impl_self_infer),
     660                 :             :                                 impl_predicate.get_locus (),
     661                 :             :                                 true /*emit-errors*/, true /*commit-if-ok*/,
     662                 :             :                                 true /*infer*/, true /*cleanup-on-fail*/);
     663                 :        1459 :   rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
     664                 :        1459 :   TyTy::BaseType *self_result = result;
     665                 :             : 
     666                 :             :   // create the argument list
     667                 :        2918 :   std::vector<TyTy::SubstitutionArg> associated_arguments;
     668                 :        1861 :   for (auto &p : substitutions)
     669                 :             :     {
     670                 :         402 :       std::string symbol = p.get_param_ty ()->get_symbol ();
     671                 :         402 :       auto it = param_mappings.find (symbol);
     672                 :         402 :       rust_assert (it != param_mappings.end ());
     673                 :             : 
     674                 :         402 :       HirId id = it->second;
     675                 :         402 :       TyTy::BaseType *argument = nullptr;
     676                 :         402 :       bool ok = context->lookup_type (id, &argument);
     677                 :         402 :       rust_assert (ok);
     678                 :             : 
     679                 :         402 :       TyTy::SubstitutionArg arg (&p, argument);
     680                 :         402 :       associated_arguments.push_back (arg);
     681                 :         402 :     }
     682                 :             : 
     683                 :        1459 :   TyTy::SubstitutionArgumentMappings associated_type_args (
     684                 :             :     std::move (associated_arguments), {},
     685                 :        1459 :     TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
     686                 :        2918 :     locus);
     687                 :             : 
     688                 :        1459 :   auto &impl_items = impl->get_impl_items ();
     689                 :        3445 :   for (auto &impl_item : impl_items)
     690                 :             :     {
     691                 :        1986 :       bool is_type_alias = impl_item->get_impl_item_type ()
     692                 :        1986 :                            == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
     693                 :        1986 :       if (!is_type_alias)
     694                 :        1295 :         continue;
     695                 :             : 
     696                 :         691 :       HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
     697                 :             : 
     698                 :         691 :       TraitItemReference *resolved_trait_item = nullptr;
     699                 :         691 :       bool ok
     700                 :         691 :         = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
     701                 :             :                                     &resolved_trait_item);
     702                 :         691 :       if (!ok)
     703                 :           0 :         continue;
     704                 :         691 :       if (resolved_trait_item->get_trait_item_type ()
     705                 :             :           != TraitItemReference::TraitItemType::TYPE)
     706                 :           0 :         continue;
     707                 :             : 
     708                 :         691 :       TyTy::BaseType *lookup;
     709                 :         691 :       if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
     710                 :           0 :         continue;
     711                 :             : 
     712                 :             :       // this might be generic
     713                 :         691 :       TyTy::BaseType *substituted
     714                 :         691 :         = SubstMapperInternal::Resolve (lookup, associated_type_args);
     715                 :         691 :       resolved_trait_item->associated_type_set (substituted);
     716                 :             :     }
     717                 :             : 
     718                 :        1459 :   if (args != nullptr)
     719                 :             :     {
     720                 :         140 :       *args = associated_type_args;
     721                 :             :     }
     722                 :             : 
     723                 :        1459 :   return self_result;
     724                 :        1459 : }
     725                 :             : 
     726                 :             : void
     727                 :           0 : AssociatedImplTrait::reset_associated_types ()
     728                 :             : {
     729                 :           0 :   trait->clear_associated_types ();
     730                 :           0 : }
     731                 :             : 
     732                 :             : location_t
     733                 :           0 : AssociatedImplTrait::get_locus () const
     734                 :             : {
     735                 :           0 :   return impl->get_locus ();
     736                 :             : }
     737                 :             : 
     738                 :             : Analysis::NodeMapping
     739                 :           0 : TraitItemReference::get_parent_trait_mappings () const
     740                 :             : {
     741                 :           0 :   auto &mappings = Analysis::Mappings::get ();
     742                 :             : 
     743                 :           0 :   HIR::Trait *trait
     744                 :           0 :     = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
     745                 :           0 :   rust_assert (trait != nullptr);
     746                 :             : 
     747                 :           0 :   return trait->get_mappings ();
     748                 :             : }
     749                 :             : 
     750                 :             : bool
     751                 :        1645 : TraitItemReference::is_object_safe () const
     752                 :             : {
     753                 :             :   // https://doc.rust-lang.org/reference/items/traits.html#object-safety
     754                 :        1645 :   switch (get_trait_item_type ())
     755                 :             :     {
     756                 :        1641 :       case TraitItemReference::TraitItemType::FN: {
     757                 :             :         // lets be boring and just check that this is indeed a method will do
     758                 :             :         // for now
     759                 :        1641 :         const HIR::TraitItem *item = get_hir_trait_item ();
     760                 :        1641 :         const HIR::TraitItemFunc *fn
     761                 :             :           = static_cast<const HIR::TraitItemFunc *> (item);
     762                 :        1641 :         return fn->get_decl ().is_method ();
     763                 :             :       }
     764                 :             : 
     765                 :             :       // constants are not available via dyn dispatch and so is not object safe
     766                 :             :     case TraitItemReference::TraitItemType::CONST:
     767                 :             :       return false;
     768                 :             : 
     769                 :             :       // types are object safe since they are not available via dyn dispatch
     770                 :           0 :     case TraitItemReference::TraitItemType::TYPE:
     771                 :           0 :       return true;
     772                 :             : 
     773                 :             :       // this is just an error so lets just fail it
     774                 :             :     case TraitItemReference::TraitItemType::ERROR:
     775                 :             :       return false;
     776                 :             :     }
     777                 :             :   return false;
     778                 :             : }
     779                 :             : 
     780                 :             : } // namespace Resolver
     781                 :             : } // namespace Rust
        

Generated by: LCOV version 2.1-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.