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