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

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.