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: 94.2 % 514 484
Test Date: 2026-10-24 16:24:59 Functions: 92.0 % 25 23
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 "rich-location.h"
      21              : #include "rust-hir-trait-reference.h"
      22              : #include "rust-hir-type-check-expr.h"
      23              : #include "rust-rib.h"
      24              : #include "rust-substitution-mapper.h"
      25              : #include "text-range-label.h"
      26              : #include "rust-type-util.h"
      27              : #include "rust-finalized-name-resolution-context.h"
      28              : 
      29              : namespace Rust {
      30              : namespace Resolver {
      31              : 
      32              : static bool
      33         3693 : validate_impl_substitution_bounds (
      34              :   const std::vector<TyTy::SubstitutionArg> &resolved_args, location_t locus,
      35              :   bool emit_error)
      36              : {
      37         3693 :   auto &mctx = Analysis::Mappings::get ();
      38              : 
      39         3693 :   std::vector<TyTy::SubstitutionArg> args;
      40         4615 :   for (const auto &arg : resolved_args)
      41          922 :     args.push_back (arg);
      42              : 
      43         3693 :   TyTy::SubstitutionArgumentMappings mappings (std::move (args),
      44              :                                                {} /*binding_args*/,
      45         3693 :                                                TyTy::RegionParamList (0),
      46         3693 :                                                locus);
      47              : 
      48         4614 :   for (const auto &arg : resolved_args)
      49              :     {
      50          922 :       TyTy::BaseGeneric *param
      51          922 :         = const_cast<TyTy::BaseGeneric *> (arg.get_param_ty ());
      52          922 :       if (param == nullptr)
      53            0 :         continue;
      54              : 
      55          922 :       TyTy::BaseType *resolved_arg = arg.get_tyty ();
      56          922 :       if (resolved_arg->get_kind () == TyTy::TypeKind::PARAM)
      57           20 :         resolved_arg
      58           20 :           = static_cast<TyTy::ParamType *> (resolved_arg)->resolve ();
      59              : 
      60          922 :       if (resolved_arg->get_kind () == TyTy::TypeKind::PARAM
      61          922 :           || resolved_arg->get_kind () == TyTy::TypeKind::INFER)
      62          130 :         continue;
      63              : 
      64          792 :       auto arg_type_locus
      65          792 :         = mctx.lookup_location (arg.get_tyty ()->get_ty_ref ());
      66         1744 :       for (auto bound : param->get_specified_bounds ())
      67              :         {
      68          953 :           auto bound_locus = bound.get_locus ();
      69          953 :           auto trait_locus = bound.get ()->get_locus ();
      70          953 :           bound.apply_argument_mappings (mappings, false /*is_super_trait*/);
      71              : 
      72          953 :           if (!resolved_arg->satisfies_bound (bound, false /*emit_error*/))
      73              :             {
      74            1 :               if (emit_error)
      75              :                 {
      76            1 :                   rich_location r (line_table, locus);
      77              : 
      78            2 :                   std::string arg_label_text = "the trait " + bound.get_name ()
      79            2 :                                                + " is not implemented for "
      80            2 :                                                + resolved_arg->get_name ();
      81              : 
      82            1 :                   text_range_label arg_label (arg_label_text.c_str ());
      83            1 :                   r.add_range (arg_type_locus, SHOW_RANGE_WITHOUT_CARET,
      84              :                                &arg_label);
      85              : 
      86            1 :                   bool ambiguous = false;
      87            1 :                   auto *trait_impl
      88            1 :                     = lookup_associated_impl_block (bound, resolved_arg,
      89              :                                                     &ambiguous);
      90            1 :                   text_range_label trait_label (
      91            1 :                     "this trait has no implementations, consider adding one");
      92            1 :                   if (trait_impl == nullptr)
      93            1 :                     r.add_range (trait_locus, SHOW_RANGE_WITHOUT_CARET,
      94              :                                  &trait_label);
      95              : 
      96            1 :                   text_range_label bound_label (
      97            1 :                     "unsatisfied trait bound introduced here");
      98            1 :                   r.add_range (bound_locus, SHOW_RANGE_WITHOUT_CARET,
      99              :                                &bound_label);
     100              : 
     101            1 :                   rust_error_at (r, ErrorCode::E0277,
     102              :                                  "the trait bound %<%s: %s%> is not satisfied",
     103            2 :                                  resolved_arg->get_name ().c_str (),
     104            2 :                                  bound.get_name ().c_str ());
     105            1 :                 }
     106            1 :               return false;
     107              :             }
     108          953 :         }
     109              :     }
     110              : 
     111              :   return true;
     112         3693 : }
     113              : 
     114              : TraitItemReference
     115         3646 : ResolveTraitItemToRef::Resolve (
     116              :   HIR::TraitItem &item, TyTy::BaseType *self,
     117              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     118              : {
     119         3646 :   ResolveTraitItemToRef resolver (self, std::move (substitutions));
     120         3646 :   item.accept_vis (resolver);
     121         3646 :   return std::move (resolver.resolved);
     122         3646 : }
     123              : 
     124              : void
     125          835 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
     126              : {
     127              :   // create trait-item-ref
     128          835 :   location_t locus = type.get_locus ();
     129          835 :   bool is_optional = false;
     130         1670 :   std::string identifier = type.get_name ().as_string ();
     131              : 
     132          835 :   resolved = TraitItemReference (identifier, is_optional,
     133              :                                  TraitItemReference::TraitItemType::TYPE, &type,
     134         2505 :                                  self, substitutions, locus);
     135          835 : }
     136              : 
     137              : void
     138           40 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
     139              : {
     140              :   // create trait-item-ref
     141           40 :   location_t locus = cst.get_locus ();
     142           40 :   bool is_optional = cst.has_expr ();
     143           80 :   std::string identifier = cst.get_name ().as_string ();
     144              : 
     145           40 :   resolved = TraitItemReference (identifier, is_optional,
     146              :                                  TraitItemReference::TraitItemType::CONST, &cst,
     147          120 :                                  self, substitutions, locus);
     148           40 : }
     149              : 
     150              : void
     151         2771 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
     152              : {
     153              :   // create trait-item-ref
     154         2771 :   location_t locus = fn.get_locus ();
     155         2771 :   bool is_optional = fn.has_definition ();
     156         5542 :   std::string identifier = fn.get_decl ().get_function_name ().as_string ();
     157              : 
     158         2771 :   resolved = TraitItemReference (identifier, is_optional,
     159              :                                  TraitItemReference::TraitItemType::FN, &fn,
     160         8313 :                                  self, std::move (substitutions), locus);
     161         2771 : }
     162              : 
     163         3646 : ResolveTraitItemToRef::ResolveTraitItemToRef (
     164              :   TyTy::BaseType *self,
     165              :   std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
     166         3646 :   : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
     167         3646 :     substitutions (std::move (substitutions))
     168         3646 : {}
     169              : 
     170              : // TraitItemReference items
     171              : 
     172              : TraitReference *
     173        67368 : TraitResolver::Resolve (HIR::TypePath &path)
     174              : {
     175        67368 :   TraitResolver resolver;
     176        67368 :   return resolver.resolve_path (path);
     177        67368 : }
     178              : 
     179              : TraitReference *
     180        81457 : TraitResolver::Resolve (HIR::Trait &trait)
     181              : {
     182        81457 :   TraitResolver resolver;
     183        81457 :   return resolver.resolve_trait (&trait);
     184        81457 : }
     185              : 
     186              : TraitReference *
     187          360 : TraitResolver::Lookup (HIR::TypePath &path)
     188              : {
     189          360 :   TraitResolver resolver;
     190          360 :   return resolver.lookup_path (path);
     191          360 : }
     192              : 
     193              : HIR::Trait *
     194       277852 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
     195              : {
     196       277852 :   TraitResolver resolver;
     197              : 
     198       277852 :   HIR::Trait *lookup = nullptr;
     199       277852 :   bool ok = resolver.resolve_path_to_trait (path, &lookup);
     200       277852 :   return ok ? lookup : nullptr;
     201       277852 : }
     202              : 
     203       427037 : TraitResolver::TraitResolver () : TypeCheckBase () {}
     204              : 
     205              : bool
     206       345580 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
     207              :                                       HIR::Trait **resolved) const
     208              : {
     209       345580 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     210              : 
     211       345580 :   NodeId ref;
     212       345580 :   if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid (),
     213       345580 :                                     Resolver2_0::Namespace::Types))
     214              :     {
     215       345580 :       ref = *ref_opt;
     216              :     }
     217              :   else
     218              :     {
     219            0 :       rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
     220            0 :       return false;
     221              :     }
     222              : 
     223       345580 :   auto hid = mappings.lookup_node_to_hir (ref);
     224       345580 :   if (!hid)
     225              :     {
     226            0 :       rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
     227            0 :       return false;
     228              :     }
     229              : 
     230       345580 :   auto resolved_item = mappings.hir.items.lookup (hid.value ());
     231       345580 :   if (!resolved_item.has_value ())
     232              :     {
     233            0 :       rust_error_at (path.get_locus (),
     234              :                      "Failed to resolve trait by looking up hir node");
     235            0 :       return false;
     236              :     }
     237              : 
     238       345580 :   if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
     239              :     {
     240            3 :       rich_location r (line_table, path.get_locus ());
     241            3 :       r.add_fixit_replace ("not a trait");
     242            3 :       rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
     243            6 :                      path.as_simple_path ().as_string ().c_str ());
     244            3 :       return false;
     245            3 :     }
     246              : 
     247       345577 :   *resolved = static_cast<HIR::Trait *> (*resolved_item);
     248       345577 :   return true;
     249              : }
     250              : 
     251              : TraitReference *
     252        67368 : TraitResolver::resolve_path (HIR::TypePath &path)
     253              : {
     254        67368 :   HIR::Trait *resolved_trait_reference;
     255        67368 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     256        67368 :   if (!ok)
     257            3 :     return &TraitReference::error_node ();
     258              : 
     259        67365 :   return resolve_trait (resolved_trait_reference);
     260              : }
     261              : 
     262              : TraitReference *
     263       148822 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
     264              : {
     265       148822 :   TraitReference *tref = &TraitReference::error_node ();
     266       148822 :   if (context->lookup_trait_reference (
     267       148822 :         trait_reference->get_mappings ().get_defid (), &tref))
     268              :     {
     269       144561 :       return tref;
     270              :     }
     271              : 
     272         4261 :   DefId trait_id = trait_reference->get_mappings ().get_defid ();
     273         4261 :   if (context->trait_query_in_progress (trait_id))
     274              :     {
     275            4 :       rust_error_at (
     276              :         trait_reference->get_locus (), ErrorCode::E0391,
     277              :         "cycle detected when computing the super predicates of %qs",
     278            4 :         trait_reference->get_name ().as_string ().c_str ());
     279            4 :       return &TraitReference::error_node ();
     280              :     }
     281              : 
     282         4257 :   TraitQueryGuard guard (trait_id);
     283         4257 :   TyTy::BaseType *self = nullptr;
     284         4257 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     285              : 
     286         4257 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     287              : 
     288              :   // this needs to be special cased for the sized trait to not auto implemented
     289              :   // Sized on Self
     290         9252 :   for (auto &generic_param : trait_reference->get_generic_params ())
     291              :     {
     292         4995 :       switch (generic_param.get ()->get_kind ())
     293              :         {
     294            7 :         case HIR::GenericParam::GenericKind::LIFETIME:
     295            7 :           {
     296            7 :             auto &lifetime_param
     297            7 :               = static_cast<HIR::LifetimeParam &> (*generic_param);
     298           14 :             context->intern_and_insert_lifetime (
     299            7 :               lifetime_param.get_lifetime ());
     300              :           }
     301            7 :           break;
     302              : 
     303              :         case HIR::GenericParam::GenericKind::CONST:
     304              :           // FIXME: Skipping Lifetime and Const completely until better
     305              :           // handling.
     306              :           break;
     307              : 
     308         4986 :         case HIR::GenericParam::GenericKind::TYPE:
     309         4986 :           {
     310         4986 :             auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
     311         4986 :             bool is_self
     312         4986 :               = typaram.get_type_representation ().as_string ().compare ("Self")
     313         4986 :                 == 0;
     314              : 
     315              :             // https://doc.rust-lang.org/std/marker/trait.Sized.html
     316              :             // The one exception is the implicit Self type of a trait
     317         4986 :             bool apply_sized = !is_self;
     318         4986 :             auto param_type
     319         4986 :               = TypeResolveGenericParam::Resolve (*generic_param, true,
     320         4986 :                                                   apply_sized);
     321              : 
     322         4986 :             context->insert_type (generic_param->get_mappings (), param_type);
     323         4986 :             substitutions.emplace_back (typaram, param_type);
     324              : 
     325         4986 :             if (is_self)
     326              :               {
     327         4257 :                 rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
     328         4257 :                 TyTy::ParamType *p
     329              :                   = static_cast<TyTy::ParamType *> (param_type);
     330         4257 :                 p->set_implicit_self_trait ();
     331         4257 :                 self = p;
     332              :               }
     333              :           }
     334         4986 :           break;
     335              :         }
     336              :     }
     337         4257 :   rust_assert (self != nullptr);
     338              : 
     339              :   // Check if there is a super-trait, and apply this bound to the Self
     340              :   // TypeParam
     341         8514 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     342              : 
     343              :   // copy the substitition mappings
     344         4257 :   std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
     345         4257 :   self_subst_copy.reserve (substitutions.size ());
     346              : 
     347         9243 :   for (auto &sub : substitutions)
     348         4986 :     self_subst_copy.push_back (sub.clone ());
     349              : 
     350              :   // They also inherit themselves as a bound this enables a trait item to
     351              :   // reference other Self::trait_items
     352         4257 :   specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
     353              :                                  std::move (self_subst_copy),
     354         8514 :                                  BoundPolarity::RegularBound,
     355         4257 :                                  trait_reference->get_locus ());
     356              : 
     357              :   // look for any
     358         4257 :   std::vector<TyTy::TypeBoundPredicate> super_traits;
     359         4257 :   if (trait_reference->has_type_param_bounds ())
     360              :     {
     361         1234 :       for (auto &bound : trait_reference->get_type_param_bounds ())
     362              :         {
     363          663 :           if (bound->get_bound_type ()
     364              :               == HIR::TypeParamBound::BoundType::TRAITBOUND)
     365              :             {
     366          663 :               HIR::TraitBound *b
     367          663 :                 = static_cast<HIR::TraitBound *> (bound.get ());
     368              : 
     369          663 :               auto predicate = get_predicate_from_bound (
     370              :                 b->get_path (),
     371              :                 tl::nullopt /*this will setup a PLACEHOLDER for self*/,
     372          663 :                 BoundPolarity::RegularBound, false, true);
     373          663 :               if (predicate.is_error ())
     374           15 :                 return &TraitReference::error_node ();
     375              : 
     376          648 :               specified_bounds.push_back (predicate);
     377          648 :               super_traits.push_back (predicate);
     378          663 :             }
     379              :         }
     380              :     }
     381         4242 :   self->inherit_bounds (specified_bounds);
     382              : 
     383         4242 :   context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
     384         4242 :   std::vector<TraitItemReference> item_refs;
     385         7888 :   for (auto &item : trait_reference->get_trait_items ())
     386              :     {
     387              :       // make a copy of the substs
     388         3646 :       std::vector<TyTy::SubstitutionParamMapping> item_subst;
     389         3646 :       item_subst.reserve (substitutions.size ());
     390              : 
     391         8837 :       for (auto &sub : substitutions)
     392         5191 :         item_subst.push_back (sub.clone ());
     393              : 
     394         3646 :       TraitItemReference trait_item_ref
     395         3646 :         = ResolveTraitItemToRef::Resolve (*item.get (), self,
     396         3646 :                                           std::move (item_subst));
     397         3646 :       item_refs.push_back (std::move (trait_item_ref));
     398         3646 :     }
     399              : 
     400         4242 :   TraitReference trait_object (trait_reference, item_refs, super_traits,
     401         4242 :                                std::move (substitutions));
     402         4242 :   context->insert_trait_reference (
     403         4242 :     trait_reference->get_mappings ().get_defid (), std::move (trait_object));
     404              : 
     405         4242 :   tref = &TraitReference::error_node ();
     406         4242 :   bool ok = context->lookup_trait_reference (
     407         4242 :     trait_reference->get_mappings ().get_defid (), &tref);
     408         4242 :   rust_assert (ok);
     409              : 
     410              :   // hook to allow the trait to resolve its optional item blocks, we cant
     411              :   // resolve the blocks of functions etc because it can end up in a recursive
     412              :   // loop of trying to resolve traits as required by the types
     413         4242 :   tref->on_resolved ();
     414         4242 :   context->block_context ().exit ();
     415              : 
     416         4242 :   return tref;
     417         4257 : }
     418              : 
     419              : TraitReference *
     420          360 : TraitResolver::lookup_path (HIR::TypePath &path)
     421              : {
     422          360 :   HIR::Trait *resolved_trait_reference;
     423          360 :   bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
     424          360 :   if (!ok)
     425            0 :     return &TraitReference::error_node ();
     426              : 
     427          360 :   TraitReference *tref = &TraitReference::error_node ();
     428          360 :   if (context->lookup_trait_reference (
     429          360 :         resolved_trait_reference->get_mappings ().get_defid (), &tref))
     430              :     {
     431          360 :       return tref;
     432              :     }
     433            0 :   return &TraitReference::error_node ();
     434              : }
     435              : 
     436              : void
     437         3646 : TraitItemReference::on_resolved (const TraitReference *tref)
     438              : {
     439         3646 :   switch (type)
     440              :     {
     441           40 :     case CONST:
     442           40 :       resolve_item (tref, static_cast<HIR::TraitItemConst &> (*hir_trait_item));
     443           40 :       break;
     444              : 
     445          835 :     case TYPE:
     446          835 :       resolve_item (tref, static_cast<HIR::TraitItemType &> (*hir_trait_item));
     447          835 :       break;
     448              : 
     449         2771 :     case FN:
     450         2771 :       {
     451         2771 :         TyTy::BaseType *fn_type = get_tyty ();
     452         2771 :         if (is_optional () && fn_type->get_kind () == TyTy::TypeKind::FNDEF)
     453          869 :           context->mark_function_body_pending (
     454              :             static_cast<TyTy::FnType *> (fn_type)->get_id ());
     455              :       }
     456              :       break;
     457              : 
     458              :     default:
     459              :       break;
     460              :     }
     461         3646 : }
     462              : 
     463              : void
     464         3635 : TraitItemReference::resolve_default_function_body (const TraitReference *tref)
     465              : {
     466         3635 :   if (type != FN || !is_optional ())
     467              :     return;
     468              : 
     469          869 :   auto &func = static_cast<HIR::TraitItemFunc &> (*hir_trait_item);
     470          869 :   TyTy::BaseType *item_tyty = get_tyty ();
     471          869 :   if (item_tyty->get_kind () != TyTy::TypeKind::FNDEF)
     472              :     return;
     473              : 
     474          869 :   auto fn_type = static_cast<TyTy::FnType *> (item_tyty);
     475          869 :   if (!context->function_body_pending (fn_type->get_id ()))
     476              :     return;
     477              : 
     478          869 :   resolve_item (tref, func);
     479              : }
     480              : 
     481              : void
     482          835 : TraitItemReference::resolve_item (const TraitReference *tref,
     483              :                                   HIR::TraitItemType &type)
     484              : {
     485          835 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     486         2027 :   for (auto &param : tref->get_hir_trait_ref ()->get_generic_params ())
     487              :     {
     488         1192 :       if (param->get_kind () == HIR::GenericParam::GenericKind::LIFETIME)
     489              :         {
     490            1 :           auto &lifetime_param = static_cast<HIR::LifetimeParam &> (*param);
     491            1 :           context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
     492              :         }
     493              :     }
     494              : 
     495          835 :   auto substitutions = inherited_substitutions;
     496          835 :   tl::optional<TypeCheckContext::LifetimeResolverGuard> binder_pin;
     497          835 :   if (type.has_generics ())
     498              :     {
     499           17 :       binder_pin.emplace (*context,
     500           17 :                           TypeCheckContext::LifetimeResolverGuard::BINDER);
     501           17 :       TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::TypeAlias,
     502              :                                            type.get_locus (),
     503           17 :                                            type.get_generic_params (),
     504              :                                            substitutions, false, ABI::RUST);
     505              :     }
     506              : 
     507          835 :   size_t inherited_count = inherited_substitutions.size ();
     508          835 :   auto projection
     509          835 :     = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), nullptr,
     510          835 :                                 tref, type.get_mappings ().get_defid (),
     511              :                                 substitutions, self,
     512         1670 :                                 TyTy::SubstitutionArgumentMappings::error (),
     513         1670 :                                 {}, {}, inherited_count);
     514              : 
     515          835 :   context->insert_type (type.get_mappings (), projection);
     516              : 
     517              :   // Attach the bounds declared on the associated type itself:
     518              :   //
     519              :   //     type IntoIter: Iterator<Item = Self::Item>
     520              :   //
     521              :   // so satisfies_bound finds them in specified_bounds
     522          835 :   if (type.has_type_param_bounds ())
     523              :     {
     524           51 :       std::vector<TyTy::TypeBoundPredicate> trait_item_bounds;
     525          102 :       for (auto &bound : type.get_type_param_bounds ())
     526              :         {
     527           51 :           if (bound->get_bound_type ()
     528              :               != HIR::TypeParamBound::BoundType::TRAITBOUND)
     529            1 :             continue;
     530           50 :           auto *b = static_cast<HIR::TraitBound *> (bound.get ());
     531           50 :           auto predicate = TypeCheckBase::ResolvePredicateFromBound (
     532              :             b->get_path (),
     533              :             tl::nullopt /*this will setup a PLACEHOLDER for self*/,
     534           50 :             BoundPolarity::RegularBound, false, true);
     535           50 :           if (!predicate.is_error ())
     536           50 :             trait_item_bounds.push_back (std::move (predicate));
     537           50 :         }
     538           51 :       if (!trait_item_bounds.empty ())
     539           50 :         projection->inherit_bounds (trait_item_bounds);
     540           51 :     }
     541          835 : }
     542              : 
     543              : void
     544           40 : TraitItemReference::resolve_item (const TraitReference *tref,
     545              :                                   HIR::TraitItemConst &constant)
     546              : {
     547           40 :   TyTy::BaseType *ty = nullptr;
     548           40 :   if (constant.has_type ())
     549           11 :     ty = TypeCheckType::Resolve (constant.get_type ());
     550              : 
     551           40 :   TyTy::BaseType *expr = nullptr;
     552           40 :   if (constant.has_expr ())
     553           11 :     expr = TypeCheckExpr::Resolve (constant.get_expr ());
     554              : 
     555           51 :   bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
     556           51 :   bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
     557              : 
     558           10 :   if (have_specified_ty && have_expr_ty)
     559              :     {
     560           20 :       coercion_site (constant.get_mappings ().get_hirid (),
     561              :                      TyTy::TyWithLocation (ty,
     562           10 :                                            constant.get_type ().get_locus ()),
     563              :                      TyTy::TyWithLocation (expr,
     564           10 :                                            constant.get_expr ().get_locus ()),
     565              :                      constant.get_locus ());
     566              :     }
     567           40 : }
     568              : 
     569              : void
     570          869 : TraitItemReference::resolve_item (const TraitReference *tref,
     571              :                                   HIR::TraitItemFunc &func)
     572              : {
     573          869 :   TyTy::BaseType *item_tyty = get_tyty ();
     574          869 :   if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
     575              :     return;
     576              : 
     577          869 :   if (!is_optional ())
     578              :     return;
     579              : 
     580              :   // check the block and return types
     581          869 :   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
     582              : 
     583              :   // need to get the return type from this
     584          869 :   TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
     585          869 :   context->clear_function_body_pending (resolved_fn_type->get_id ());
     586          869 :   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
     587          869 :   context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
     588              : 
     589          869 :   auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
     590              : 
     591          869 :   location_t fn_return_locus
     592          869 :     = func.get_decl ().has_return_type ()
     593          869 :         ? func.get_decl ().get_return_type ().get_locus ()
     594          203 :         : func.get_locus ();
     595              : 
     596         1738 :   coercion_site (func.get_mappings ().get_hirid (),
     597          869 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     598          869 :                  TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
     599              : 
     600          869 :   context->pop_return_type ();
     601              : }
     602              : 
     603              : TyTy::SubstitutionArgumentMappings
     604         1230 : AssociatedImplTrait::bind_impl_for_projection (TyTy::ProjectionType &proj,
     605              :                                                location_t locus)
     606              : {
     607         1230 :   std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
     608         2014 :   for (auto &generic_param : impl->get_generic_params ())
     609              :     {
     610          784 :       if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE
     611          784 :           && generic_param->get_kind ()
     612              :                != HIR::GenericParam::GenericKind::CONST)
     613            2 :         continue;
     614          782 :       TyTy::BaseType *l = nullptr;
     615          782 :       bool ok
     616          782 :         = context->lookup_type (generic_param->get_mappings ().get_hirid (),
     617              :                                 &l);
     618          782 :       if (!ok)
     619            0 :         continue;
     620              : 
     621          782 :       TyTy::BaseGeneric *param = nullptr;
     622          782 :       if (l->get_kind () == TyTy::TypeKind::PARAM)
     623          548 :         param = static_cast<TyTy::ParamType *> (l);
     624          234 :       else if (l->get_kind () == TyTy::TypeKind::CONST
     625          234 :                && l->as_const_type ()->const_kind ()
     626              :                     == TyTy::BaseConstType::ConstKind::Decl)
     627            0 :         param = static_cast<TyTy::ConstParamType *> (l);
     628          782 :       if (param != nullptr)
     629          548 :         impl_substitutions.emplace_back (*generic_param, param);
     630              :     }
     631              : 
     632              :   // Build infer args for each impl param so we dont mutate the impls own
     633              :   // ParamTys when unifying. param_mappings records impl_param_symbol ->
     634              :   // hirid_of_fresh_infer_var so we can read out what each param resolved to
     635              :   // after unification.
     636         1230 :   std::vector<TyTy::SubstitutionArg> infer_arg_vec;
     637         1230 :   std::map<std::string, HirId> param_mappings;
     638         1778 :   for (auto &p : impl_substitutions)
     639              :     {
     640          548 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     641          548 :       TyTy::TyVar infer_var
     642          548 :         = p.get_generic_param ().get_kind ()
     643              :               == HIR::GenericParam::GenericKind::CONST
     644          548 :             ? TyTy::TyVar::get_implicit_const_infer_var (locus)
     645          548 :             : TyTy::TyVar::get_implicit_infer_var (locus);
     646          548 :       TyTy::BaseType *resolved = infer_var.get_tyty ();
     647          548 :       infer_arg_vec.emplace_back (&p, resolved);
     648          548 :       param_mappings[symbol] = resolved->get_ref ();
     649          548 :     }
     650         1230 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     651              :     std::move (infer_arg_vec), {} /*binding_args*/,
     652         1230 :     TyTy::RegionParamList (0) /*regions*/, locus);
     653              : 
     654         1230 :   TyTy::BaseType *impl_self_infer
     655         1230 :     = !self->is_concrete ()
     656         1230 :         ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
     657         1018 :         : self->clone ();
     658              : 
     659              :   // sub the impls trait predicate args with infers:
     660              :   //   SliceIndex<[Y]> -> SliceIndex<[?Y]>
     661         1230 :   const TyTy::TypeBoundPredicate &impl_predicate = predicate;
     662         1230 :   std::vector<TyTy::BaseType *> impl_predicate_args;
     663         1794 :   for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
     664              :     {
     665          564 :       auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
     666          564 :       TyTy::BaseType *r = p->resolve ();
     667          564 :       if (!r->is_concrete ())
     668          392 :         r = SubstMapperInternal::Resolve (r, infer_arguments);
     669          564 :       impl_predicate_args.push_back (r);
     670              :     }
     671              : 
     672              :   // Read the projections own (trait-coord) substs and skip Self at index 0.
     673              :   // The projection's substs match by symbol in handle_substitions, so a
     674              :   // fn-level substitution that binds T won't have walked into the
     675              :   // projections X slot whose resolved value is [T]. Re-apply the
     676              :   // projections own used_arguments to each arg so any stale impl-coord
     677              :   // params inside (the T inside [T]) are followed through to their
     678              :   // current bindings
     679         1230 :   TyTy::SubstitutionArgumentMappings proj_used
     680         1230 :     = proj.get_substitution_arguments ();
     681         1230 :   std::vector<TyTy::BaseType *> proj_args;
     682         1801 :   for (size_t i = 1; i < proj.get_substs ().size (); i++)
     683              :     {
     684          571 :       auto p = proj.get_substs ().at (i).get_param_ty ();
     685          571 :       TyTy::BaseType *r = p->resolve ();
     686          571 :       if (!r->is_concrete () && !proj_used.is_empty ())
     687           14 :         r = SubstMapperInternal::Resolve (r, proj_used);
     688          571 :       proj_args.push_back (r);
     689              :     }
     690              : 
     691         1230 :   if (impl_predicate_args.size () != proj_args.size ())
     692            7 :     return TyTy::SubstitutionArgumentMappings::error ();
     693              : 
     694              :   // unify trait args [?Y] -> [{integer}]
     695         1787 :   for (size_t i = 0; i < proj_args.size (); i++)
     696              :     {
     697          564 :       TyTy::BaseType *proj_arg = proj_args[i];
     698          564 :       if (impl_predicate_args[i]->get_kind () == TyTy::TypeKind::SLICE
     699          564 :           && proj_arg->get_kind () != TyTy::TypeKind::SLICE)
     700              :         {
     701          294 :           auto &mappings = Analysis::Mappings::get ();
     702          294 :           HirId id = mappings.get_next_hir_id ();
     703          294 :           auto *wrapped
     704              :             = new TyTy::SliceType (id, proj_arg->get_locus (),
     705          294 :                                    TyTy::TyVar (proj_arg->get_ref ()));
     706          294 :           context->insert_implicit_type (id, wrapped);
     707          294 :           proj_arg = wrapped;
     708              :         }
     709              : 
     710          564 :       auto *res = unify_site_and (0 /*id*/,
     711          564 :                                   TyTy::TyWithLocation (impl_predicate_args[i]),
     712          564 :                                   TyTy::TyWithLocation (proj_arg), locus,
     713              :                                   false /*emit_errors*/, true /*commit_if_ok*/,
     714              :                                   true /*infer*/, true /*cleanup_on_fail*/,
     715              :                                   false /*check_bounds*/);
     716          564 :       if (res->get_kind () == TyTy::TypeKind::ERROR)
     717            0 :         return TyTy::SubstitutionArgumentMappings::error ();
     718              :     }
     719              : 
     720              :   // unify self Range<{integer}> -> Range<usize>
     721         1223 :   auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
     722         1223 :                               TyTy::TyWithLocation (proj.get_self ()),
     723         1223 :                               TyTy::TyWithLocation (impl_self_infer), locus,
     724              :                               false /*emit_errors*/, true /*commit_if_ok*/,
     725              :                               true /*infer*/, true /*cleanup_on_fail*/,
     726              :                               false /*check_bounds*/);
     727         1223 :   if (res->get_kind () == TyTy::TypeKind::ERROR)
     728            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     729              : 
     730         1223 :   std::vector<TyTy::SubstitutionArg> resolved_args;
     731         1771 :   for (auto &p : impl_substitutions)
     732              :     {
     733          548 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     734          548 :       auto it = param_mappings.find (symbol);
     735          548 :       if (it == param_mappings.end ())
     736            0 :         continue;
     737          548 :       TyTy::BaseType *r = nullptr;
     738          548 :       bool ok = context->lookup_type (it->second, &r);
     739          548 :       if (!ok)
     740            0 :         continue;
     741          548 :       resolved_args.emplace_back (&p, r);
     742          548 :     }
     743              : 
     744         1223 :   if (!validate_impl_substitution_bounds (resolved_args, locus,
     745              :                                           false /*emit_error*/))
     746            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     747              : 
     748         1223 :   return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
     749              :                                              {} /*binding_args*/,
     750         1223 :                                              TyTy::RegionParamList (0)
     751              :                                              /*regions*/,
     752         2446 :                                              locus);
     753         2453 : }
     754              : 
     755              : TyTy::SubstitutionArgumentMappings
     756         2470 : AssociatedImplTrait::bind_impl_for_bound (TyTy::BaseType *receiver,
     757              :                                           const TyTy::TypeBoundPredicate &bound,
     758              :                                           location_t locus, bool emit_error)
     759              : {
     760              :   // Same shape as bind_impl_for_projection but the receiver/trait-args are
     761              :   // taken from the (binding, bound) pair instead of a ProjectionType.
     762         2470 :   std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
     763         2867 :   for (auto &generic_param : impl->get_generic_params ())
     764              :     {
     765          397 :       if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE
     766          397 :           && generic_param->get_kind ()
     767              :                != HIR::GenericParam::GenericKind::CONST)
     768           23 :         continue;
     769          374 :       TyTy::BaseType *l = nullptr;
     770          374 :       bool ok
     771          374 :         = context->lookup_type (generic_param->get_mappings ().get_hirid (),
     772              :                                 &l);
     773          374 :       if (!ok)
     774            0 :         continue;
     775              : 
     776          374 :       TyTy::BaseGeneric *param = nullptr;
     777          374 :       if (l->get_kind () == TyTy::TypeKind::PARAM)
     778          368 :         param = static_cast<TyTy::ParamType *> (l);
     779            6 :       else if (l->get_kind () == TyTy::TypeKind::CONST
     780            6 :                && l->as_const_type ()->const_kind ()
     781              :                     == TyTy::BaseConstType::ConstKind::Decl)
     782            6 :         param = static_cast<TyTy::ConstParamType *> (l);
     783          374 :       if (param != nullptr)
     784          374 :         impl_substitutions.emplace_back (*generic_param, param);
     785              :     }
     786              : 
     787         2470 :   std::vector<TyTy::SubstitutionArg> infer_arg_vec;
     788         2470 :   std::map<std::string, HirId> param_mappings;
     789         2844 :   for (auto &p : impl_substitutions)
     790              :     {
     791          374 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     792          374 :       TyTy::TyVar infer_var
     793          374 :         = p.get_generic_param ().get_kind ()
     794              :               == HIR::GenericParam::GenericKind::CONST
     795          374 :             ? TyTy::TyVar::get_implicit_const_infer_var (locus)
     796          368 :             : TyTy::TyVar::get_implicit_infer_var (locus);
     797          374 :       TyTy::BaseType *resolved = infer_var.get_tyty ();
     798          374 :       infer_arg_vec.emplace_back (&p, resolved);
     799          374 :       param_mappings[symbol] = resolved->get_ref ();
     800          374 :     }
     801         2470 :   TyTy::SubstitutionArgumentMappings infer_arguments (
     802              :     std::move (infer_arg_vec), {} /*binding_args*/,
     803         2470 :     TyTy::RegionParamList (0) /*regions*/, locus);
     804              : 
     805         2470 :   TyTy::BaseType *impl_self_infer
     806         2470 :     = !self->is_concrete ()
     807         2470 :         ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
     808         2252 :         : self->clone ();
     809              : 
     810         2470 :   const TyTy::TypeBoundPredicate &impl_predicate = predicate;
     811         2470 :   std::vector<TyTy::BaseType *> impl_predicate_args;
     812         3705 :   for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
     813              :     {
     814         1235 :       auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
     815         1235 :       TyTy::BaseType *r = p->resolve ();
     816         1235 :       if (!r->is_concrete ())
     817          278 :         r = SubstMapperInternal::Resolve (r, infer_arguments);
     818         1235 :       impl_predicate_args.push_back (r);
     819              :     }
     820              : 
     821              :   // Trait args from the bound predicate the caller passed in (skip Self).
     822              :   // Apply the bound's own used_arguments so any stale impl-coord params
     823              :   // inside follow through to their current bindings.
     824         2470 :   TyTy::SubstitutionArgumentMappings bound_used
     825         2470 :     = bound.get_substitution_arguments ();
     826         2470 :   std::vector<TyTy::BaseType *> bound_args;
     827         3705 :   for (size_t i = 1; i < bound.get_substs ().size (); i++)
     828              :     {
     829         1235 :       auto p = bound.get_substs ().at (i).get_param_ty ();
     830         1235 :       TyTy::BaseType *r = p->resolve ();
     831         1235 :       if (!r->is_concrete () && !bound_used.is_empty ())
     832            7 :         r = SubstMapperInternal::Resolve (r, bound_used);
     833         1235 :       bound_args.push_back (r);
     834              :     }
     835              : 
     836         2470 :   if (impl_predicate_args.size () != bound_args.size ())
     837            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     838              : 
     839         3705 :   for (size_t i = 0; i < bound_args.size (); i++)
     840              :     {
     841         2470 :       auto *res = unify_site_and (0 /*id*/,
     842         1235 :                                   TyTy::TyWithLocation (impl_predicate_args[i]),
     843         1235 :                                   TyTy::TyWithLocation (bound_args[i]), locus,
     844              :                                   false /*emit_errors*/, true /*commit_if_ok*/,
     845              :                                   true /*infer*/, true /*cleanup_on_fail*/,
     846              :                                   false /*check_bounds*/);
     847         1235 :       if (res->get_kind () == TyTy::TypeKind::ERROR)
     848            0 :         return TyTy::SubstitutionArgumentMappings::error ();
     849              :     }
     850              : 
     851         2470 :   auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
     852         2470 :                               TyTy::TyWithLocation (receiver),
     853         2470 :                               TyTy::TyWithLocation (impl_self_infer), locus,
     854              :                               false /*emit_errors*/, true /*commit_if_ok*/,
     855              :                               true /*infer*/, true /*cleanup_on_fail*/,
     856              :                               false /*check_bounds*/);
     857         2470 :   if (res->get_kind () == TyTy::TypeKind::ERROR)
     858            0 :     return TyTy::SubstitutionArgumentMappings::error ();
     859              : 
     860         2470 :   std::vector<TyTy::SubstitutionArg> resolved_args;
     861         2844 :   for (auto &p : impl_substitutions)
     862              :     {
     863          374 :       const std::string &symbol = p.get_param_ty ()->get_symbol ();
     864          374 :       auto it = param_mappings.find (symbol);
     865          374 :       if (it == param_mappings.end ())
     866            0 :         continue;
     867          374 :       TyTy::BaseType *r = nullptr;
     868          374 :       bool ok = context->lookup_type (it->second, &r);
     869          374 :       if (!ok)
     870            0 :         continue;
     871          374 :       resolved_args.emplace_back (&p, r);
     872          374 :     }
     873              : 
     874         2470 :   if (!validate_impl_substitution_bounds (resolved_args, locus, emit_error))
     875            1 :     return TyTy::SubstitutionArgumentMappings::error ();
     876              : 
     877         2469 :   return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
     878              :                                              {} /*binding_args*/,
     879         2469 :                                              TyTy::RegionParamList (0)
     880              :                                              /*regions*/,
     881         4938 :                                              locus);
     882         4940 : }
     883              : 
     884              : location_t
     885            0 : AssociatedImplTrait::get_locus () const
     886              : {
     887            0 :   return impl->get_locus ();
     888              : }
     889              : 
     890              : Analysis::NodeMapping
     891            0 : TraitItemReference::get_parent_trait_mappings () const
     892              : {
     893            0 :   auto &mappings = Analysis::Mappings::get ();
     894              : 
     895            0 :   HIR::Trait *trait
     896            0 :     = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
     897            0 :   rust_assert (trait != nullptr);
     898              : 
     899            0 :   return trait->get_mappings ();
     900              : }
     901              : 
     902              : bool
     903         1915 : TraitItemReference::is_object_safe () const
     904              : {
     905              :   // https://doc.rust-lang.org/reference/items/traits.html#object-safety
     906         1915 :   switch (get_trait_item_type ())
     907              :     {
     908         1898 :     case TraitItemReference::TraitItemType::FN:
     909         1898 :       {
     910              :         // lets be boring and just check that this is indeed a method will do
     911              :         // for now
     912         1898 :         const HIR::TraitItem *item = get_hir_trait_item ();
     913         1898 :         const HIR::TraitItemFunc *fn
     914              :           = static_cast<const HIR::TraitItemFunc *> (item);
     915         1898 :         return fn->get_decl ().is_method ();
     916              :       }
     917              : 
     918              :       // constants are not available via dyn dispatch and so is not object safe
     919              :     case TraitItemReference::TraitItemType::CONST:
     920              :       return false;
     921              : 
     922              :       // types are object safe since they are not available via dyn dispatch
     923           15 :     case TraitItemReference::TraitItemType::TYPE:
     924           15 :       return true;
     925              : 
     926              :       // this is just an error so lets just fail it
     927              :     case TraitItemReference::TraitItemType::ERROR:
     928              :       return false;
     929              :     }
     930              :   return false;
     931              : }
     932              : 
     933              : } // namespace Resolver
     934              : } // namespace Rust
        

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