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