LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-bounds.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.8 % 517 490
Test Date: 2026-02-28 14:20:25 Functions: 93.0 % 57 53
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        66508 : TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
      30        66508 :   : TypeCheckBase (), receiver (receiver)
      31        66508 : {}
      32              : 
      33              : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
      34        66508 : TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
      35              : {
      36        66508 :   TypeBoundsProbe probe (receiver);
      37        66508 :   probe.scan ();
      38        66508 :   return probe.trait_references;
      39        66508 : }
      40              : 
      41              : bool
      42           80 : TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
      43              :                                               TraitReference *ref)
      44              : {
      45           80 :   for (auto &bound : receiver->get_specified_bounds ())
      46              :     {
      47            0 :       const TraitReference *b = bound.get ();
      48            0 :       if (b->is_equal (*ref))
      49           80 :         return true;
      50              :     }
      51              : 
      52           80 :   std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
      53           80 :     = Probe (receiver);
      54           91 :   for (auto &bound : bounds)
      55              :     {
      56           91 :       const TraitReference *b = bound.first;
      57           91 :       if (b->is_equal (*ref))
      58           80 :         return true;
      59              :     }
      60              : 
      61              :   return false;
      62           80 : }
      63              : 
      64              : bool
      65      2002015 : 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      2002015 :   if (!impl->has_trait_ref ())
      72              :     return true;
      73              : 
      74              :   // can be recursive trait resolution
      75      1782618 :   HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
      76      1782618 :   if (t == nullptr)
      77              :     return true;
      78              : 
      79      1782618 :   HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
      80      1782618 :   TyTy::BaseType *impl_type = nullptr;
      81      1782618 :   if (!query_type (impl_ty_id, &impl_type))
      82              :     return true;
      83              : 
      84      1779607 :   if (!types_compatable (TyTy::TyWithLocation (receiver),
      85      1779607 :                          TyTy::TyWithLocation (impl_type), impl->get_locus (),
      86              :                          false /*emit_errors*/, false /*check-bounds*/))
      87              :     return true;
      88              : 
      89       283662 :   possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
      90       283662 :   return true;
      91              : }
      92              : 
      93              : void
      94        66508 : TypeBoundsProbe::scan ()
      95              : {
      96        66508 :   std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
      97        66508 :     possible_trait_paths;
      98        66508 :   mappings.iterate_impl_blocks (
      99        66508 :     [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
     100      2002015 :       return process_impl_block (id, impl, possible_trait_paths);
     101              :     });
     102              : 
     103       350170 :   for (auto &path : possible_trait_paths)
     104              :     {
     105       283662 :       HIR::TypePath *trait_path = path.first;
     106       283662 :       TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
     107              : 
     108       283662 :       if (!trait_ref->is_error ())
     109       283662 :         trait_references.emplace_back (trait_ref, path.second);
     110              :     }
     111              : 
     112              :   // marker traits...
     113        66508 :   assemble_marker_builtins ();
     114              : 
     115              :   // add auto trait bounds
     116        66526 :   for (auto *auto_trait : mappings.get_auto_traits ())
     117           18 :     add_trait_bound (auto_trait);
     118        66508 : }
     119              : 
     120              : void
     121        66508 : TypeBoundsProbe::assemble_marker_builtins ()
     122              : {
     123        66508 :   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        66508 :   switch (raw->get_kind ())
     134              :     {
     135        50687 :     case TyTy::ARRAY:
     136        50687 :     case TyTy::REF:
     137        50687 :     case TyTy::POINTER:
     138        50687 :     case TyTy::PARAM:
     139        50687 :     case TyTy::FNDEF:
     140        50687 :     case TyTy::BOOL:
     141        50687 :     case TyTy::CHAR:
     142        50687 :     case TyTy::INT:
     143        50687 :     case TyTy::UINT:
     144        50687 :     case TyTy::FLOAT:
     145        50687 :     case TyTy::USIZE:
     146        50687 :     case TyTy::ISIZE:
     147        50687 :     case TyTy::INFER:
     148        50687 :     case TyTy::NEVER:
     149        50687 :     case TyTy::PLACEHOLDER:
     150        50687 :     case TyTy::PROJECTION:
     151        50687 :     case TyTy::OPAQUE:
     152        50687 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     153        50687 :       break;
     154              : 
     155          175 :     case TyTy::FNPTR:
     156          175 :     case TyTy::CLOSURE:
     157          175 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     158          175 :       assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
     159          175 :       assemble_builtin_candidate (LangItem::Kind::FN);
     160          175 :       assemble_builtin_candidate (LangItem::Kind::FN_MUT);
     161          175 :       break;
     162              : 
     163              :       // FIXME str and slice need to be moved and test cases updated
     164        15417 :     case TyTy::SLICE:
     165        15417 :     case TyTy::STR:
     166        15417 :     case TyTy::ADT:
     167        15417 :     case TyTy::TUPLE:
     168              :       // FIXME add extra checks
     169        15417 :       assemble_builtin_candidate (LangItem::Kind::SIZED);
     170        15417 :       break;
     171              : 
     172              :     case TyTy::CONST:
     173              :     case TyTy::DYNAMIC:
     174              :     case TyTy::ERROR:
     175              :       break;
     176              :     }
     177        66508 : }
     178              : 
     179              : void
     180        66215 : TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
     181              : {
     182        66215 :   auto trait_ref = TraitResolver::Resolve (*trait);
     183              : 
     184        66215 :   trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
     185        66215 : }
     186              : 
     187              : void
     188        66804 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
     189              : {
     190        66804 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item);
     191        66804 :   if (!lang_item_defined)
     192          607 :     return;
     193        66197 :   DefId &id = lang_item_defined.value ();
     194              : 
     195        66197 :   auto defid = mappings.lookup_defid (id);
     196        66197 :   if (!defid)
     197              :     return;
     198        66197 :   auto item = defid.value ();
     199              : 
     200        66197 :   rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
     201        66197 :   HIR::Trait *trait = static_cast<HIR::Trait *> (item);
     202        66197 :   const TyTy::BaseType *raw = receiver->destructure ();
     203              : 
     204        66197 :   add_trait_bound (trait);
     205              : 
     206        66197 :   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         6757 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
     213              : {
     214         6757 :   return TraitResolver::Resolve (path);
     215              : }
     216              : 
     217              : TyTy::TypeBoundPredicate
     218        38136 : 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        38136 :   TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
     224        38136 :   bool already_resolved
     225        38136 :     = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
     226              :                                  &lookup);
     227        38136 :   if (already_resolved)
     228        31379 :     return lookup;
     229              : 
     230         6757 :   TraitReference *trait = resolve_trait_path (type_path);
     231         6757 :   if (trait->is_error ())
     232            9 :     return TyTy::TypeBoundPredicate::error ();
     233              : 
     234         6748 :   TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
     235         6748 :   HIR::GenericArgs args
     236         6748 :     = HIR::GenericArgs::create_empty (type_path.get_locus ());
     237              : 
     238         6748 :   auto &final_seg = type_path.get_final_segment ();
     239         6748 :   switch (final_seg.get_type ())
     240              :     {
     241          847 :     case HIR::TypePathSegment::SegmentType::GENERIC:
     242          847 :       {
     243          847 :         auto &final_generic_seg
     244              :           = static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
     245          847 :         if (final_generic_seg.has_generic_args ())
     246              :           {
     247          847 :             args = final_generic_seg.get_generic_args ();
     248          847 :             if (args.get_binding_args ().size () > 0
     249          847 :                 && 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         6748 :   if (associated_self.has_value ())
     322              :     {
     323         5950 :       std::vector<std::unique_ptr<HIR::Type>> type_args;
     324         5950 :       type_args.push_back (std::unique_ptr<HIR::Type> (
     325         5950 :         associated_self.value ().get ().clone_type ()));
     326         6539 :       for (auto &arg : args.get_type_args ())
     327              :         {
     328          589 :           type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
     329              :         }
     330              : 
     331        17850 :       args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
     332         5950 :                                args.get_binding_args (), args.get_const_args (),
     333        11900 :                                args.get_locus ());
     334         5950 :     }
     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         6748 :   if (!args.is_empty () || predicate.requires_generic_args ())
     340              :     {
     341              :       // this is applying generic arguments to a trait reference
     342         6224 :       predicate.apply_generic_arguments (&args, associated_self.has_value (),
     343              :                                          is_super_trait);
     344              :     }
     345              : 
     346         6748 :   context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
     347              :                                       predicate);
     348              : 
     349         6748 :   return predicate;
     350        38136 : }
     351              : 
     352              : } // namespace Resolver
     353              : 
     354              : namespace TyTy {
     355              : 
     356        20224 : TypeBoundPredicate::TypeBoundPredicate (
     357              :   const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
     358        20224 :   location_t locus)
     359        40448 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     360        20224 :     reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
     361        20224 :     error_flag (false), polarity (polarity),
     362        60672 :     super_traits (trait_reference.get_super_traits ())
     363              : {
     364        20224 :   rust_assert (!trait_reference.get_trait_substs ().empty ());
     365              : 
     366        20224 :   substitutions.clear ();
     367        43340 :   for (const auto &p : trait_reference.get_trait_substs ())
     368        23116 :     substitutions.push_back (p.clone ());
     369              : 
     370              :   // we setup a dummy implict self argument
     371        20224 :   SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
     372        20224 :   used_arguments.get_mappings ().push_back (placeholder_self);
     373        20224 : }
     374              : 
     375         3696 : TypeBoundPredicate::TypeBoundPredicate (
     376              :   DefId reference, std::vector<SubstitutionParamMapping> subst,
     377         3696 :   BoundPolarity polarity, location_t locus)
     378         7392 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     379         3696 :     reference (reference), locus (locus), error_flag (false),
     380         7392 :     polarity (polarity)
     381              : {
     382         3696 :   rust_assert (!subst.empty ());
     383              : 
     384         3696 :   substitutions.clear ();
     385         8041 :   for (const auto &p : subst)
     386         4345 :     substitutions.push_back (p.clone ());
     387              : 
     388              :   // we setup a dummy implict self argument
     389         3696 :   SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
     390         3696 :   used_arguments.get_mappings ().push_back (placeholder_self);
     391         3696 : }
     392              : 
     393       108790 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
     394       217580 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     395       108790 :     reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
     396       108790 :     polarity (BoundPolarity::RegularBound)
     397       108790 : {}
     398              : 
     399     73867070 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
     400    147734140 :   : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
     401     73867070 :     reference (other.reference), locus (other.locus),
     402     73867070 :     error_flag (other.error_flag), polarity (other.polarity),
     403    147734140 :     super_traits (other.super_traits)
     404              : {
     405     73867070 :   substitutions.clear ();
     406    157197190 :   for (const auto &p : other.get_substs ())
     407     83330120 :     substitutions.push_back (p.clone ());
     408              : 
     409     73867070 :   std::vector<SubstitutionArg> mappings;
     410    149375468 :   for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
     411              :     {
     412     75508398 :       const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
     413     75508398 :       SubstitutionArg arg (oa);
     414     75508398 :       mappings.push_back (std::move (arg));
     415              :     }
     416              : 
     417              :   // we need to remap the argument mappings based on this copied constructor
     418     73867070 :   std::vector<SubstitutionArg> copied_arg_mappings;
     419     73867070 :   size_t i = 0;
     420    149375468 :   for (const auto &m : other.used_arguments.get_mappings ())
     421              :     {
     422     75508398 :       TyTy::BaseType *argument
     423     75508398 :         = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
     424     75508398 :       SubstitutionArg c (&substitutions.at (i++), argument);
     425     75508398 :       copied_arg_mappings.push_back (std::move (c));
     426              :     }
     427              : 
     428     73867070 :   used_arguments
     429     73867070 :     = SubstitutionArgumentMappings (copied_arg_mappings, {},
     430              :                                     other.used_arguments.get_regions (),
     431    147734140 :                                     other.used_arguments.get_locus ());
     432     73867070 : }
     433              : 
     434              : TypeBoundPredicate &
     435        81128 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
     436              : {
     437        81128 :   reference = other.reference;
     438        81128 :   locus = other.locus;
     439        81128 :   error_flag = other.error_flag;
     440        81128 :   polarity = other.polarity;
     441        81128 :   used_arguments = SubstitutionArgumentMappings::empty ();
     442              : 
     443        81128 :   substitutions.clear ();
     444       199880 :   for (const auto &p : other.get_substs ())
     445       118752 :     substitutions.push_back (p.clone ());
     446              : 
     447        81128 :   if (other.is_error ())
     448              :     return *this;
     449              : 
     450        71971 :   std::vector<SubstitutionArg> mappings;
     451       190712 :   for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
     452              :     {
     453       118741 :       const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
     454       118741 :       SubstitutionArg arg (oa);
     455       118741 :       mappings.push_back (std::move (arg));
     456              :     }
     457              : 
     458              :   // we need to remap the argument mappings based on this copied constructor
     459        71971 :   std::vector<SubstitutionArg> copied_arg_mappings;
     460        71971 :   size_t i = 0;
     461       190712 :   for (const auto &m : other.used_arguments.get_mappings ())
     462              :     {
     463       118741 :       TyTy::BaseType *argument
     464       118741 :         = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
     465              : 
     466       118741 :       copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
     467              :     }
     468              : 
     469        71971 :   used_arguments
     470        71971 :     = SubstitutionArgumentMappings (copied_arg_mappings, {},
     471              :                                     other.used_arguments.get_regions (),
     472       143942 :                                     other.used_arguments.get_locus ());
     473        71971 :   super_traits = other.super_traits;
     474              : 
     475        71971 :   return *this;
     476        71971 : }
     477              : 
     478              : TypeBoundPredicate
     479       108790 : TypeBoundPredicate::error ()
     480              : {
     481       108790 :   return TypeBoundPredicate (mark_is_error ());
     482              : }
     483              : 
     484              : std::string
     485         3271 : TypeBoundPredicate::as_string () const
     486              : {
     487         3271 :   return get ()->as_string () + subst_as_string ();
     488              : }
     489              : 
     490              : std::string
     491        49615 : TypeBoundPredicate::as_name () const
     492              : {
     493        49615 :   return get ()->get_name () + subst_as_string ();
     494              : }
     495              : 
     496              : const Resolver::TraitReference *
     497       362883 : TypeBoundPredicate::get () const
     498              : {
     499       362883 :   auto context = Resolver::TypeCheckContext::get ();
     500              : 
     501       362883 :   Resolver::TraitReference *ref = nullptr;
     502       362883 :   bool ok = context->lookup_trait_reference (reference, &ref);
     503       362883 :   rust_assert (ok);
     504              : 
     505       362883 :   return ref;
     506              : }
     507              : 
     508              : std::string
     509         8536 : TypeBoundPredicate::get_name () const
     510              : {
     511         8536 :   return get ()->get_name ();
     512              : }
     513              : 
     514              : bool
     515          200 : TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
     516              : {
     517          200 :   const Resolver::TraitReference *trait = get ();
     518          200 :   rust_assert (trait != nullptr);
     519          200 :   return trait->is_object_safe (emit_error, locus);
     520              : }
     521              : 
     522              : void
     523         6289 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
     524              :                                              bool has_associated_self,
     525              :                                              bool is_super_trait)
     526              : {
     527         6289 :   rust_assert (!substitutions.empty ());
     528         6289 :   if (has_associated_self)
     529              :     {
     530         5950 :       used_arguments = SubstitutionArgumentMappings::empty ();
     531              :     }
     532              :   else
     533              :     {
     534              :       // we need to get the substitutions argument mappings but also remember
     535              :       // that we have an implicit Self argument which we must be careful to
     536              :       // respect
     537          339 :       rust_assert (!used_arguments.is_empty ());
     538              :     }
     539              : 
     540              :   // now actually perform a substitution
     541         6289 :   auto args = get_mappings_from_generic_args (
     542              :     *generic_args,
     543         6289 :     Resolver::TypeCheckContext::get ()->regions_from_generic_args (
     544        12578 :       *generic_args));
     545              : 
     546         6289 :   apply_argument_mappings (args, is_super_trait);
     547         6289 : }
     548              : 
     549              : void
     550        10316 : TypeBoundPredicate::apply_argument_mappings (
     551              :   SubstitutionArgumentMappings &arguments, bool is_super_trait)
     552              : {
     553        10316 :   used_arguments = arguments;
     554        10316 :   error_flag |= used_arguments.is_error ();
     555        10316 :   auto &subst_mappings = used_arguments;
     556              : 
     557        10316 :   bool substs_need_bounds_check = !is_super_trait;
     558        23623 :   for (auto &sub : get_substs ())
     559              :     {
     560        13307 :       SubstitutionArg arg = SubstitutionArg::error ();
     561        13307 :       bool ok
     562        13307 :         = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
     563        13307 :       if (ok && arg.get_tyty () != nullptr)
     564        12887 :         sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
     565              :                            substs_need_bounds_check);
     566              :     }
     567              : 
     568              :   // associated argument mappings
     569        10396 :   for (auto &it : subst_mappings.get_binding_args ())
     570              :     {
     571           80 :       std::string identifier = it.first;
     572           80 :       TyTy::BaseType *type = it.second;
     573              : 
     574           80 :       tl::optional<TypeBoundPredicateItem> item
     575           80 :         = lookup_associated_item (identifier);
     576              : 
     577           80 :       if (!item.has_value ())
     578            0 :         continue;
     579              : 
     580           80 :       const auto item_ref = item->get_raw_item ();
     581           80 :       item_ref->associated_type_set (type);
     582           80 :     }
     583              : 
     584        14335 :   for (auto &super_trait : super_traits)
     585              :     {
     586         4019 :       auto adjusted
     587              :         = super_trait.adjust_mappings_for_this (used_arguments,
     588         4019 :                                                 true /*trait mode*/);
     589         4019 :       super_trait.apply_argument_mappings (adjusted, is_super_trait);
     590         4019 :     }
     591        10316 : }
     592              : 
     593              : bool
     594            0 : TypeBoundPredicate::contains_item (const std::string &search) const
     595              : {
     596            0 :   auto trait_ref = get ();
     597            0 :   const Resolver::TraitItemReference *trait_item_ref = nullptr;
     598            0 :   return trait_ref->lookup_trait_item (search, &trait_item_ref);
     599              : }
     600              : 
     601              : tl::optional<TypeBoundPredicateItem>
     602        24751 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
     603              : {
     604        24751 :   auto trait_ref = get ();
     605        24751 :   const Resolver::TraitItemReference *trait_item_ref = nullptr;
     606        24751 :   if (trait_ref->lookup_trait_item (search, &trait_item_ref,
     607              :                                     false /*lookup supers*/))
     608        23270 :     return TypeBoundPredicateItem (*this, trait_item_ref);
     609              : 
     610         1597 :   for (auto &super_trait : super_traits)
     611              :     {
     612          236 :       auto lookup = super_trait.lookup_associated_item (search);
     613          236 :       if (lookup.has_value ())
     614          120 :         return lookup;
     615          236 :     }
     616              : 
     617         1361 :   return tl::nullopt;
     618              : }
     619              : 
     620        28755 : TypeBoundPredicateItem::TypeBoundPredicateItem (
     621              :   const TypeBoundPredicate parent,
     622        28755 :   const Resolver::TraitItemReference *trait_item_ref)
     623        28755 :   : parent (parent), trait_item_ref (trait_item_ref)
     624        28755 : {}
     625              : 
     626        31337 : TypeBoundPredicateItem::TypeBoundPredicateItem (
     627        31337 :   const TypeBoundPredicateItem &other)
     628        31337 :   : parent (other.parent), trait_item_ref (other.trait_item_ref)
     629        31337 : {}
     630              : 
     631              : TypeBoundPredicateItem &
     632         5408 : TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
     633              : {
     634         5408 :   parent = other.parent;
     635         5408 :   trait_item_ref = other.trait_item_ref;
     636              : 
     637         5408 :   return *this;
     638              : }
     639              : 
     640              : TypeBoundPredicateItem
     641         5412 : TypeBoundPredicateItem::error ()
     642              : {
     643         5412 :   return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
     644              : }
     645              : 
     646              : bool
     647         5484 : TypeBoundPredicateItem::is_error () const
     648              : {
     649         5484 :   return parent.is_error () || trait_item_ref == nullptr;
     650              : }
     651              : 
     652              : const TypeBoundPredicate *
     653         1262 : TypeBoundPredicateItem::get_parent () const
     654              : {
     655         1262 :   return &parent;
     656              : }
     657              : 
     658              : tl::optional<TypeBoundPredicateItem>
     659         5347 : TypeBoundPredicate::lookup_associated_item (
     660              :   const Resolver::TraitItemReference *ref) const
     661              : {
     662         5347 :   return lookup_associated_item (ref->get_identifier ());
     663              : }
     664              : 
     665              : BaseType *
     666         7381 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
     667              : {
     668         7381 :   TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
     669         7381 :   if (parent.get_substitution_arguments ().is_empty ())
     670              :     return trait_item_tyty;
     671              : 
     672         7381 :   const Resolver::TraitItemReference *tref = get_raw_item ();
     673         7381 :   bool is_associated_type = tref->get_trait_item_type ();
     674         7381 :   if (is_associated_type)
     675              :     return trait_item_tyty;
     676              : 
     677              :   // set up the self mapping
     678         5880 :   SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
     679         5880 :   rust_assert (!gargs.is_empty ());
     680              : 
     681              :   // setup the adjusted mappings
     682         5880 :   std::vector<SubstitutionArg> adjusted_mappings;
     683        14225 :   for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
     684              :     {
     685         8345 :       auto &mapping = gargs.get_mappings ().at (i);
     686              : 
     687         8345 :       bool is_implicit_self = i == 0;
     688         8345 :       TyTy::BaseType *argument
     689         8345 :         = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
     690              : 
     691         8345 :       adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument);
     692              :     }
     693              : 
     694         5880 :   SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
     695              :                                          gargs.get_regions (),
     696              :                                          gargs.get_locus (),
     697         5880 :                                          gargs.get_subst_cb (),
     698         5880 :                                          true /* trait-mode-flag */);
     699         5880 :   return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
     700         5880 : }
     701              : bool
     702       152902 : TypeBoundPredicate::is_error () const
     703              : {
     704       152902 :   auto context = Resolver::TypeCheckContext::get ();
     705              : 
     706       152902 :   Resolver::TraitReference *ref = nullptr;
     707       152902 :   bool ok = context->lookup_trait_reference (reference, &ref);
     708              : 
     709       152902 :   return !ok || error_flag;
     710              : }
     711              : 
     712              : BaseType *
     713        36957 : TypeBoundPredicate::handle_substitions (
     714              :   SubstitutionArgumentMappings &subst_mappings)
     715              : {
     716        82076 :   for (auto &sub : get_substs ())
     717              :     {
     718        45119 :       if (sub.get_param_ty () == nullptr)
     719            0 :         continue;
     720              : 
     721        45119 :       auto p = sub.get_param_ty ();
     722        45119 :       BaseType *r = p->resolve ();
     723        45119 :       BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
     724              : 
     725        45119 :       p->set_ty_ref (s->get_ty_ref ());
     726              :     }
     727              : 
     728              :   // associated argument mappings
     729        37000 :   for (auto &it : subst_mappings.get_binding_args ())
     730              :     {
     731           43 :       std::string identifier = it.first;
     732           43 :       TyTy::BaseType *type = it.second;
     733              : 
     734           43 :       tl::optional<TypeBoundPredicateItem> item
     735           43 :         = lookup_associated_item (identifier);
     736           43 :       if (item.has_value ())
     737              :         {
     738            8 :           const auto item_ref = item->get_raw_item ();
     739            8 :           item_ref->associated_type_set (type);
     740              :         }
     741           43 :     }
     742              : 
     743              :   // FIXME more error handling at some point
     744              :   // used_arguments = subst_mappings;
     745              :   // error_flag |= used_arguments.is_error ();
     746              : 
     747        36957 :   return nullptr;
     748              : }
     749              : 
     750              : bool
     751          524 : TypeBoundPredicate::requires_generic_args () const
     752              : {
     753          524 :   if (is_error ())
     754              :     return false;
     755              : 
     756          524 :   return substitutions.size () > 1;
     757              : }
     758              : 
     759              : bool
     760            0 : TypeBoundPredicate::contains_associated_types () const
     761              : {
     762            0 :   return get_num_associated_bindings () > 0;
     763              : }
     764              : 
     765              : size_t
     766          144 : TypeBoundPredicate::get_num_associated_bindings () const
     767              : {
     768          144 :   size_t count = 0;
     769              : 
     770          144 :   get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
     771          396 :     for (const auto &trait_item : ref.get_trait_items ())
     772              :       {
     773          252 :         bool is_associated_type
     774          252 :           = trait_item.get_trait_item_type ()
     775          252 :             == Resolver::TraitItemReference::TraitItemType::TYPE;
     776          252 :         if (is_associated_type)
     777          144 :           count++;
     778              :       }
     779          144 :   });
     780              : 
     781          144 :   return count;
     782              : }
     783              : 
     784              : void
     785          144 : TypeBoundPredicate::get_trait_hierachy (
     786              :   std::function<void (const Resolver::TraitReference &)> callback) const
     787              : {
     788          144 :   auto trait_ref = get ();
     789          144 :   callback (*trait_ref);
     790              : 
     791          144 :   for (auto &super : super_traits)
     792              :     {
     793            0 :       const auto &super_trait_ref = *super.get ();
     794            0 :       callback (super_trait_ref);
     795            0 :       super.get_trait_hierachy (callback);
     796              :     }
     797          144 : }
     798              : 
     799              : TypeBoundPredicateItem
     800           72 : TypeBoundPredicate::lookup_associated_type (const std::string &search)
     801              : {
     802           72 :   tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search);
     803              : 
     804              :   // only need to check that it is infact an associated type because other
     805              :   // wise if it was not found it will just be an error node anyway
     806           72 :   if (item.has_value ())
     807              :     {
     808           72 :       const auto raw = item->get_raw_item ();
     809           72 :       if (raw->get_trait_item_type ()
     810              :           != Resolver::TraitItemReference::TraitItemType::TYPE)
     811            0 :         return TypeBoundPredicateItem::error ();
     812              :     }
     813           72 :   return item.value ();
     814           72 : }
     815              : 
     816              : std::vector<TypeBoundPredicateItem>
     817            0 : TypeBoundPredicate::get_associated_type_items ()
     818              : {
     819            0 :   std::vector<TypeBoundPredicateItem> items;
     820            0 :   auto trait_ref = get ();
     821            0 :   for (const auto &trait_item : trait_ref->get_trait_items ())
     822              :     {
     823            0 :       bool is_associated_type
     824            0 :         = trait_item.get_trait_item_type ()
     825            0 :           == Resolver::TraitItemReference::TraitItemType::TYPE;
     826            0 :       if (is_associated_type)
     827            0 :         items.emplace_back (*this, &trait_item);
     828              :     }
     829            0 :   return items;
     830              : }
     831              : 
     832              : bool
     833        21704 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
     834              : {
     835              :   // check they match the same trait reference
     836        40122 :   if (reference != other.reference)
     837              :     return false;
     838              : 
     839              :   // check that the generics match
     840         3301 :   if (get_num_substitutions () != other.get_num_substitutions ())
     841              :     return false;
     842              : 
     843              :   // then match the generics applied
     844         7713 :   for (size_t i = 0; i < get_num_substitutions (); i++)
     845              :     {
     846         4427 :       SubstitutionParamMapping a = substitutions.at (i);
     847         4427 :       SubstitutionParamMapping b = other.substitutions.at (i);
     848              : 
     849         4427 :       auto ap = a.get_param_ty ();
     850         4427 :       auto bp = b.get_param_ty ();
     851              : 
     852         4427 :       BaseType *apd = ap->destructure ();
     853         4427 :       BaseType *bpd = bp->destructure ();
     854              : 
     855         4427 :       if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
     856         4427 :                                        TyTy::TyWithLocation (bpd),
     857              :                                        UNKNOWN_LOCATION, false))
     858           15 :         return false;
     859              :     }
     860              : 
     861              :   return true;
     862              : }
     863              : 
     864              : bool
     865         8310 : TypeBoundPredicate::validate_type_implements_super_traits (
     866              :   TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
     867              : {
     868         8310 :   if (get_polarity () != BoundPolarity::RegularBound)
     869              :     return true;
     870              : 
     871         8305 :   auto &ptref = *get ();
     872        11964 :   for (auto &super : super_traits)
     873              :     {
     874         3660 :       if (super.get_polarity () != BoundPolarity::RegularBound)
     875            0 :         continue;
     876              : 
     877         3660 :       if (!super.validate_type_implements_this (self, impl_type, trait))
     878              :         {
     879            1 :           auto &sptref = *super.get ();
     880              : 
     881              :           // emit error
     882            1 :           std::string fixit1
     883            1 :             = "required by this bound in: " + ptref.get_name ();
     884            2 :           std::string fixit2 = "the trait " + sptref.get_name ()
     885            2 :                                + " is not implemented for "
     886            2 :                                + impl_type.to_string ();
     887              : 
     888            1 :           rich_location r (line_table, trait.get_locus ());
     889            1 :           r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
     890            1 :           r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
     891            1 :           rust_error_at (r, ErrorCode::E0277,
     892              :                          "the trait bound %<%s: %s%> is not satisfied",
     893            2 :                          impl_type.to_string ().c_str (),
     894            1 :                          sptref.get_name ().c_str ());
     895              : 
     896            1 :           return false;
     897            1 :         }
     898              : 
     899         3659 :       if (!super.validate_type_implements_super_traits (self, impl_type, trait))
     900              :         return false;
     901              :     }
     902              : 
     903              :   return true;
     904              : }
     905              : 
     906              : bool
     907         3660 : TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
     908              :                                                    HIR::Type &impl_type,
     909              :                                                    HIR::Type &trait) const
     910              : {
     911         3660 :   const auto &ptref = *get ();
     912         3660 :   auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
     913        13065 :   for (auto &elem : probed_bounds)
     914              :     {
     915        13064 :       auto &tref = *(elem.first);
     916        13064 :       if (ptref.is_equal (tref))
     917         3660 :         return true;
     918              :     }
     919              : 
     920              :   return false;
     921         3660 : }
     922              : 
     923              : // trait item reference
     924              : 
     925              : const Resolver::TraitItemReference *
     926        43549 : TypeBoundPredicateItem::get_raw_item () const
     927              : {
     928        43549 :   return trait_item_ref;
     929              : }
     930              : 
     931              : bool
     932            0 : TypeBoundPredicateItem::needs_implementation () const
     933              : {
     934            0 :   return !get_raw_item ()->is_optional ();
     935              : }
     936              : 
     937              : location_t
     938            5 : TypeBoundPredicateItem::get_locus () const
     939              : {
     940            5 :   return get_raw_item ()->get_locus ();
     941              : }
     942              : 
     943              : // TypeBoundsMappings
     944              : 
     945     87349062 : TypeBoundsMappings::TypeBoundsMappings (
     946     87349062 :   std::vector<TypeBoundPredicate> specified_bounds)
     947     87349062 :   : specified_bounds (specified_bounds)
     948     87349062 : {}
     949              : 
     950              : std::vector<TypeBoundPredicate> &
     951       105576 : TypeBoundsMappings::get_specified_bounds ()
     952              : {
     953       105576 :   return specified_bounds;
     954              : }
     955              : 
     956              : const std::vector<TypeBoundPredicate> &
     957     85857838 : TypeBoundsMappings::get_specified_bounds () const
     958              : {
     959     85857838 :   return specified_bounds;
     960              : }
     961              : 
     962              : TypeBoundPredicate
     963         2407 : TypeBoundsMappings::lookup_predicate (DefId id)
     964              : {
     965         2589 :   for (auto &b : specified_bounds)
     966              :     {
     967         2756 :       if (b.get_id () == id)
     968         2392 :         return b;
     969              :     }
     970           15 :   return TypeBoundPredicate::error ();
     971              : }
     972              : 
     973              : size_t
     974       232621 : TypeBoundsMappings::num_specified_bounds () const
     975              : {
     976       232621 :   return specified_bounds.size ();
     977              : }
     978              : 
     979              : std::string
     980        30637 : TypeBoundsMappings::raw_bounds_as_string () const
     981              : {
     982        30637 :   std::string buf;
     983        31658 :   for (size_t i = 0; i < specified_bounds.size (); i++)
     984              :     {
     985         1021 :       const TypeBoundPredicate &b = specified_bounds.at (i);
     986         1021 :       bool has_next = (i + 1) < specified_bounds.size ();
     987         4070 :       buf += b.as_string () + (has_next ? " + " : "");
     988              :     }
     989        30637 :   return buf;
     990              : }
     991              : 
     992              : std::string
     993        29690 : TypeBoundsMappings::bounds_as_string () const
     994              : {
     995        59380 :   return "bounds:[" + raw_bounds_as_string () + "]";
     996              : }
     997              : 
     998              : std::string
     999        49533 : TypeBoundsMappings::raw_bounds_as_name () const
    1000              : {
    1001        49533 :   std::string buf;
    1002        99148 :   for (size_t i = 0; i < specified_bounds.size (); i++)
    1003              :     {
    1004        49615 :       const TypeBoundPredicate &b = specified_bounds.at (i);
    1005        49615 :       bool has_next = (i + 1) < specified_bounds.size ();
    1006       198354 :       buf += b.as_name () + (has_next ? " + " : "");
    1007              :     }
    1008              : 
    1009        49533 :   return buf;
    1010              : }
    1011              : 
    1012              : void
    1013        59978 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
    1014              : {
    1015        65771 :   for (auto &bound : specified_bounds)
    1016              :     {
    1017        35515 :       bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
    1018         5793 :       if (same_trait_ref_p)
    1019        59978 :         return;
    1020              :     }
    1021              : 
    1022        30256 :   specified_bounds.push_back (predicate);
    1023              : }
    1024              : 
    1025              : } // namespace TyTy
    1026              : } // 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.