LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-trait-resolve.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.0 % 350 322
Test Date: 2024-04-20 14:03:02 Functions: 92.0 % 25 23
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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