LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-bounds.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.9 % 506 475
Test Date: 2026-07-11 15:47:05 Functions: 91.2 % 57 52
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-full-decls.h"
      20              : #include "rust-hir-type-bounds.h"
      21              : #include "rust-hir-trait-resolve.h"
      22              : #include "rust-substitution-mapper.h"
      23              : #include "rust-hir-trait-resolve.h"
      24              : #include "rust-type-util.h"
      25              : 
      26              : namespace Rust {
      27              : namespace Resolver {
      28              : 
      29        80226 : TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
      30        80226 :   : TypeCheckBase (), receiver (receiver)
      31        80226 : {}
      32              : 
      33              : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
      34        80226 : TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
      35              : {
      36        80226 :   TypeBoundsProbe probe (receiver);
      37        80226 :   probe.scan ();
      38        80226 :   return probe.trait_references;
      39        80226 : }
      40              : 
      41              : bool
      42           82 : TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
      43              :                                               TraitReference *ref)
      44              : {
      45           82 :   for (auto &bound : receiver->get_specified_bounds ())
      46              :     {
      47            0 :       const TraitReference *b = bound.get ();
      48            0 :       if (b->is_equal (*ref))
      49           82 :         return true;
      50              :     }
      51              : 
      52           82 :   std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
      53           82 :     = Probe (receiver);
      54           93 :   for (auto &bound : bounds)
      55              :     {
      56           91 :       const TraitReference *b = bound.first;
      57           91 :       if (b->is_equal (*ref))
      58           82 :         return true;
      59              :     }
      60              : 
      61              :   return false;
      62           82 : }
      63              : 
      64              : bool
      65      2521501 : TypeBoundsProbe::process_impl_block (
      66              :   HirId id, HIR::ImplBlock *impl,
      67              :   std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
      68              :     &possible_trait_paths)
      69              : {
      70              :   // we are filtering for trait-impl-blocks
      71      2521501 :   if (!impl->has_trait_ref ())
      72              :     return true;
      73              : 
      74              :   // can be recursive trait resolution
      75      2234012 :   HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
      76      2234012 :   if (t == nullptr)
      77              :     return true;
      78              : 
      79      2234012 :   HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
      80      2234012 :   TyTy::BaseType *impl_type = nullptr;
      81      2234012 :   if (!query_type (impl_ty_id, &impl_type))
      82              :     return true;
      83              : 
      84      2230985 :   if (!types_compatable (TyTy::TyWithLocation (receiver),
      85      2230985 :                          TyTy::TyWithLocation (impl_type), impl->get_locus (),
      86              :                          false /*emit_errors*/, false /*check-bounds*/))
      87              :     return true;
      88              : 
      89       347909 :   possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
      90       347909 :   return true;
      91              : }
      92              : 
      93              : void
      94        80226 : TypeBoundsProbe::scan ()
      95              : {
      96        80226 :   std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
      97        80226 :     possible_trait_paths;
      98        80226 :   mappings.iterate_impl_blocks (
      99        80226 :     [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
     100      2521501 :       return process_impl_block (id, impl, possible_trait_paths);
     101              :     });
     102              : 
     103       428135 :   for (auto &path : possible_trait_paths)
     104              :     {
     105       347909 :       HIR::TypePath *trait_path = path.first;
     106       347909 :       TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
     107              : 
     108       347909 :       if (!trait_ref->is_error ())
     109       347906 :         trait_references.emplace_back (trait_ref, path.second);
     110              :     }
     111              : 
     112              :   // marker traits...
     113        80226 :   assemble_marker_builtins ();
     114              : 
     115              :   // add auto trait bounds
     116        80244 :   for (auto *auto_trait : mappings.get_auto_traits ())
     117           18 :     add_trait_bound (auto_trait);
     118        80226 : }
     119              : 
     120              : void
     121        80226 : TypeBoundsProbe::assemble_marker_builtins ()
     122              : {
     123        80226 :   const TyTy::BaseType *raw = receiver->destructure ();
     124              : 
     125              :   // https://runrust.miraheze.org/wiki/Dynamically_Sized_Type
     126              :   // everything is sized except for:
     127              :   //
     128              :   //   1. dyn traits
     129              :   //   2. slices
     130              :   //   3. str
     131              :   //   4. ADT's which contain any of the above
     132              :   //   t. tuples which contain any of the above
     133        80226 :   switch (raw->get_kind ())
     134              :     {
     135        59083 :     case TyTy::ARRAY:
     136        59083 :     case TyTy::REF:
     137        59083 :     case TyTy::POINTER:
     138        59083 :     case TyTy::PARAM:
     139        59083 :     case TyTy::FNDEF:
     140        59083 :     case TyTy::BOOL:
     141        59083 :     case TyTy::CHAR:
     142        59083 :     case TyTy::INT:
     143        59083 :     case TyTy::UINT:
     144        59083 :     case TyTy::FLOAT:
     145        59083 :     case TyTy::USIZE:
     146        59083 :     case TyTy::ISIZE:
     147        59083 :     case TyTy::INFER:
     148        59083 :     case TyTy::NEVER:
     149        59083 :     case TyTy::PLACEHOLDER:
     150        59083 :     case TyTy::PROJECTION:
     151        59083 :     case TyTy::OPAQUE:
     152        59083 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     153        59083 :       break;
     154              : 
     155          279 :     case TyTy::FNPTR:
     156          279 :     case TyTy::CLOSURE:
     157          279 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     158          279 :       assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
     159          279 :       assemble_builtin_candidate (LangItem::Kind::FN);
     160          279 :       assemble_builtin_candidate (LangItem::Kind::FN_MUT);
     161          279 :       break;
     162              : 
     163              :       // FIXME str and slice need to be moved and test cases updated
     164        20601 :     case TyTy::SLICE:
     165        20601 :     case TyTy::STR:
     166        20601 :     case TyTy::ADT:
     167        20601 :     case TyTy::TUPLE:
     168              :       // FIXME add extra checks
     169        20601 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     170        20601 :       break;
     171              : 
     172              :     case TyTy::CONST:
     173              :     case TyTy::DYNAMIC:
     174              :     case TyTy::ERROR:
     175              :       break;
     176              :     }
     177        80226 : }
     178              : 
     179              : void
     180        79982 : TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
     181              : {
     182        79982 :   auto trait_ref = TraitResolver::Resolve (*trait);
     183              : 
     184        79982 :   trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
     185        79982 : }
     186              : 
     187              : void
     188        80800 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
     189              : {
     190        80800 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item);
     191        80800 :   if (!lang_item_defined)
     192          836 :     return;
     193        79964 :   DefId &id = lang_item_defined.value ();
     194              : 
     195        79964 :   auto defid = mappings.lookup_defid (id);
     196        79964 :   if (!defid)
     197              :     return;
     198        79964 :   auto item = defid.value ();
     199              : 
     200        79964 :   rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
     201        79964 :   HIR::Trait *trait = static_cast<HIR::Trait *> (item);
     202        79964 :   const TyTy::BaseType *raw = receiver->destructure ();
     203              : 
     204        79964 :   add_trait_bound (trait);
     205              : 
     206        79964 :   rust_debug ("Added builtin lang_item: %s for %s",
     207              :               LangItem::ToString (lang_item).c_str (),
     208              :               raw->get_name ().c_str ());
     209              : }
     210              : 
     211              : TraitReference *
     212         6930 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
     213              : {
     214         6930 :   return TraitResolver::Resolve (path);
     215              : }
     216              : 
     217              : TyTy::TypeBoundPredicate
     218        43199 : TypeCheckBase::get_predicate_from_bound (
     219              :   HIR::TypePath &type_path,
     220              :   tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
     221              :   BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait)
     222              : {
     223        43199 :   TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
     224        43199 :   bool already_resolved
     225        43199 :     = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
     226              :                                  &lookup);
     227        43199 :   if (already_resolved)
     228        36269 :     return lookup;
     229              : 
     230         6930 :   TraitReference *trait = resolve_trait_path (type_path);
     231         6930 :   if (trait->is_error ())
     232            9 :     return TyTy::TypeBoundPredicate::error ();
     233              : 
     234         6921 :   TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
     235         6921 :   HIR::GenericArgs args
     236         6921 :     = HIR::GenericArgs::create_empty (type_path.get_locus ());
     237              : 
     238         6921 :   auto &final_seg = type_path.get_final_segment ();
     239         6921 :   switch (final_seg.get_type ())
     240              :     {
     241          879 :     case HIR::TypePathSegment::SegmentType::GENERIC:
     242          879 :       {
     243          879 :         auto &final_generic_seg
     244              :           = static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
     245          879 :         if (final_generic_seg.has_generic_args ())
     246              :           {
     247          879 :             args = final_generic_seg.get_generic_args ();
     248          879 :             if (args.get_binding_args ().size () > 0
     249          879 :                 && associated_self.has_value () && is_qualified_type_path)
     250              :               {
     251            1 :                 auto &binding_args = args.get_binding_args ();
     252              : 
     253            1 :                 rich_location r (line_table, args.get_locus ());
     254            2 :                 for (auto it = binding_args.begin (); it != binding_args.end ();
     255            1 :                      it++)
     256              :                   {
     257            1 :                     auto &arg = *it;
     258            1 :                     r.add_fixit_remove (arg.get_locus ());
     259              :                   }
     260            1 :                 rust_error_at (r, ErrorCode::E0229,
     261              :                                "associated type bindings are not allowed here");
     262            1 :               }
     263              :           }
     264              :       }
     265              :       break;
     266              : 
     267           27 :     case HIR::TypePathSegment::SegmentType::FUNCTION:
     268           27 :       {
     269           27 :         auto &final_function_seg
     270              :           = static_cast<HIR::TypePathSegmentFunction &> (final_seg);
     271           27 :         auto &fn = final_function_seg.get_function_path ();
     272              : 
     273              :         // we need to make implicit generic args which must be an implicit
     274              :         // Tuple
     275           27 :         auto crate_num = mappings.get_current_crate ();
     276           27 :         HirId implicit_args_id = mappings.get_next_hir_id ();
     277           27 :         Analysis::NodeMapping mapping (crate_num,
     278           27 :                                        final_seg.get_mappings ().get_nodeid (),
     279           27 :                                        implicit_args_id, UNKNOWN_LOCAL_DEFID);
     280              : 
     281           27 :         std::vector<std::unique_ptr<HIR::Type>> params_copy;
     282           56 :         for (auto &p : fn.get_params ())
     283              :           {
     284           29 :             params_copy.push_back (p->clone_type ());
     285              :           }
     286              : 
     287           27 :         std::vector<std::unique_ptr<HIR::Type>> inputs;
     288           27 :         inputs.push_back (
     289           27 :           std::make_unique<HIR::TupleType> (mapping, std::move (params_copy),
     290           27 :                                             final_seg.get_locus ()));
     291              : 
     292              :         // resolve the fn_once_output type which assumes there must be an output
     293              :         // set
     294           27 :         rust_assert (fn.has_return_type ());
     295           27 :         TypeCheckType::Resolve (fn.get_return_type ());
     296              : 
     297           27 :         HIR::TraitItem *trait_item
     298           27 :           = mappings
     299           27 :               .lookup_trait_item_lang_item (LangItem::Kind::FN_ONCE_OUTPUT,
     300              :                                             final_seg.get_locus ())
     301           27 :               .value ();
     302              : 
     303           27 :         std::vector<HIR::GenericArgsBinding> bindings;
     304           27 :         location_t output_locus = fn.get_return_type ().get_locus ();
     305           81 :         bindings.emplace_back (Identifier (trait_item->trait_identifier ()),
     306           54 :                                fn.get_return_type ().clone_type (),
     307              :                                output_locus);
     308              : 
     309           54 :         args = HIR::GenericArgs ({} /* lifetimes */,
     310              :                                  std::move (inputs) /* type_args*/,
     311              :                                  std::move (bindings) /* binding_args*/,
     312           54 :                                  {} /* const_args */, final_seg.get_locus ());
     313           27 :       }
     314           27 :       break;
     315              : 
     316              :     default:
     317              :       /* nothing to do */
     318              :       break;
     319              :     }
     320              : 
     321         6921 :   if (associated_self.has_value ())
     322              :     {
     323         6033 :       std::vector<std::unique_ptr<HIR::Type>> type_args;
     324         6033 :       type_args.push_back (std::unique_ptr<HIR::Type> (
     325         6033 :         associated_self.value ().get ().clone_type ()));
     326         6628 :       for (auto &arg : args.get_type_args ())
     327              :         {
     328          595 :           type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
     329              :         }
     330              : 
     331        18099 :       args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
     332         6033 :                                args.get_binding_args (), args.get_const_args (),
     333        12066 :                                args.get_locus ());
     334         6033 :     }
     335              : 
     336              :   // we try to apply generic arguments when they are non empty and or when the
     337              :   // predicate requires them so that we get the relevant Foo expects x number
     338              :   // arguments but got zero see test case rust/compile/traits12.rs
     339         6921 :   if (!args.is_empty () || predicate.requires_generic_args ())
     340              :     {
     341              :       // this is applying generic arguments to a trait reference
     342         6335 :       predicate.apply_generic_arguments (&args, associated_self.has_value (),
     343              :                                          is_super_trait);
     344              :     }
     345              : 
     346         6921 :   context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
     347              :                                       predicate);
     348              : 
     349         6921 :   return predicate;
     350        43199 : }
     351              : 
     352              : } // namespace Resolver
     353              : 
     354              : namespace TyTy {
     355              : 
     356        21160 : TypeBoundPredicate::TypeBoundPredicate (
     357              :   const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
     358        21160 :   location_t locus)
     359        42320 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     360        21160 :     reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
     361        21160 :     error_flag (false), polarity (polarity),
     362        63480 :     super_traits (trait_reference.get_super_traits ())
     363              : {
     364        21160 :   rust_assert (!trait_reference.get_trait_substs ().empty ());
     365              : 
     366        21160 :   substitutions.clear ();
     367        45224 :   for (const auto &p : trait_reference.get_trait_substs ())
     368        24064 :     substitutions.push_back (p.clone ());
     369              : 
     370              :   // we setup a dummy implict self argument
     371        21160 :   SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
     372        21160 :   used_arguments.get_mappings ().push_back (placeholder_self);
     373        21160 : }
     374              : 
     375         3942 : TypeBoundPredicate::TypeBoundPredicate (
     376              :   DefId reference, std::vector<SubstitutionParamMapping> subst,
     377         3942 :   BoundPolarity polarity, location_t locus)
     378         7884 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     379         3942 :     reference (reference), locus (locus), error_flag (false),
     380         7884 :     polarity (polarity)
     381              : {
     382         3942 :   rust_assert (!subst.empty ());
     383              : 
     384         3942 :   substitutions.clear ();
     385         8536 :   for (const auto &p : subst)
     386         4594 :     substitutions.push_back (p.clone ());
     387              : 
     388              :   // we setup a dummy implict self argument
     389         3942 :   SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
     390         3942 :   used_arguments.get_mappings ().push_back (placeholder_self);
     391         3942 : }
     392              : 
     393       119238 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
     394       238476 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     395       119238 :     reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
     396       119238 :     polarity (BoundPolarity::RegularBound)
     397       119238 : {}
     398              : 
     399     82571549 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
     400    165143098 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     401     82571549 :     reference (other.reference), locus (other.locus),
     402     82571549 :     error_flag (other.error_flag), polarity (other.polarity),
     403    165143098 :     super_traits (other.super_traits)
     404              : {
     405     82571549 :   substitutions.clear ();
     406    174746485 :   for (const auto &p : other.get_substs ())
     407     92174936 :     substitutions.push_back (p.clone ());
     408              : 
     409     82571549 :   std::vector<SubstitutionArg> mappings;
     410    166809250 :   for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
     411              :     {
     412     84237701 :       const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
     413     84237701 :       SubstitutionArg arg (oa);
     414     84237701 :       mappings.push_back (std::move (arg));
     415              :     }
     416              : 
     417              :   // we need to remap the argument mappings based on this copied constructor
     418     82571549 :   std::vector<SubstitutionArg> copied_arg_mappings;
     419     82571549 :   size_t i = 0;
     420    166809250 :   for (const auto &m : other.used_arguments.get_mappings ())
     421              :     {
     422     84237701 :       TyTy::BaseType *argument
     423     84237701 :         = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
     424     84237701 :       SubstitutionArg c (&substitutions.at (i++), argument);
     425     84237701 :       copied_arg_mappings.push_back (std::move (c));
     426              :     }
     427              : 
     428     82571549 :   used_arguments
     429     82571549 :     = SubstitutionArgumentMappings (copied_arg_mappings,
     430              :                                     other.used_arguments.get_binding_args (),
     431              :                                     other.used_arguments.get_regions (),
     432    165143098 :                                     other.used_arguments.get_locus ());
     433     82571549 : }
     434              : 
     435              : TypeBoundPredicate &
     436        90715 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
     437              : {
     438        90715 :   reference = other.reference;
     439        90715 :   locus = other.locus;
     440        90715 :   error_flag = other.error_flag;
     441        90715 :   polarity = other.polarity;
     442        90715 :   used_arguments = SubstitutionArgumentMappings::empty ();
     443              : 
     444        90715 :   substitutions.clear ();
     445       221975 :   for (const auto &p : other.get_substs ())
     446       131260 :     substitutions.push_back (p.clone ());
     447              : 
     448        90715 :   if (other.is_error ())
     449              :     return *this;
     450              : 
     451        80010 :   std::vector<SubstitutionArg> mappings;
     452       211241 :   for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
     453              :     {
     454       131231 :       const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
     455       131231 :       SubstitutionArg arg (oa);
     456       131231 :       mappings.push_back (std::move (arg));
     457              :     }
     458              : 
     459              :   // we need to remap the argument mappings based on this copied constructor
     460        80010 :   std::vector<SubstitutionArg> copied_arg_mappings;
     461        80010 :   size_t i = 0;
     462       211241 :   for (const auto &m : other.used_arguments.get_mappings ())
     463              :     {
     464       131231 :       TyTy::BaseType *argument
     465       131231 :         = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
     466              : 
     467       131231 :       copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
     468              :     }
     469              : 
     470        80010 :   used_arguments
     471        80010 :     = SubstitutionArgumentMappings (copied_arg_mappings,
     472              :                                     other.used_arguments.get_binding_args (),
     473              :                                     other.used_arguments.get_regions (),
     474       160020 :                                     other.used_arguments.get_locus ());
     475        80010 :   super_traits = other.super_traits;
     476              : 
     477        80010 :   return *this;
     478        80010 : }
     479              : 
     480              : TypeBoundPredicate
     481       119238 : TypeBoundPredicate::error ()
     482              : {
     483       119238 :   return TypeBoundPredicate (mark_is_error ());
     484              : }
     485              : 
     486              : std::string
     487         1184 : TypeBoundPredicate::as_string () const
     488              : {
     489         1184 :   return get ()->as_string () + subst_as_string ();
     490              : }
     491              : 
     492              : std::string
     493        53514 : TypeBoundPredicate::as_name () const
     494              : {
     495        53514 :   return get ()->get_name () + subst_as_string ();
     496              : }
     497              : 
     498              : const Resolver::TraitReference *
     499       422390 : TypeBoundPredicate::get () const
     500              : {
     501       422390 :   auto context = Resolver::TypeCheckContext::get ();
     502              : 
     503       422390 :   Resolver::TraitReference *ref = nullptr;
     504       422390 :   bool ok = context->lookup_trait_reference (reference, &ref);
     505       422390 :   rust_assert (ok);
     506              : 
     507       422390 :   return ref;
     508              : }
     509              : 
     510              : std::string
     511         8252 : TypeBoundPredicate::get_name () const
     512              : {
     513         8252 :   return get ()->get_name ();
     514              : }
     515              : 
     516              : bool
     517          249 : TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
     518              : {
     519          249 :   const Resolver::TraitReference *trait = get ();
     520          249 :   rust_assert (trait != nullptr);
     521          249 :   return trait->is_object_safe (emit_error, locus);
     522              : }
     523              : 
     524              : void
     525         6400 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
     526              :                                              bool has_associated_self,
     527              :                                              bool is_super_trait)
     528              : {
     529         6400 :   rust_assert (!substitutions.empty ());
     530         6400 :   if (has_associated_self)
     531              :     {
     532         6033 :       used_arguments = SubstitutionArgumentMappings::empty ();
     533              :     }
     534              :   else
     535              :     {
     536              :       // we need to get the substitutions argument mappings but also remember
     537              :       // that we have an implicit Self argument which we must be careful to
     538              :       // respect
     539          367 :       rust_assert (!used_arguments.is_empty ());
     540              :     }
     541              : 
     542              :   // now actually perform a substitution
     543         6400 :   auto args = get_mappings_from_generic_args (
     544              :     *generic_args,
     545         6400 :     Resolver::TypeCheckContext::get ()->regions_from_generic_args (
     546        12800 :       *generic_args));
     547              : 
     548         6400 :   apply_argument_mappings (args, is_super_trait);
     549         6400 : }
     550              : 
     551              : void
     552        10433 : TypeBoundPredicate::apply_argument_mappings (
     553              :   SubstitutionArgumentMappings &arguments, bool is_super_trait)
     554              : {
     555        10433 :   used_arguments = arguments;
     556        10433 :   error_flag |= used_arguments.is_error ();
     557        10433 :   auto &subst_mappings = used_arguments;
     558              : 
     559        10433 :   bool substs_need_bounds_check = !is_super_trait;
     560        23866 :   for (auto &sub : get_substs ())
     561              :     {
     562        13433 :       SubstitutionArg arg = SubstitutionArg::error ();
     563        13433 :       bool ok
     564        13433 :         = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
     565        13433 :       if (ok && arg.get_tyty () != nullptr)
     566        12983 :         sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
     567              :                            substs_need_bounds_check);
     568              :     }
     569              : 
     570              :   // Associated type binding args (Iterator<Item = i32>) are consumed
     571              :   // by BaseType::satisfies_bound at check time
     572        14458 :   for (auto &super_trait : super_traits)
     573              :     {
     574         4025 :       auto adjusted
     575              :         = super_trait.adjust_mappings_for_this (used_arguments,
     576         4025 :                                                 true /*trait mode*/);
     577         4025 :       super_trait.apply_argument_mappings (adjusted, is_super_trait);
     578         4025 :     }
     579        10433 : }
     580              : 
     581              : bool
     582            0 : TypeBoundPredicate::contains_item (const std::string &search) const
     583              : {
     584            0 :   auto trait_ref = get ();
     585            0 :   const Resolver::TraitItemReference *trait_item_ref = nullptr;
     586            0 :   return trait_ref->lookup_trait_item (search, &trait_item_ref);
     587              : }
     588              : 
     589              : tl::optional<TypeBoundPredicateItem>
     590        26406 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
     591              : {
     592        26406 :   auto trait_ref = get ();
     593        26406 :   const Resolver::TraitItemReference *trait_item_ref = nullptr;
     594        26406 :   if (trait_ref->lookup_trait_item (search, &trait_item_ref,
     595              :                                     false /*lookup supers*/))
     596        24941 :     return TypeBoundPredicateItem (*this, trait_item_ref);
     597              : 
     598         1581 :   for (auto &super_trait : super_traits)
     599              :     {
     600          238 :       auto lookup = super_trait.lookup_associated_item (search);
     601          238 :       if (lookup.has_value ())
     602          122 :         return lookup;
     603          238 :     }
     604              : 
     605         1343 :   return tl::nullopt;
     606              : }
     607              : 
     608        31158 : TypeBoundPredicateItem::TypeBoundPredicateItem (
     609              :   const TypeBoundPredicate parent,
     610        31158 :   const Resolver::TraitItemReference *trait_item_ref)
     611        31158 :   : parent (parent), trait_item_ref (trait_item_ref)
     612        31158 : {}
     613              : 
     614        33867 : TypeBoundPredicateItem::TypeBoundPredicateItem (
     615        33867 :   const TypeBoundPredicateItem &other)
     616        33867 :   : parent (other.parent), trait_item_ref (other.trait_item_ref)
     617        33867 : {}
     618              : 
     619              : TypeBoundPredicateItem &
     620         6139 : TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
     621              : {
     622         6139 :   parent = other.parent;
     623         6139 :   trait_item_ref = other.trait_item_ref;
     624              : 
     625         6139 :   return *this;
     626              : }
     627              : 
     628              : TypeBoundPredicateItem
     629         6144 : TypeBoundPredicateItem::error ()
     630              : {
     631         6144 :   return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
     632              : }
     633              : 
     634              : bool
     635         6241 : TypeBoundPredicateItem::is_error () const
     636              : {
     637         6241 :   return parent.is_error () || trait_item_ref == nullptr;
     638              : }
     639              : 
     640              : const TypeBoundPredicate *
     641         1312 : TypeBoundPredicateItem::get_parent () const
     642              : {
     643         1312 :   return &parent;
     644              : }
     645              : 
     646              : tl::optional<TypeBoundPredicateItem>
     647         6078 : TypeBoundPredicate::lookup_associated_item (
     648              :   const Resolver::TraitItemReference *ref) const
     649              : {
     650         6078 :   return lookup_associated_item (ref->get_identifier ());
     651              : }
     652              : 
     653              : BaseType *
     654         8295 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
     655              : {
     656         8295 :   auto ctx = Resolver::TypeCheckContext::get ();
     657              : 
     658         8295 :   TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
     659         8295 :   if (parent.get_substitution_arguments ().is_empty ())
     660              :     return trait_item_tyty;
     661              : 
     662              :   // set up the self mapping
     663         8295 :   SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
     664         8295 :   rust_assert (!gargs.is_empty ());
     665              : 
     666              :   // The associated-type projection we are rebasing is stored in trait
     667              :   // coordinates
     668              :   //
     669              :   //   Self/X for trait SliceIndex<X>
     670              :   //
     671              :   // The predicate's own  SubstitutionParamMappings may have already been
     672              :   // mutated by SubstitutionParamMapping::fill_param_ty when the bound is a
     673              :   // where-clause like I: SliceIndex<[T]>: substituting Self with the
     674              :   // ParamType I rebinds the predicate's first param from Self to I.
     675              :   // Building adjusted_mappings from those renamed mappings would make
     676              :   // name-based lookup (get_argument_for_symbol) miss the trait's Self/X
     677              :   // symbols inside the projection.
     678         8295 :   const auto &trait_substs = parent.get ()->get_trait_substs ();
     679         8295 :   rust_assert (gargs.get_mappings ().size () <= trait_substs.size ());
     680              : 
     681         8295 :   std::vector<SubstitutionArg> adjusted_mappings;
     682        20513 :   for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
     683              :     {
     684        12218 :       auto &mapping = gargs.get_mappings ().at (i);
     685              : 
     686        12218 :       bool is_implicit_self = i == 0;
     687        12218 :       TyTy::BaseType *argument
     688        12218 :         = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
     689              : 
     690        12218 :       adjusted_mappings.emplace_back (&trait_substs.at (i), argument);
     691              :     }
     692              : 
     693         8295 :   SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
     694              :                                          gargs.get_regions (),
     695              :                                          gargs.get_locus (),
     696         8295 :                                          gargs.get_subst_cb (),
     697         8295 :                                          true /* trait-mode-flag */);
     698         8295 :   TyTy::BaseType *res
     699         8295 :     = Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
     700              : 
     701         8295 :   if (res != trait_item_tyty)
     702              :     {
     703         8295 :       auto &mappings = Analysis::Mappings::get ();
     704         8295 :       HirId fresh = mappings.get_next_hir_id ();
     705         8295 :       res->set_ref (fresh);
     706         8295 :       res->set_ty_ref (fresh);
     707         8295 :       ctx->insert_implicit_type (fresh, res);
     708              :     }
     709              : 
     710         8295 :   return res;
     711         8295 : }
     712              : bool
     713       155300 : TypeBoundPredicate::is_error () const
     714              : {
     715       155300 :   auto context = Resolver::TypeCheckContext::get ();
     716              : 
     717       155300 :   Resolver::TraitReference *ref = nullptr;
     718       155300 :   bool ok = context->lookup_trait_reference (reference, &ref);
     719              : 
     720       155300 :   return !ok || error_flag;
     721              : }
     722              : 
     723              : BaseType *
     724        53287 : TypeBoundPredicate::handle_substitions (
     725              :   SubstitutionArgumentMappings &subst_mappings)
     726              : {
     727       117112 :   for (auto &sub : get_substs ())
     728              :     {
     729        63825 :       if (sub.get_param_ty () == nullptr)
     730            0 :         continue;
     731              : 
     732        63825 :       auto p = sub.get_param_ty ();
     733        63825 :       BaseType *r = p->resolve ();
     734        63825 :       BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
     735              : 
     736        63825 :       p->set_ty_ref (s->get_ty_ref ());
     737              :     }
     738              : 
     739              :   // FIXME more error handling at some point
     740              :   // used_arguments = subst_mappings;
     741              :   // error_flag |= used_arguments.is_error ();
     742              : 
     743        53287 :   return nullptr;
     744              : }
     745              : 
     746              : bool
     747          588 : TypeBoundPredicate::requires_generic_args () const
     748              : {
     749          588 :   if (is_error ())
     750              :     return false;
     751              : 
     752          588 :   return substitutions.size () > 1;
     753              : }
     754              : 
     755              : bool
     756            0 : TypeBoundPredicate::contains_associated_types () const
     757              : {
     758            0 :   return get_num_associated_bindings () > 0;
     759              : }
     760              : 
     761              : size_t
     762          194 : TypeBoundPredicate::get_num_associated_bindings () const
     763              : {
     764          194 :   size_t count = 0;
     765              : 
     766          194 :   get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
     767          546 :     for (const auto &trait_item : ref.get_trait_items ())
     768              :       {
     769          352 :         bool is_associated_type
     770          352 :           = trait_item.get_trait_item_type ()
     771          352 :             == Resolver::TraitItemReference::TraitItemType::TYPE;
     772          352 :         if (is_associated_type)
     773          194 :           count++;
     774              :       }
     775          194 :   });
     776              : 
     777          194 :   return count;
     778              : }
     779              : 
     780              : void
     781          194 : TypeBoundPredicate::get_trait_hierachy (
     782              :   std::function<void (const Resolver::TraitReference &)> callback) const
     783              : {
     784          194 :   auto trait_ref = get ();
     785          194 :   callback (*trait_ref);
     786              : 
     787          194 :   for (auto &super : super_traits)
     788              :     {
     789            0 :       const auto &super_trait_ref = *super.get ();
     790            0 :       callback (super_trait_ref);
     791            0 :       super.get_trait_hierachy (callback);
     792              :     }
     793          194 : }
     794              : 
     795              : TypeBoundPredicateItem
     796           97 : TypeBoundPredicate::lookup_associated_type (const std::string &search)
     797              : {
     798           97 :   tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search);
     799              : 
     800              :   // only need to check that it is infact an associated type because other
     801              :   // wise if it was not found it will just be an error node anyway
     802           97 :   if (item.has_value ())
     803              :     {
     804           97 :       const auto raw = item->get_raw_item ();
     805           97 :       if (raw->get_trait_item_type ()
     806              :           != Resolver::TraitItemReference::TraitItemType::TYPE)
     807            0 :         return TypeBoundPredicateItem::error ();
     808              :     }
     809           97 :   return item.value ();
     810           97 : }
     811              : 
     812              : std::vector<TypeBoundPredicateItem>
     813            0 : TypeBoundPredicate::get_associated_type_items ()
     814              : {
     815            0 :   std::vector<TypeBoundPredicateItem> items;
     816            0 :   auto trait_ref = get ();
     817            0 :   for (const auto &trait_item : trait_ref->get_trait_items ())
     818              :     {
     819            0 :       bool is_associated_type
     820            0 :         = trait_item.get_trait_item_type ()
     821            0 :           == Resolver::TraitItemReference::TraitItemType::TYPE;
     822            0 :       if (is_associated_type)
     823            0 :         items.emplace_back (*this, &trait_item);
     824              :     }
     825            0 :   return items;
     826              : }
     827              : 
     828              : bool
     829        19269 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
     830              : {
     831              :   // check they match the same trait reference
     832        34888 :   if (reference != other.reference)
     833              :     return false;
     834              : 
     835              :   // check that the generics match
     836         3655 :   if (get_num_substitutions () != other.get_num_substitutions ())
     837              :     return false;
     838              : 
     839              :   // then match the generics applied
     840         8359 :   for (size_t i = 0; i < get_num_substitutions (); i++)
     841              :     {
     842         4709 :       SubstitutionParamMapping a = substitutions.at (i);
     843         4709 :       SubstitutionParamMapping b = other.substitutions.at (i);
     844              : 
     845         4709 :       auto ap = a.get_param_ty ();
     846         4709 :       auto bp = b.get_param_ty ();
     847              : 
     848         4709 :       BaseType *apd = ap->destructure ();
     849         4709 :       BaseType *bpd = bp->destructure ();
     850              : 
     851         4709 :       if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
     852         4709 :                                        TyTy::TyWithLocation (bpd),
     853              :                                        UNKNOWN_LOCATION, false))
     854            5 :         return false;
     855              :     }
     856              : 
     857              :   return true;
     858              : }
     859              : 
     860              : bool
     861         8381 : TypeBoundPredicate::validate_type_implements_super_traits (
     862              :   TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
     863              : {
     864         8381 :   if (get_polarity () != BoundPolarity::RegularBound)
     865              :     return true;
     866              : 
     867         8376 :   auto &ptref = *get ();
     868        12038 :   for (auto &super : super_traits)
     869              :     {
     870         3663 :       if (super.get_polarity () != BoundPolarity::RegularBound)
     871            0 :         continue;
     872              : 
     873         3663 :       if (!super.validate_type_implements_this (self, impl_type, trait))
     874              :         {
     875            1 :           auto &sptref = *super.get ();
     876              : 
     877              :           // emit error
     878            1 :           std::string fixit1
     879            1 :             = "required by this bound in: " + ptref.get_name ();
     880            2 :           std::string fixit2 = "the trait " + sptref.get_name ()
     881            2 :                                + " is not implemented for "
     882            2 :                                + impl_type.to_string ();
     883              : 
     884            1 :           rich_location r (line_table, trait.get_locus ());
     885            1 :           r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
     886            1 :           r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
     887            1 :           rust_error_at (r, ErrorCode::E0277,
     888              :                          "the trait bound %<%s: %s%> is not satisfied",
     889            2 :                          impl_type.to_string ().c_str (),
     890            1 :                          sptref.get_name ().c_str ());
     891              : 
     892            1 :           return false;
     893            1 :         }
     894              : 
     895         3662 :       if (!super.validate_type_implements_super_traits (self, impl_type, trait))
     896              :         return false;
     897              :     }
     898              : 
     899              :   return true;
     900              : }
     901              : 
     902              : bool
     903         3663 : TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
     904              :                                                    HIR::Type &impl_type,
     905              :                                                    HIR::Type &trait) const
     906              : {
     907         3663 :   const auto &ptref = *get ();
     908         3663 :   auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
     909        13073 :   for (auto &elem : probed_bounds)
     910              :     {
     911        13072 :       auto &tref = *(elem.first);
     912        13072 :       if (ptref.is_equal (tref))
     913         3663 :         return true;
     914              :     }
     915              : 
     916              :   return false;
     917         3663 : }
     918              : 
     919              : // trait item reference
     920              : 
     921              : const Resolver::TraitItemReference *
     922        39465 : TypeBoundPredicateItem::get_raw_item () const
     923              : {
     924        39465 :   return trait_item_ref;
     925              : }
     926              : 
     927              : bool
     928            0 : TypeBoundPredicateItem::needs_implementation () const
     929              : {
     930            0 :   return !get_raw_item ()->is_optional ();
     931              : }
     932              : 
     933              : location_t
     934            5 : TypeBoundPredicateItem::get_locus () const
     935              : {
     936            5 :   return get_raw_item ()->get_locus ();
     937              : }
     938              : 
     939              : // TypeBoundsMappings
     940              : 
     941     96787050 : TypeBoundsMappings::TypeBoundsMappings (
     942     96787050 :   std::vector<TypeBoundPredicate> specified_bounds)
     943     96787050 :   : specified_bounds (specified_bounds)
     944     96787050 : {}
     945              : 
     946              : std::vector<TypeBoundPredicate> &
     947       132694 : TypeBoundsMappings::get_specified_bounds ()
     948              : {
     949       132694 :   return specified_bounds;
     950              : }
     951              : 
     952              : const std::vector<TypeBoundPredicate> &
     953     95150629 : TypeBoundsMappings::get_specified_bounds () const
     954              : {
     955     95150629 :   return specified_bounds;
     956              : }
     957              : 
     958              : TypeBoundPredicate
     959            0 : TypeBoundsMappings::lookup_predicate (DefId id)
     960              : {
     961            0 :   for (auto &b : specified_bounds)
     962              :     {
     963            0 :       if (b.get_id () == id)
     964            0 :         return b;
     965              :     }
     966            0 :   return TypeBoundPredicate::error ();
     967              : }
     968              : 
     969              : size_t
     970       239532 : TypeBoundsMappings::num_specified_bounds () const
     971              : {
     972       239532 :   return specified_bounds.size ();
     973              : }
     974              : 
     975              : std::string
     976        32751 : TypeBoundsMappings::raw_bounds_as_string () const
     977              : {
     978        32751 :   std::string buf;
     979        33927 :   for (size_t i = 0; i < specified_bounds.size (); i++)
     980              :     {
     981         1176 :       const TypeBoundPredicate &b = specified_bounds.at (i);
     982         1176 :       bool has_next = (i + 1) < specified_bounds.size ();
     983         4690 :       buf += b.as_string () + (has_next ? " + " : "");
     984              :     }
     985        32751 :   return buf;
     986              : }
     987              : 
     988              : std::string
     989        31649 : TypeBoundsMappings::bounds_as_string () const
     990              : {
     991        63298 :   return "bounds:[" + raw_bounds_as_string () + "]";
     992              : }
     993              : 
     994              : std::string
     995        53432 : TypeBoundsMappings::raw_bounds_as_name () const
     996              : {
     997        53432 :   std::string buf;
     998       106946 :   for (size_t i = 0; i < specified_bounds.size (); i++)
     999              :     {
    1000        53514 :       const TypeBoundPredicate &b = specified_bounds.at (i);
    1001        53514 :       bool has_next = (i + 1) < specified_bounds.size ();
    1002       213950 :       buf += b.as_name () + (has_next ? " + " : "");
    1003              :     }
    1004              : 
    1005        53432 :   return buf;
    1006              : }
    1007              : 
    1008              : void
    1009        68329 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
    1010              : {
    1011        75908 :   for (auto &bound : specified_bounds)
    1012              :     {
    1013        40311 :       bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
    1014         7579 :       if (same_trait_ref_p)
    1015        68329 :         return;
    1016              :     }
    1017              : 
    1018        35597 :   specified_bounds.push_back (predicate);
    1019              : }
    1020              : 
    1021              : } // namespace TyTy
    1022              : } // 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.