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