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 % 396 370
Test Date: 2026-02-28 14:20:25 Functions: 88.9 % 27 24
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2021-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-hir-trait-resolve.h"
      20              : #include "rust-hir-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         3310 : ResolveTraitItemToRef::Resolve (
      30              :   HIR::TraitItem &item, TyTy::BaseType *self,
      31              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
      32              : {
      33         3310 :   ResolveTraitItemToRef resolver (self, std::move (substitutions));
      34         3310 :   item.accept_vis (resolver);
      35         3310 :   return std::move (resolver.resolved);
      36         3310 : }
      37              : 
      38              : void
      39          736 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
      40              : {
      41              :   // create trait-item-ref
      42          736 :   location_t locus = type.get_locus ();
      43          736 :   bool is_optional = false;
      44         1472 :   std::string identifier = type.get_name ().as_string ();
      45              : 
      46          736 :   resolved = TraitItemReference (identifier, is_optional,
      47              :                                  TraitItemReference::TraitItemType::TYPE, &type,
      48         2208 :                                  self, substitutions, locus);
      49          736 : }
      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         2536 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
      66              : {
      67              :   // create trait-item-ref
      68         2536 :   location_t locus = fn.get_locus ();
      69         2536 :   bool is_optional = fn.has_definition ();
      70         5072 :   std::string identifier = fn.get_decl ().get_function_name ().as_string ();
      71              : 
      72         2536 :   resolved = TraitItemReference (identifier, is_optional,
      73              :                                  TraitItemReference::TraitItemType::FN, &fn,
      74         7608 :                                  self, std::move (substitutions), locus);
      75         2536 : }
      76              : 
      77         3310 : ResolveTraitItemToRef::ResolveTraitItemToRef (
      78              :   TyTy::BaseType *self,
      79         3310 :   std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
      80         3310 :   : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
      81         3310 :     substitutions (std::move (substitutions))
      82         3310 : {}
      83              : 
      84              : // TraitItemReference items
      85              : 
      86              : TraitReference *
      87       423288 : TraitResolver::Resolve (HIR::TypePath &path)
      88              : {
      89       423288 :   TraitResolver resolver;
      90       423288 :   return resolver.resolve_path (path);
      91       423288 : }
      92              : 
      93              : TraitReference *
      94        82438 : TraitResolver::Resolve (HIR::Trait &trait)
      95              : {
      96        82438 :   TraitResolver resolver;
      97        82438 :   return resolver.resolve_trait (&trait);
      98        82438 : }
      99              : 
     100              : TraitReference *
     101        21935 : TraitResolver::Lookup (HIR::TypePath &path)
     102              : {
     103        21935 :   TraitResolver resolver;
     104        21935 :   return resolver.lookup_path (path);
     105        21935 : }
     106              : 
     107              : HIR::Trait *
     108      1782618 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
     109              : {
     110      1782618 :   TraitResolver resolver;
     111              : 
     112      1782618 :   HIR::Trait *lookup = nullptr;
     113      1782618 :   bool ok = resolver.resolve_path_to_trait (path, &lookup);
     114      1782618 :   return ok ? lookup : nullptr;
     115      1782618 : }
     116              : 
     117      2310279 : TraitResolver::TraitResolver () : TypeCheckBase () {}
     118              : 
     119              : bool
     120      2227841 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
     121              :                                       HIR::Trait **resolved) const
     122              : {
     123      2227841 :   auto &nr_ctx
     124      2227841 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     125              : 
     126      2227841 :   NodeId ref;
     127      2227841 :   if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
     128              :     {
     129      2227841 :       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      2227841 :   auto hid = mappings.lookup_node_to_hir (ref);
     138      2227841 :   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      2227841 :   auto resolved_item = mappings.lookup_hir_item (hid.value ());
     145      2227841 :   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      2227841 :   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      2227839 :   *resolved = static_cast<HIR::Trait *> (*resolved_item);
     162      2227839 :   return true;
     163              : }
     164              : 
     165              : TraitReference *
     166       423288 : TraitResolver::resolve_path (HIR::TypePath &path)
     167              : {
     168       423288 :   HIR::Trait *resolved_trait_reference;
     169       423288 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     170       423288 :   if (!ok)
     171            2 :     return &TraitReference::error_node ();
     172              : 
     173       423286 :   return resolve_trait (resolved_trait_reference);
     174              : }
     175              : 
     176              : TraitReference *
     177       505724 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
     178              : {
     179       505724 :   TraitReference *tref = &TraitReference::error_node ();
     180       505724 :   if (context->lookup_trait_reference (
     181       505724 :         trait_reference->get_mappings ().get_defid (), &tref))
     182              :     {
     183       502032 :       return tref;
     184              :     }
     185              : 
     186         3692 :   DefId trait_id = trait_reference->get_mappings ().get_defid ();
     187         3692 :   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         3688 :   TraitQueryGuard guard (trait_id);
     197         3688 :   TyTy::BaseType *self = nullptr;
     198         3688 :   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         8026 :   for (auto &generic_param : trait_reference->get_generic_params ())
     203              :     {
     204         4338 :       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         4329 :         case HIR::GenericParam::GenericKind::TYPE:
     213         4329 :           {
     214         4329 :             auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
     215         4329 :             bool is_self
     216         4329 :               = typaram.get_type_representation ().as_string ().compare ("Self")
     217         4329 :                 == 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         4329 :             bool apply_sized = !is_self;
     222         4329 :             auto param_type
     223         4329 :               = TypeResolveGenericParam::Resolve (*generic_param, true,
     224         4329 :                                                   apply_sized);
     225              : 
     226         4329 :             context->insert_type (generic_param->get_mappings (), param_type);
     227         4329 :             substitutions.emplace_back (typaram, param_type);
     228              : 
     229         4329 :             if (is_self)
     230              :               {
     231         3688 :                 rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
     232         3688 :                 TyTy::ParamType *p
     233              :                   = static_cast<TyTy::ParamType *> (param_type);
     234         3688 :                 p->set_implicit_self_trait ();
     235         3688 :                 self = p;
     236              :               }
     237              :           }
     238         4329 :           break;
     239              :         }
     240              :     }
     241         3688 :   rust_assert (self != nullptr);
     242              : 
     243              :   // Check if there is a super-trait, and apply this bound to the Self
     244              :   // TypeParam
     245         7376 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     246              : 
     247              :   // copy the substitition mappings
     248         3688 :   std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
     249         3688 :   self_subst_copy.reserve (substitutions.size ());
     250              : 
     251         8017 :   for (auto &sub : substitutions)
     252         4329 :     self_subst_copy.push_back (sub.clone ());
     253              : 
     254              :   // They also inherit themselves as a bound this enables a trait item to
     255              :   // reference other Self::trait_items
     256         3688 :   specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
     257              :                                  std::move (self_subst_copy),
     258         7376 :                                  BoundPolarity::RegularBound,
     259         3688 :                                  trait_reference->get_locus ());
     260              : 
     261              :   // look for any
     262         7376 :   std::vector<TyTy::TypeBoundPredicate> super_traits;
     263         3688 :   if (trait_reference->has_type_param_bounds ())
     264              :     {
     265         1132 :       for (auto &bound : trait_reference->get_type_param_bounds ())
     266              :         {
     267          606 :           if (bound->get_bound_type ()
     268              :               == HIR::TypeParamBound::BoundType::TRAITBOUND)
     269              :             {
     270          606 :               HIR::TraitBound *b
     271          606 :                 = static_cast<HIR::TraitBound *> (bound.get ());
     272              : 
     273          606 :               auto predicate = get_predicate_from_bound (
     274              :                 b->get_path (),
     275              :                 tl::nullopt /*this will setup a PLACEHOLDER for self*/,
     276          606 :                 BoundPolarity::RegularBound, false, true);
     277          606 :               if (predicate.is_error ())
     278            8 :                 return &TraitReference::error_node ();
     279              : 
     280          598 :               specified_bounds.push_back (predicate);
     281          598 :               super_traits.push_back (predicate);
     282          606 :             }
     283              :         }
     284              :     }
     285         3680 :   self->inherit_bounds (specified_bounds);
     286              : 
     287         3680 :   context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
     288         7360 :   std::vector<TraitItemReference> item_refs;
     289         6990 :   for (auto &item : trait_reference->get_trait_items ())
     290              :     {
     291              :       // make a copy of the substs
     292         3310 :       std::vector<TyTy::SubstitutionParamMapping> item_subst;
     293         3310 :       item_subst.reserve (substitutions.size ());
     294              : 
     295         8045 :       for (auto &sub : substitutions)
     296         4735 :         item_subst.push_back (sub.clone ());
     297              : 
     298         3310 :       TraitItemReference trait_item_ref
     299         3310 :         = ResolveTraitItemToRef::Resolve (*item.get (), self,
     300         3310 :                                           std::move (item_subst));
     301         3310 :       item_refs.push_back (std::move (trait_item_ref));
     302         3310 :     }
     303              : 
     304         3680 :   TraitReference trait_object (trait_reference, item_refs, super_traits,
     305         3680 :                                std::move (substitutions));
     306         3680 :   context->insert_trait_reference (
     307         3680 :     trait_reference->get_mappings ().get_defid (), std::move (trait_object));
     308              : 
     309         3680 :   tref = &TraitReference::error_node ();
     310         3680 :   bool ok = context->lookup_trait_reference (
     311         3680 :     trait_reference->get_mappings ().get_defid (), &tref);
     312         3680 :   rust_assert (ok);
     313              : 
     314              :   // hook to allow the trait to resolve its optional item blocks, we cant
     315              :   // resolve the blocks of functions etc because it can end up in a recursive
     316              :   // loop of trying to resolve traits as required by the types
     317         3680 :   tref->on_resolved ();
     318         3680 :   context->block_context ().exit ();
     319              : 
     320         3680 :   return tref;
     321         3688 : }
     322              : 
     323              : TraitReference *
     324        21935 : TraitResolver::lookup_path (HIR::TypePath &path)
     325              : {
     326        21935 :   HIR::Trait *resolved_trait_reference;
     327        21935 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     328        21935 :   if (!ok)
     329            0 :     return &TraitReference::error_node ();
     330              : 
     331        21935 :   TraitReference *tref = &TraitReference::error_node ();
     332        21935 :   if (context->lookup_trait_reference (
     333        21935 :         resolved_trait_reference->get_mappings ().get_defid (), &tref))
     334              :     {
     335        21935 :       return tref;
     336              :     }
     337            0 :   return &TraitReference::error_node ();
     338              : }
     339              : 
     340              : void
     341         3310 : TraitItemReference::on_resolved ()
     342              : {
     343         3310 :   switch (type)
     344              :     {
     345           38 :     case CONST:
     346           38 :       resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
     347           38 :       break;
     348              : 
     349          736 :     case TYPE:
     350          736 :       resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
     351          736 :       break;
     352              : 
     353         2536 :     case FN:
     354         2536 :       resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
     355         2536 :       break;
     356              : 
     357              :     default:
     358              :       break;
     359              :     }
     360         3310 : }
     361              : 
     362              : void
     363          736 : TraitItemReference::resolve_item (HIR::TraitItemType &type)
     364              : {
     365          736 :   TyTy::BaseType *ty
     366          736 :     = new TyTy::PlaceholderType (type.get_name ().as_string (),
     367          736 :                                  type.get_mappings ().get_defid (),
     368         1472 :                                  type.get_mappings ().get_hirid ());
     369          736 :   context->insert_type (type.get_mappings (), ty);
     370          736 : }
     371              : 
     372              : void
     373           38 : TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
     374              : {
     375           38 :   TyTy::BaseType *ty = nullptr;
     376           38 :   if (constant.has_type ())
     377           11 :     ty = TypeCheckType::Resolve (constant.get_type ());
     378              : 
     379           38 :   TyTy::BaseType *expr = nullptr;
     380           38 :   if (constant.has_expr ())
     381           11 :     expr = TypeCheckExpr::Resolve (constant.get_expr ());
     382              : 
     383           49 :   bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
     384           49 :   bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
     385              : 
     386           10 :   if (have_specified_ty && have_expr_ty)
     387              :     {
     388           20 :       coercion_site (constant.get_mappings ().get_hirid (),
     389              :                      TyTy::TyWithLocation (ty,
     390           10 :                                            constant.get_type ().get_locus ()),
     391              :                      TyTy::TyWithLocation (expr,
     392           10 :                                            constant.get_expr ().get_locus ()),
     393              :                      constant.get_locus ());
     394              :     }
     395           38 : }
     396              : 
     397              : void
     398         2536 : TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
     399              : {
     400         2536 :   TyTy::BaseType *item_tyty = get_tyty ();
     401         2536 :   if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
     402              :     return;
     403              : 
     404         2534 :   if (!is_optional ())
     405              :     return;
     406              : 
     407              :   // check the block and return types
     408          855 :   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
     409              : 
     410              :   // need to get the return type from this
     411          855 :   TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
     412          855 :   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
     413          855 :   context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
     414              : 
     415          855 :   auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
     416              : 
     417          855 :   location_t fn_return_locus
     418          855 :     = func.get_decl ().has_return_type ()
     419          855 :         ? func.get_decl ().get_return_type ().get_locus ()
     420          191 :         : func.get_locus ();
     421              : 
     422         1710 :   coercion_site (func.get_mappings ().get_hirid (),
     423          855 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     424          855 :                  TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
     425              : 
     426          855 :   context->pop_return_type ();
     427              : }
     428              : 
     429              : void
     430         2959 : TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
     431              : {
     432         2959 :   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
     433              : 
     434              :   // this isnt super safe there are cases like the FnTraits where the type is
     435              :   // set to the impls placeholder associated type. For example
     436              :   //
     437              :   // type Output = F::Output; -- see the fn trait impls in libcore
     438              :   //
     439              :   // then this projection ends up resolving back to this placeholder so it just
     440              :   // ends up being cyclical
     441              : 
     442         2959 :   TyTy::BaseType *item_ty = get_tyty ();
     443         2959 :   rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
     444         2959 :   TyTy::PlaceholderType *placeholder
     445              :     = static_cast<TyTy::PlaceholderType *> (item_ty);
     446              : 
     447         2959 :   if (ty->is<TyTy::ProjectionType> ())
     448              :     {
     449         2771 :       const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
     450         2771 :       const auto resolved = projection.get ();
     451         2771 :       if (resolved == item_ty)
     452              :         return;
     453              :     }
     454              : 
     455         2959 :   placeholder->set_associated_type (ty->get_ty_ref ());
     456              : }
     457              : 
     458              : void
     459         1353 : TraitItemReference::associated_type_reset (bool only_projections) const
     460              : {
     461         1353 :   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
     462              : 
     463         1353 :   TyTy::BaseType *item_ty = get_tyty ();
     464         1353 :   rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
     465         1353 :   TyTy::PlaceholderType *placeholder
     466              :     = static_cast<TyTy::PlaceholderType *> (item_ty);
     467              : 
     468         1353 :   if (!only_projections)
     469              :     {
     470         1177 :       placeholder->clear_associated_type ();
     471              :     }
     472              :   else
     473              :     {
     474          176 :       if (!placeholder->can_resolve ())
     475              :         return;
     476              : 
     477           40 :       const TyTy::BaseType *r = placeholder->resolve ();
     478           40 :       if (r->get_kind () == TyTy::TypeKind::PROJECTION)
     479              :         {
     480           14 :           placeholder->clear_associated_type ();
     481              :         }
     482              :     }
     483              : }
     484              : 
     485              : void
     486         5534 : AssociatedImplTrait::setup_raw_associated_types ()
     487              : {
     488         5534 :   auto &impl_items = impl->get_impl_items ();
     489        17909 :   for (auto &impl_item : impl_items)
     490              :     {
     491        12375 :       bool is_type_alias = impl_item->get_impl_item_type ()
     492        12375 :                            == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
     493        12375 :       if (!is_type_alias)
     494        11416 :         continue;
     495              : 
     496          959 :       HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
     497              : 
     498          959 :       TraitItemReference *resolved_trait_item = nullptr;
     499          959 :       bool ok
     500          959 :         = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
     501              :                                     &resolved_trait_item);
     502          959 :       if (!ok)
     503            0 :         continue;
     504          959 :       if (resolved_trait_item->get_trait_item_type ()
     505              :           != TraitItemReference::TraitItemType::TYPE)
     506            0 :         continue;
     507              : 
     508          959 :       TyTy::BaseType *lookup;
     509          959 :       ok = context->lookup_type (type.get_mappings ().get_hirid (), &lookup);
     510          959 :       rust_assert (ok);
     511              : 
     512          959 :       resolved_trait_item->associated_type_set (lookup);
     513              :     }
     514         5534 : }
     515              : 
     516              : TyTy::BaseType *
     517         2242 : AssociatedImplTrait::setup_associated_types (
     518              :   const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
     519              :   TyTy::SubstitutionArgumentMappings *args, bool infer)
     520              : {
     521              :   // compute the constrained impl block generic arguments based on self and the
     522              :   // higher ranked trait bound
     523         2242 :   TyTy::BaseType *receiver = self->clone ();
     524              : 
     525              :   // impl<Y> SliceIndex<[Y]> for Range<usize>
     526              :   // vs
     527              :   // I: SliceIndex<[<integer>]> and Range<<integer>>
     528              :   //
     529              :   // we need to figure out what Y is
     530              : 
     531         2242 :   TyTy::BaseType *associated_self = get_self ();
     532              : 
     533         2242 :   rust_debug ("setup_associated_types for: %s->%s bound %s",
     534              :               associated_self->debug_str ().c_str (),
     535              :               self->debug_str ().c_str (), bound.as_string ().c_str ());
     536              : 
     537              :   // grab the parameters
     538         2242 :   HIR::ImplBlock &impl_block = *get_impl_block ();
     539         2242 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     540         2641 :   for (auto &generic_param : impl_block.get_generic_params ())
     541              :     {
     542          399 :       switch (generic_param.get ()->get_kind ())
     543              :         {
     544              :         case HIR::GenericParam::GenericKind::LIFETIME:
     545              :         case HIR::GenericParam::GenericKind::CONST:
     546              :           // FIXME: Skipping Lifetime and Const completely until better
     547              :           // handling.
     548              :           break;
     549              : 
     550          385 :         case HIR::GenericParam::GenericKind::TYPE:
     551          385 :           {
     552          385 :             TyTy::BaseType *l = nullptr;
     553          385 :             bool ok = context->lookup_type (
     554          385 :               generic_param->get_mappings ().get_hirid (), &l);
     555          385 :             if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
     556              :               {
     557          385 :                 substitutions.emplace_back (static_cast<HIR::TypeParam &> (
     558          385 :                                               *generic_param),
     559          385 :                                             static_cast<TyTy::ParamType *> (l));
     560              :               }
     561              :           }
     562          385 :           break;
     563              :         }
     564              :     }
     565              : 
     566              :   // this callback gives us the parameters that get substituted so we can
     567              :   // compute the constrained type parameters for this impl block
     568         4484 :   std::map<std::string, HirId> param_mappings;
     569         2242 :   TyTy::ParamSubstCb param_subst_cb
     570         2242 :     = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
     571          575 :         param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
     572         2242 :       };
     573              : 
     574              :   // generate inference variables for these bound arguments so we can compute
     575              :   // their values
     576         2242 :   location_t locus = UNKNOWN_LOCATION;
     577         4484 :   std::vector<TyTy::SubstitutionArg> subst_args;
     578         2627 :   for (auto &p : substitutions)
     579              :     {
     580          385 :       if (p.needs_substitution () && infer)
     581              :         {
     582          334 :           TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
     583          334 :           subst_args.emplace_back (&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.emplace_back (&p, resolved);
     590           51 :           param_mappings[param->get_symbol ()] = resolved->get_ref ();
     591              :         }
     592              :     }
     593              : 
     594         2242 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     595              :     std::move (subst_args), {},
     596         4484 :     TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
     597         6726 :     locus, param_subst_cb);
     598         2242 :   TyTy::BaseType *impl_self_infer
     599         2242 :     = (!associated_self->is_concrete ())
     600         2242 :         ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
     601              :         : associated_self;
     602              : 
     603         2242 :   const TyTy::TypeBoundPredicate &impl_predicate
     604         2242 :     = associated_self->lookup_predicate (bound.get_id ());
     605         2242 :   rust_assert (!impl_predicate.is_error ());
     606              : 
     607              :   // infer the arguments on the predicate
     608         4484 :   std::vector<TyTy::BaseType *> impl_trait_predicate_args;
     609              : 
     610         5467 :   for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
     611              :     {
     612         3225 :       const auto &arg = impl_predicate.get_substs ().at (i);
     613         3225 :       if (i == 0)
     614         2242 :         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         4484 :   std::vector<TyTy::BaseType *> hrtb_bound_arguments;
     627         5467 :   for (size_t i = 0; i < bound.get_substs ().size (); i++)
     628              :     {
     629         3225 :       const auto &arg = bound.get_substs ().at (i);
     630         3225 :       if (i == 0)
     631         2242 :         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         2242 :   rust_assert (impl_trait_predicate_args.size ()
     643              :                == hrtb_bound_arguments.size ());
     644         3225 :   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         4484 :   auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
     662         2242 :                                 TyTy::TyWithLocation (receiver),
     663         2242 :                                 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         2242 :   rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
     668         2242 :   TyTy::BaseType *self_result = result;
     669              : 
     670              :   // create the argument list
     671         4484 :   std::vector<TyTy::SubstitutionArg> associated_arguments;
     672         2627 :   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         2242 :   TyTy::SubstitutionArgumentMappings associated_type_args (
     688              :     std::move (associated_arguments), {},
     689         2242 :     TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
     690         4484 :     locus);
     691              : 
     692         2242 :   auto &impl_items = impl->get_impl_items ();
     693         5253 :   for (auto &impl_item : impl_items)
     694              :     {
     695         3011 :       bool is_type_alias = impl_item->get_impl_item_type ()
     696         3011 :                            == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
     697         3011 :       if (!is_type_alias)
     698         2374 :         continue;
     699              : 
     700          637 :       HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
     701              : 
     702          637 :       TraitItemReference *resolved_trait_item = nullptr;
     703          637 :       bool ok
     704          637 :         = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
     705              :                                     &resolved_trait_item);
     706          637 :       if (!ok)
     707            0 :         continue;
     708          637 :       if (resolved_trait_item->get_trait_item_type ()
     709              :           != TraitItemReference::TraitItemType::TYPE)
     710            0 :         continue;
     711              : 
     712          637 :       TyTy::BaseType *lookup;
     713          637 :       if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
     714            0 :         continue;
     715              : 
     716              :       // this might be generic
     717          637 :       TyTy::BaseType *substituted
     718          637 :         = SubstMapperInternal::Resolve (lookup, associated_type_args);
     719          637 :       resolved_trait_item->associated_type_set (substituted);
     720              :     }
     721              : 
     722         2242 :   if (args != nullptr)
     723              :     {
     724           92 :       *args = associated_type_args;
     725              :     }
     726              : 
     727         2242 :   return self_result;
     728         2242 : }
     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.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.