LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-subst.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.1 % 543 473
Test Date: 2026-07-11 15:47:05 Functions: 87.2 % 78 68
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-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-tyty-subst.h"
      20              : 
      21              : #include "rust-hir-generic-param.h"
      22              : #include "rust-system.h"
      23              : #include "rust-tyty.h"
      24              : #include "rust-hir-type-check.h"
      25              : #include "rust-substitution-mapper.h"
      26              : #include "rust-hir-type-check-type.h"
      27              : #include "rust-hir-type-check-expr.h"
      28              : #include "rust-compile-base.h"
      29              : #include "rust-type-util.h"
      30              : #include "tree.h"
      31              : 
      32              : namespace Rust {
      33              : namespace TyTy {
      34              : 
      35     92489400 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
      36     92489400 :                                                     BaseGeneric *param)
      37     92489400 :   : generic (generic), param (param)
      38     92489400 : {}
      39              : 
      40    102428307 : SubstitutionParamMapping::SubstitutionParamMapping (
      41    102428307 :   const SubstitutionParamMapping &other)
      42    102428307 :   : generic (other.generic), param (other.param)
      43    102428307 : {}
      44              : 
      45              : std::string
      46      1168543 : SubstitutionParamMapping::as_string () const
      47              : {
      48      1168543 :   if (param == nullptr)
      49            0 :     return "nullptr";
      50              : 
      51      1168543 :   return param->get_name ();
      52              : }
      53              : 
      54              : SubstitutionParamMapping
      55     92472648 : SubstitutionParamMapping::clone () const
      56              : {
      57     92472648 :   return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
      58     92472648 :                                               param->clone ()));
      59              : }
      60              : 
      61              : BaseGeneric *
      62       282890 : SubstitutionParamMapping::get_param_ty ()
      63              : {
      64       282890 :   return param;
      65              : }
      66              : 
      67              : const BaseGeneric *
      68     84610419 : SubstitutionParamMapping::get_param_ty () const
      69              : {
      70     84610419 :   return param;
      71              : }
      72              : 
      73              : HIR::GenericParam &
      74        18181 : SubstitutionParamMapping::get_generic_param ()
      75              : {
      76        18181 :   return generic;
      77              : }
      78              : 
      79              : const HIR::GenericParam &
      80        10044 : SubstitutionParamMapping::get_generic_param () const
      81              : {
      82        10044 :   return generic;
      83              : }
      84              : 
      85              : bool
      86       115036 : SubstitutionParamMapping::needs_substitution () const
      87              : {
      88       115036 :   return !(get_param_ty ()->is_concrete ());
      89              : }
      90              : 
      91              : Identifier
      92         2394 : SubstitutionParamMapping::get_type_representation () const
      93              : {
      94         4788 :   return param->get_symbol ();
      95              : }
      96              : 
      97              : location_t
      98         1008 : SubstitutionParamMapping::get_param_locus () const
      99              : {
     100         1008 :   return generic.get_locus ();
     101              : }
     102              : 
     103              : bool
     104        24043 : SubstitutionParamMapping::param_has_default_ty () const
     105              : {
     106        24043 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     107              :     {
     108        23792 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     109        23792 :       return type_param.has_type ();
     110              :     }
     111              : 
     112          251 :   rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
     113          251 :   const auto &const_param
     114              :     = static_cast<const HIR::ConstGenericParam &> (generic);
     115          251 :   return const_param.has_default_expression ();
     116              : }
     117              : 
     118              : BaseType *
     119         1140 : SubstitutionParamMapping::get_default_ty () const
     120              : {
     121         1140 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     122              :     {
     123         1135 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     124         1135 :       TyVar var (type_param.get_type_mappings ().get_hirid ());
     125         1135 :       return var.get_tyty ();
     126              :     }
     127              : 
     128            5 :   rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
     129            5 :   const auto &const_param
     130              :     = static_cast<const HIR::ConstGenericParam &> (generic);
     131            5 :   rust_assert (const_param.has_default_expression ());
     132              : 
     133            5 :   const auto &expr = const_param.get_default_expression ();
     134            5 :   TyVar var (expr.get_mappings ().get_hirid ());
     135            5 :   return var.get_tyty ();
     136              : }
     137              : 
     138              : bool
     139            0 : SubstitutionParamMapping::need_substitution () const
     140              : {
     141            0 :   if (!param->can_resolve ())
     142              :     return true;
     143              : 
     144            0 :   auto resolved = param->resolve ();
     145            0 :   return !resolved->is_concrete ();
     146              : }
     147              : 
     148              : bool
     149        51044 : SubstitutionParamMapping::fill_param_ty (
     150              :   SubstitutionArgumentMappings &subst_mappings, location_t locus,
     151              :   bool needs_bounds_check)
     152              : {
     153        51044 :   SubstitutionArg arg = SubstitutionArg::error ();
     154        51044 :   bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
     155        51044 :   if (!ok)
     156              :     return true;
     157              : 
     158        51044 :   TyTy::BaseType &type = *arg.get_tyty ();
     159        51044 :   std::pair<HirId, HirId> subst_key (param->get_ref (), type.get_ref ());
     160        51044 :   static std::vector<std::pair<HirId, HirId>> active_substs;
     161        51044 :   bool is_recursive_subst
     162        51044 :     = Resolver::ScopedPush<std::pair<HirId, HirId>>::contains (active_substs,
     163              :                                                                subst_key);
     164        51044 :   bool skip_recursive_bounds
     165        51044 :     = is_recursive_subst && type.get_kind () == TyTy::TypeKind::INFER;
     166           42 :   if (skip_recursive_bounds)
     167              :     {
     168           42 :       type.append_reference (param->get_ref ());
     169           42 :       type.append_reference (param->get_ty_ref ());
     170           42 :       for (auto ref : param->get_combined_refs ())
     171            0 :         type.append_reference (ref);
     172           42 :       if (param->can_resolve ())
     173              :         {
     174           42 :           TyTy::BaseType *resolved = param->resolve ();
     175           42 :           type.append_reference (resolved->get_ref ());
     176           42 :           type.append_reference (resolved->get_ty_ref ());
     177           42 :           for (auto ref : resolved->get_combined_refs ())
     178            0 :             type.append_reference (ref);
     179           42 :           if (resolved->get_kind () != TyTy::TypeKind::PARAM
     180           42 :               && resolved->get_kind () != TyTy::TypeKind::INFER)
     181              :             return true;
     182              :         }
     183              :     }
     184              : 
     185        51002 :   Resolver::ScopedPush<std::pair<HirId, HirId>> guard (active_substs, subst_key,
     186        51002 :                                                        !is_recursive_subst);
     187              : 
     188        51002 :   if (type.get_kind () == TyTy::TypeKind::INFER)
     189              :     {
     190        15022 :       type.inherit_bounds (*param);
     191              :     }
     192              : 
     193        51002 :   if (type.get_kind () == TypeKind::PARAM)
     194              :     {
     195         9665 :       param = static_cast<BaseGeneric *> (type.clone ());
     196              :     }
     197        41337 :   else if (type.get_kind () == TyTy::TypeKind::CONST)
     198              :     {
     199          204 :       rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
     200          204 :       auto *const_type = type.as_const_type ();
     201          204 :       if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
     202           22 :         param = static_cast<BaseGeneric *> (type.clone ());
     203              :       else
     204          182 :         param->set_ty_ref (type.get_ref ());
     205              :     }
     206        41133 :   else if (param->get_kind () == TypeKind::PARAM)
     207              :     {
     208        41133 :       auto &p = *static_cast<TyTy::ParamType *> (param);
     209              : 
     210              :       // check the substitution is compatible with bounds
     211        41133 :       rust_debug_loc (locus,
     212              :                       "fill_param_ty bounds_compatible: param %s type %s",
     213        82266 :                       param->get_name ().c_str (), type.get_name ().c_str ());
     214        41133 :       if (!skip_recursive_bounds && needs_bounds_check
     215        41133 :           && !p.is_implicit_self_trait ())
     216              :         {
     217        22419 :           if (!param->bounds_compatible (type, locus, true))
     218              :             return false;
     219              :         }
     220              : 
     221              :       // recursively pass this down to all HRTB's
     222        41125 :       if (!skip_recursive_bounds)
     223        94251 :         for (auto &bound : param->get_specified_bounds ())
     224        53126 :           bound.handle_substitions (subst_mappings);
     225              : 
     226        41125 :       param->set_ty_ref (type.get_ref ());
     227        41125 :       subst_mappings.on_param_subst (p, arg);
     228              :     }
     229              : 
     230              :   return true;
     231        51002 : }
     232              : 
     233              : void
     234         5254 : SubstitutionParamMapping::override_context ()
     235              : {
     236         5254 :   if (!param->can_resolve ())
     237              :     return;
     238              : 
     239         5240 :   auto &mappings = Analysis::Mappings::get ();
     240         5240 :   auto context = Resolver::TypeCheckContext::get ();
     241              : 
     242         5240 :   context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
     243              :                                                UNKNOWN_NODEID,
     244         5240 :                                                param->get_ref (),
     245         5240 :                                                UNKNOWN_LOCAL_DEFID),
     246         5240 :                         param->resolve ());
     247              : }
     248              : 
     249     84689996 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
     250     84689996 :                                   BaseType *argument)
     251     84689996 :   : param (param), argument (argument)
     252              : {
     253     84689996 :   if (param != nullptr)
     254     84454456 :     original_param = param->get_param_ty ();
     255     84689996 : }
     256              : 
     257    341126075 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
     258    341126075 :   : param (other.param), original_param (other.original_param),
     259    341126075 :     argument (other.argument)
     260    341126075 : {}
     261              : 
     262              : SubstitutionArg &
     263       224585 : SubstitutionArg::operator= (const SubstitutionArg &other)
     264              : {
     265       224585 :   param = other.param;
     266       224585 :   argument = other.argument;
     267       224585 :   original_param = other.original_param;
     268              : 
     269       224585 :   return *this;
     270              : }
     271              : 
     272              : BaseType *
     273     87565313 : SubstitutionArg::get_tyty () const
     274              : {
     275     87565313 :   return argument;
     276              : }
     277              : 
     278              : const SubstitutionParamMapping *
     279            0 : SubstitutionArg::get_param_mapping () const
     280              : {
     281            0 :   return param;
     282              : }
     283              : 
     284              : const BaseGeneric *
     285       252104 : SubstitutionArg::get_param_ty () const
     286              : {
     287       252104 :   return original_param;
     288              : }
     289              : 
     290              : SubstitutionArg
     291       235540 : SubstitutionArg::error ()
     292              : {
     293       235540 :   return SubstitutionArg (nullptr, nullptr);
     294              : }
     295              : 
     296              : bool
     297        80490 : SubstitutionArg::is_error () const
     298              : {
     299        80490 :   return param == nullptr || argument == nullptr;
     300              : }
     301              : 
     302              : bool
     303            0 : SubstitutionArg::is_conrete () const
     304              : {
     305            0 :   if (argument == nullptr)
     306              :     return false;
     307              : 
     308            0 :   if (argument->get_kind () == TyTy::TypeKind::PARAM)
     309              :     return false;
     310              : 
     311            0 :   return argument->is_concrete ();
     312              : }
     313              : 
     314              : std::string
     315            0 : SubstitutionArg::as_string () const
     316              : {
     317            0 :   return original_param->as_string ()
     318            0 :          + (argument != nullptr ? ":" + argument->as_string () : "");
     319              : }
     320              : 
     321              : const RegionParamList &
     322     82708259 : SubstitutionArgumentMappings::get_regions () const
     323              : {
     324     82708259 :   return regions;
     325              : }
     326              : 
     327              : RegionParamList &
     328         2070 : SubstitutionArgumentMappings::get_mut_regions ()
     329              : {
     330         2070 :   return regions;
     331              : }
     332              : 
     333              : // SubstitutionArgumentMappings
     334              : 
     335    165617368 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     336              :   std::vector<SubstitutionArg> mappings,
     337              :   std::map<std::string, BaseType *> binding_args, RegionParamList regions,
     338              :   location_t locus, ParamSubstCb param_subst_cb, bool trait_item_flag,
     339    165617368 :   bool error_flag)
     340    165617368 :   : mappings (std::move (mappings)), binding_args (binding_args),
     341    165617368 :     regions (regions), locus (locus), param_subst_cb (param_subst_cb),
     342    165617368 :     trait_item_flag (trait_item_flag), error_flag (error_flag)
     343    165617368 : {}
     344              : 
     345     83316584 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     346     83316584 :   const SubstitutionArgumentMappings &other)
     347     83316584 :   : mappings (other.mappings), binding_args (other.binding_args),
     348     83316584 :     regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
     349     83316584 :     trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
     350     83316584 : {}
     351              : 
     352              : SubstitutionArgumentMappings &
     353        53332 : SubstitutionArgumentMappings::operator= (
     354              :   const SubstitutionArgumentMappings &other)
     355              : {
     356        53332 :   mappings = other.mappings;
     357        53332 :   binding_args = other.binding_args;
     358        53332 :   regions = other.regions;
     359        53332 :   locus = other.locus;
     360        53332 :   param_subst_cb = nullptr;
     361        53332 :   trait_item_flag = other.trait_item_flag;
     362        53332 :   error_flag = other.error_flag;
     363              : 
     364        53332 :   return *this;
     365              : }
     366              : 
     367              : SubstitutionArgumentMappings
     368        52475 : SubstitutionArgumentMappings::error ()
     369              : {
     370       104950 :   return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
     371        52475 :                                        false, true);
     372              : }
     373              : 
     374              : SubstitutionArgumentMappings
     375     82858467 : SubstitutionArgumentMappings::empty (size_t num_regions)
     376              : {
     377    165716934 :   return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
     378     82858467 :                                        nullptr, false, false);
     379              : }
     380              : 
     381              : bool
     382        44431 : SubstitutionArgumentMappings::is_error () const
     383              : {
     384        44431 :   return error_flag;
     385              : }
     386              : 
     387              : bool
     388       216147 : SubstitutionArgumentMappings::get_argument_for_symbol (
     389              :   const BaseGeneric *param_to_find, SubstitutionArg *argument) const
     390              : {
     391       274556 :   for (const auto &mapping : mappings)
     392              :     {
     393       252104 :       const auto *p = mapping.get_param_ty ();
     394       252104 :       if (p->get_symbol () == param_to_find->get_symbol ())
     395              :         {
     396       193695 :           *argument = mapping;
     397       193695 :           return true;
     398              :         }
     399              :     }
     400              :   return false;
     401              : }
     402              : tl::optional<size_t>
     403            0 : SubstitutionArgumentMappings::find_symbol (const ParamType &param_to_find) const
     404              : {
     405            0 :   auto it = std::find_if (mappings.begin (), mappings.end (),
     406            0 :                           [param_to_find] (const SubstitutionArg &arg) {
     407            0 :                             return arg.get_param_ty ()->get_symbol ()
     408            0 :                                    == param_to_find.get_symbol ();
     409              :                           });
     410            0 :   if (it == mappings.end ())
     411            0 :     return tl::nullopt;
     412            0 :   return std::distance (mappings.begin (), it);
     413              : }
     414              : 
     415              : bool
     416        19393 : SubstitutionArgumentMappings::get_argument_at (size_t index,
     417              :                                                SubstitutionArg *argument)
     418              : {
     419        19393 :   if (index > mappings.size ())
     420              :     return false;
     421              : 
     422        19393 :   *argument = mappings.at (index);
     423        19393 :   return true;
     424              : }
     425              : 
     426              : bool
     427            0 : SubstitutionArgumentMappings::is_concrete () const
     428              : {
     429            0 :   for (auto &mapping : mappings)
     430              :     {
     431            0 :       if (!mapping.is_conrete ())
     432            0 :         return false;
     433              :     }
     434              :   return true;
     435              : }
     436              : 
     437              : location_t
     438     82728347 : SubstitutionArgumentMappings::get_locus () const
     439              : {
     440     82728347 :   return locus;
     441              : }
     442              : 
     443              : size_t
     444        41370 : SubstitutionArgumentMappings::size () const
     445              : {
     446        41370 :   return mappings.size ();
     447              : }
     448              : 
     449              : bool
     450        19047 : SubstitutionArgumentMappings::is_empty () const
     451              : {
     452        19047 :   return size () == 0;
     453              : }
     454              : 
     455              : std::vector<SubstitutionArg> &
     456        77332 : SubstitutionArgumentMappings::get_mappings ()
     457              : {
     458        77332 :   return mappings;
     459              : }
     460              : 
     461              : const std::vector<SubstitutionArg> &
     462    334052714 : SubstitutionArgumentMappings::get_mappings () const
     463              : {
     464    334052714 :   return mappings;
     465              : }
     466              : 
     467              : std::map<std::string, BaseType *> &
     468        20915 : SubstitutionArgumentMappings::get_binding_args ()
     469              : {
     470        20915 :   return binding_args;
     471              : }
     472              : 
     473              : const std::map<std::string, BaseType *> &
     474     82667789 : SubstitutionArgumentMappings::get_binding_args () const
     475              : {
     476     82667789 :   return binding_args;
     477              : }
     478              : 
     479              : std::string
     480            0 : SubstitutionArgumentMappings::as_string () const
     481              : {
     482            0 :   std::string buffer;
     483            0 :   for (auto &mapping : mappings)
     484              :     {
     485            0 :       buffer += mapping.as_string () + ", ";
     486              :     }
     487            0 :   return "<" + buffer + ">";
     488            0 : }
     489              : 
     490              : void
     491        99589 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
     492              :                                               const SubstitutionArg &a) const
     493              : {
     494        99589 :   if (param_subst_cb == nullptr)
     495              :     return;
     496              : 
     497            0 :   param_subst_cb (p, a);
     498              : }
     499              : 
     500              : ParamSubstCb
     501        25681 : SubstitutionArgumentMappings::get_subst_cb () const
     502              : {
     503        25681 :   return param_subst_cb;
     504              : }
     505              : 
     506              : bool
     507        17410 : SubstitutionArgumentMappings::trait_item_mode () const
     508              : {
     509        17410 :   return trait_item_flag;
     510              : }
     511              : 
     512              : // SubstitutionRef
     513              : 
     514     82962306 : SubstitutionRef::SubstitutionRef (
     515              :   std::vector<SubstitutionParamMapping> substitutions,
     516     82962306 :   SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
     517     82962306 :   : substitutions (substitutions), used_arguments (arguments),
     518    165924612 :     region_constraints (region_constraints)
     519     82962306 : {}
     520              : 
     521              : bool
     522       187515 : SubstitutionRef::has_substitutions () const
     523              : {
     524       187515 :   return substitutions.size () > 0;
     525              : }
     526              : 
     527              : std::string
     528      2471976 : SubstitutionRef::subst_as_string () const
     529              : {
     530      2471976 :   std::string buffer;
     531      3640519 :   for (size_t i = 0; i < substitutions.size (); i++)
     532              :     {
     533      1168543 :       const SubstitutionParamMapping &sub = substitutions.at (i);
     534      2337086 :       buffer += sub.as_string ();
     535              : 
     536      1168543 :       if ((i + 1) < substitutions.size ())
     537        77830 :         buffer += ", ";
     538              :     }
     539              : 
     540      3562689 :   return buffer.empty () ? "" : "<" + buffer + ">";
     541      2471976 : }
     542              : 
     543              : bool
     544           98 : SubstitutionRef::supports_associated_bindings () const
     545              : {
     546           98 :   return get_num_associated_bindings () > 0;
     547              : }
     548              : 
     549              : size_t
     550            1 : SubstitutionRef::get_num_associated_bindings () const
     551              : {
     552            1 :   return 0;
     553              : }
     554              : 
     555              : TypeBoundPredicateItem
     556            0 : SubstitutionRef::lookup_associated_type (const std::string &search)
     557              : {
     558            0 :   return TypeBoundPredicateItem::error ();
     559              : }
     560              : 
     561              : size_t
     562        98211 : SubstitutionRef::get_num_substitutions () const
     563              : {
     564        98211 :   return substitutions.size ();
     565              : }
     566              : size_t
     567          135 : SubstitutionRef::get_num_lifetime_params () const
     568              : {
     569          135 :   return used_arguments.get_regions ().size ();
     570              : }
     571              : size_t
     572          436 : SubstitutionRef::get_num_type_params () const
     573              : {
     574          436 :   return get_num_substitutions ();
     575              : }
     576              : 
     577              : std::vector<SubstitutionParamMapping> &
     578       178344 : SubstitutionRef::get_substs ()
     579              : {
     580       178344 :   return substitutions;
     581              : }
     582              : 
     583              : const std::vector<SubstitutionParamMapping> &
     584     82680481 : SubstitutionRef::get_substs () const
     585              : {
     586     82680481 :   return substitutions;
     587              : }
     588              : 
     589              : std::vector<SubstitutionParamMapping>
     590       197517 : SubstitutionRef::clone_substs () const
     591              : {
     592       197517 :   std::vector<SubstitutionParamMapping> clone;
     593       197517 :   clone.reserve (substitutions.size ());
     594              : 
     595       294556 :   for (auto &sub : substitutions)
     596        97039 :     clone.push_back (sub.clone ());
     597              : 
     598       197517 :   return clone;
     599              : }
     600              : 
     601              : void
     602         4730 : SubstitutionRef::override_context ()
     603              : {
     604         9984 :   for (auto &sub : substitutions)
     605              :     {
     606         5254 :       sub.override_context ();
     607              :     }
     608         4730 : }
     609              : 
     610              : bool
     611       162490 : SubstitutionRef::needs_substitution () const
     612              : {
     613       162490 :   return std::any_of (substitutions.begin (), substitutions.end (),
     614              :                       std::mem_fn (
     615       162490 :                         &SubstitutionParamMapping::needs_substitution));
     616              : }
     617              : 
     618              : bool
     619           63 : SubstitutionRef::was_substituted () const
     620              : {
     621           63 :   return !needs_substitution ();
     622              : }
     623              : 
     624              : SubstitutionArgumentMappings &
     625        67098 : SubstitutionRef::get_substitution_arguments ()
     626              : {
     627        67098 :   return used_arguments;
     628              : }
     629              : 
     630              : const SubstitutionArgumentMappings &
     631        43808 : SubstitutionRef::get_substitution_arguments () const
     632              : {
     633        43808 :   return used_arguments;
     634              : }
     635              : 
     636              : size_t
     637         9410 : SubstitutionRef::num_required_substitutions () const
     638              : {
     639         9410 :   size_t n = 0;
     640        21178 :   for (auto &p : substitutions)
     641              :     {
     642        11768 :       if (p.needs_substitution ())
     643        11440 :         n++;
     644              :     }
     645         9410 :   return n;
     646              : }
     647              : 
     648              : size_t
     649        18835 : SubstitutionRef::min_required_substitutions () const
     650              : {
     651        18835 :   size_t n = 0;
     652        42394 :   for (auto &p : substitutions)
     653              :     {
     654        23559 :       if (p.needs_substitution () && !p.param_has_default_ty ())
     655        19746 :         n++;
     656              :     }
     657        18835 :   return n;
     658              : }
     659              : 
     660              : const SubstitutionArgumentMappings &
     661        13260 : SubstitutionRef::get_used_arguments () const
     662              : {
     663        13260 :   return used_arguments;
     664              : }
     665              : 
     666              : tl::optional<SubstitutionArg>
     667          171 : SubstitutionRef::get_arg_at (size_t i) const
     668              : {
     669          171 :   auto param_ty = get_substs ().at (i).get_param_ty ();
     670          171 :   SubstitutionArg arg = SubstitutionArg::error ();
     671          171 :   get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
     672          171 :   if (arg.is_error ())
     673            8 :     return tl::nullopt;
     674          163 :   return arg;
     675              : }
     676              : 
     677              : const RegionConstraints &
     678       184476 : SubstitutionRef::get_region_constraints () const
     679              : {
     680       184476 :   return region_constraints;
     681              : }
     682              : 
     683              : SubstitutionArgumentMappings
     684         9425 : SubstitutionRef::get_mappings_from_generic_args (
     685              :   HIR::GenericArgs &args, const std::vector<Region> &regions)
     686              : {
     687         9425 :   std::map<std::string, BaseType *> binding_arguments;
     688         9425 :   if (args.get_binding_args ().size () > 0)
     689              :     {
     690           98 :       if (supports_associated_bindings ())
     691              :         {
     692           97 :           if (args.get_binding_args ().size () > get_num_associated_bindings ())
     693              :             {
     694            0 :               rich_location r (line_table, args.get_locus ());
     695            0 :               rust_error_at (r,
     696              :                              "generic item takes at most %lu type binding "
     697              :                              "arguments but %lu were supplied",
     698            0 :                              (unsigned long) get_num_associated_bindings (),
     699            0 :                              (unsigned long) args.get_binding_args ().size ());
     700            0 :               return SubstitutionArgumentMappings::error ();
     701            0 :             }
     702              : 
     703          194 :           for (auto &binding : args.get_binding_args ())
     704              :             {
     705           97 :               BaseType *resolved
     706           97 :                 = Resolver::TypeCheckType::Resolve (binding.get_type ());
     707           97 :               if (resolved == nullptr
     708           97 :                   || resolved->get_kind () == TyTy::TypeKind::ERROR)
     709              :                 {
     710            0 :                   return SubstitutionArgumentMappings::error ();
     711              :                 }
     712              : 
     713              :               // resolve to relevant binding
     714           97 :               auto binding_item = lookup_associated_type (
     715           97 :                 binding.get_identifier ().as_string ());
     716           97 :               if (binding_item.is_error ())
     717              :                 {
     718            0 :                   rust_error_at (
     719              :                     binding.get_locus (), "unknown associated type binding: %s",
     720            0 :                     binding.get_identifier ().as_string ().c_str ());
     721            0 :                   return SubstitutionArgumentMappings::error ();
     722              :                 }
     723              : 
     724           97 :               binding_arguments[binding.get_identifier ().as_string ()]
     725           97 :                 = resolved;
     726           97 :             }
     727              :         }
     728              :       else
     729              :         {
     730            1 :           rich_location r (line_table, args.get_locus ());
     731            3 :           for (auto &binding : args.get_binding_args ())
     732            2 :             r.add_range (binding.get_locus ());
     733              : 
     734            1 :           rust_error_at (r, ErrorCode::E0229,
     735              :                          "associated type bindings are not allowed here");
     736            1 :           return SubstitutionArgumentMappings::error ();
     737            1 :         }
     738              :     }
     739              : 
     740              :   // check if we need to use inherited arguments or nothing
     741         9424 :   size_t offs = 0;
     742         9424 :   size_t total_arguments
     743         9424 :     = args.get_type_args ().size () + args.get_const_args ().size ();
     744         9424 :   if (total_arguments < substitutions.size ())
     745              :     {
     746         1713 :       offs = used_arguments.get_mappings ().empty () ? get_outer_param_count ()
     747          570 :                                                      : used_arguments.size ();
     748         1713 :       total_arguments += offs;
     749              :     }
     750              : 
     751         9424 :   if (total_arguments > substitutions.size ())
     752              :     {
     753            4 :       rich_location r (line_table, args.get_locus ());
     754            4 :       if (!substitutions.empty ())
     755              :         {
     756            3 :           const auto &subst = substitutions.front ();
     757            3 :           const auto &generic = subst.get_generic_param ();
     758            3 :           r.add_range (generic.get_locus ());
     759              :         }
     760              : 
     761            8 :       rust_error_at (
     762              :         r,
     763              :         "generic item takes at most %lu type arguments but %lu were supplied",
     764            4 :         (unsigned long) substitutions.size (),
     765            4 :         (unsigned long) args.get_type_args ().size ());
     766            4 :       return SubstitutionArgumentMappings::error ();
     767            4 :     }
     768              : 
     769         9420 :   if (total_arguments < min_required_substitutions ())
     770              :     {
     771            5 :       rich_location r (line_table, args.get_locus ());
     772            5 :       if (!substitutions.empty ())
     773              :         {
     774            5 :           const auto &subst = substitutions.front ();
     775            5 :           const auto &generic = subst.get_generic_param ();
     776            5 :           r.add_range (generic.get_locus ());
     777              :         }
     778              : 
     779           10 :       rust_error_at (
     780              :         r, ErrorCode::E0107,
     781              :         "generic item takes at least %lu type arguments but %lu were supplied",
     782            5 :         (unsigned long) (min_required_substitutions () - offs),
     783            5 :         (unsigned long) args.get_type_args ().size ());
     784            5 :       return SubstitutionArgumentMappings::error ();
     785            5 :     }
     786              : 
     787         9415 :   std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
     788        19330 :   for (auto &arg : args.get_type_args ())
     789              :     {
     790         9919 :       BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
     791         9919 :       if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
     792              :         {
     793            4 :           return SubstitutionArgumentMappings::error ();
     794              :         }
     795              : 
     796         9919 :       const auto &param_mapping = substitutions.at (offs);
     797         9919 :       const auto &generic = param_mapping.get_generic_param ();
     798         9919 :       if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     799              :         {
     800         9916 :           const auto &type_param
     801              :             = static_cast<const HIR::TypeParam &> (generic);
     802         9916 :           if (type_param.from_impl_trait ())
     803              :             {
     804            1 :               rich_location r (line_table, arg->get_locus ());
     805            1 :               r.add_fixit_remove (arg->get_locus ());
     806            1 :               rust_error_at (r, ErrorCode::E0632,
     807              :                              "cannot provide explicit generic arguments when "
     808              :                              "%<impl Trait%> is used in argument position");
     809            1 :               return SubstitutionArgumentMappings::error ();
     810            1 :             }
     811              :         }
     812            3 :       else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     813              :         {
     814            3 :           if (resolved->get_kind () != TyTy::TypeKind::CONST)
     815              :             {
     816            3 :               rich_location r (line_table, arg->get_locus ());
     817            3 :               r.add_fixit_remove (arg->get_locus ());
     818            3 :               rust_error_at (r, ErrorCode::E0747,
     819              :                              "type provided when a constant was expected");
     820            3 :               return SubstitutionArgumentMappings::error ();
     821            3 :             }
     822              :         }
     823              : 
     824         9915 :       mappings.emplace_back (&param_mapping, resolved);
     825         9915 :       offs++;
     826              :     }
     827              : 
     828         9527 :   for (auto &arg : args.get_const_args ())
     829              :     {
     830          117 :       auto &expr = *arg.get_expression ().get ();
     831          117 :       BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
     832          234 :       if (expr_type == nullptr || expr_type->is<ErrorType> ())
     833            1 :         return SubstitutionArgumentMappings::error ();
     834              : 
     835              :       // validate this param is really a const generic
     836          117 :       const auto &param_mapping = substitutions.at (offs);
     837          117 :       const auto &generic = param_mapping.get_generic_param ();
     838          117 :       if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
     839              :         {
     840            0 :           rich_location r (line_table, arg.get_locus ());
     841            0 :           r.add_fixit_remove (expr.get_locus ());
     842            0 :           rust_error_at (r, "invalid position for a const generic argument");
     843            0 :           return SubstitutionArgumentMappings::error ();
     844            0 :         }
     845              : 
     846              :       // get the const generic specified type
     847          117 :       const auto base_generic = param_mapping.get_param_ty ();
     848          117 :       rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
     849          117 :       const auto const_param
     850          117 :         = static_cast<const TyTy::ConstParamType *> (base_generic);
     851          117 :       auto specified_type = const_param->get_specified_type ();
     852              : 
     853              :       // validate this const generic is of the correct type
     854          117 :       TyTy::BaseType *coereced_type = nullptr;
     855          117 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     856              :         {
     857           22 :           auto const_expr_type = expr_type->as_const_type ();
     858           22 :           auto const_value_type = const_expr_type->get_specified_type ();
     859           22 :           coereced_type
     860           22 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     861           22 :                                        TyTy::TyWithLocation (specified_type),
     862              :                                        TyTy::TyWithLocation (const_value_type,
     863           22 :                                                              expr.get_locus ()),
     864              :                                        arg.get_locus ());
     865              :         }
     866              :       else
     867              :         {
     868           95 :           coereced_type
     869           95 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     870           95 :                                        TyTy::TyWithLocation (specified_type),
     871              :                                        TyTy::TyWithLocation (expr_type,
     872           95 :                                                              expr.get_locus ()),
     873              :                                        arg.get_locus ());
     874              :         }
     875              : 
     876          234 :       if (coereced_type == nullptr || coereced_type->is<ErrorType> ())
     877            0 :         return SubstitutionArgumentMappings::error ();
     878              : 
     879          117 :       TyTy::BaseType *const_value_ty = nullptr;
     880          117 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     881           22 :         const_value_ty = expr_type;
     882              :       else
     883              :         {
     884              :           // const fold it if available
     885           95 :           auto ctx = Compile::Context::get ();
     886           95 :           tree folded
     887           95 :             = Compile::HIRCompileBase::query_compile_const_expr (ctx,
     888              :                                                                  coereced_type,
     889              :                                                                  expr);
     890              : 
     891           95 :           if (folded == error_mark_node)
     892              :             {
     893            1 :               rich_location r (line_table, arg.get_locus ());
     894            1 :               r.add_range (expr.get_locus ());
     895            1 :               rust_error_at (r, "failed to resolve const expression");
     896            1 :               return SubstitutionArgumentMappings::error ();
     897            1 :             }
     898              : 
     899              :           // Use a fresh HirId to avoid conflicts with the expr's type
     900           94 :           auto &global_mappings = Analysis::Mappings::get ();
     901           94 :           HirId const_value_id = global_mappings.get_next_hir_id ();
     902           94 :           const_value_ty
     903           94 :             = new TyTy::ConstValueType (folded, coereced_type, const_value_id,
     904           94 :                                         const_value_id, {});
     905              : 
     906              :           // Insert the ConstValueType into the context so it can be looked up
     907           94 :           auto context = Resolver::TypeCheckContext::get ();
     908           94 :           context->insert_type (
     909           94 :             Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0),
     910              :             const_value_ty);
     911              :         }
     912              : 
     913          116 :       mappings.emplace_back (&param_mapping, const_value_ty);
     914          116 :       offs++;
     915              :     }
     916              : 
     917              :   // we must need to fill out defaults
     918         9410 :   size_t left_over
     919         9410 :     = num_required_substitutions () - min_required_substitutions ();
     920         9410 :   if (left_over > 0)
     921              :     {
     922         2718 :       for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
     923              :         {
     924         1140 :           SubstitutionParamMapping &param = substitutions.at (offs);
     925         1140 :           rust_assert (param.param_has_default_ty ());
     926              : 
     927         1140 :           BaseType *resolved = param.get_default_ty ();
     928         1140 :           if (resolved->get_kind () == TypeKind::ERROR)
     929            0 :             return SubstitutionArgumentMappings::error ();
     930              : 
     931              :           // this resolved default might already contain default parameters
     932         1140 :           if (!resolved->is_concrete ())
     933              :             {
     934         1118 :               SubstitutionArgumentMappings intermediate (
     935              :                 mappings, binding_arguments,
     936         1118 :                 {used_arguments.get_regions ().size ()}, args.get_locus ());
     937         1118 :               resolved = Resolver::SubstMapperInternal::Resolve (resolved,
     938              :                                                                  intermediate);
     939              : 
     940         1118 :               if (resolved->get_kind () == TypeKind::ERROR)
     941            0 :                 return SubstitutionArgumentMappings::error ();
     942         1118 :             }
     943              : 
     944         1140 :           mappings.emplace_back (&param, resolved);
     945              :         }
     946              :     }
     947              : 
     948         9410 :   return {mappings, binding_arguments,
     949        18820 :           RegionParamList::from_subst (used_arguments.get_regions ().size (),
     950              :                                        regions),
     951        28230 :           args.get_locus ()};
     952         9415 : }
     953              : 
     954              : BaseType *
     955         7407 : SubstitutionRef::infer_substitions (location_t locus)
     956              : {
     957         7407 :   std::vector<SubstitutionArg> args;
     958         7407 :   std::map<std::string, BaseType *> argument_mappings;
     959        16322 :   for (auto &p : get_substs ())
     960              :     {
     961         8915 :       if (p.needs_substitution ())
     962              :         {
     963         8871 :           const HIR::GenericParam &generic = p.get_generic_param ();
     964         8871 :           const std::string &symbol = p.get_param_ty ()->get_symbol ();
     965         8871 :           auto it = argument_mappings.find (symbol);
     966         8871 :           bool have_mapping = it != argument_mappings.end ();
     967              : 
     968         8871 :           if (have_mapping)
     969              :             {
     970          121 :               args.emplace_back (&p, it->second);
     971              :             }
     972         8750 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     973              :             {
     974         8731 :               TyVar infer_var = TyVar::get_implicit_infer_var (locus);
     975         8731 :               args.emplace_back (&p, infer_var.get_tyty ());
     976         8731 :               argument_mappings[symbol] = infer_var.get_tyty ();
     977              :             }
     978           19 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     979              :             {
     980           19 :               TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
     981           19 :               args.emplace_back (&p, infer_var.get_tyty ());
     982           19 :               argument_mappings[symbol] = infer_var.get_tyty ();
     983              :             }
     984         8871 :         }
     985              :       else
     986              :         {
     987           44 :           args.emplace_back (&p, p.get_param_ty ()->resolve ());
     988              :         }
     989              :     }
     990              : 
     991              :   // FIXME do we need to add inference variables to all the possible bindings?
     992              :   // it might just lead to inference variable hell not 100% sure if rustc does
     993              :   // this i think the language might needs this to be explicitly set
     994              : 
     995         7407 :   SubstitutionArgumentMappings infer_arguments (std::move (args),
     996              :                                                 {} /* binding_arguments */,
     997              :                                                 used_arguments.get_regions (),
     998         7407 :                                                 locus);
     999         7407 :   return handle_substitions (infer_arguments);
    1000         7407 : }
    1001              : 
    1002              : SubstitutionArgumentMappings
    1003        17398 : SubstitutionRef::adjust_mappings_for_this (
    1004              :   SubstitutionArgumentMappings &mappings, bool trait_mode)
    1005              : {
    1006        17398 :   std::vector<SubstitutionArg> resolved_mappings;
    1007        39088 :   for (size_t i = 0; i < substitutions.size (); i++)
    1008              :     {
    1009        21690 :       auto &subst = substitutions.at (i);
    1010              : 
    1011        21690 :       SubstitutionArg arg = SubstitutionArg::error ();
    1012        21690 :       if (mappings.size () == substitutions.size ())
    1013              :         {
    1014        19393 :           mappings.get_argument_at (i, &arg);
    1015              :         }
    1016              :       else
    1017              :         {
    1018         2297 :           if (subst.needs_substitution ())
    1019              :             {
    1020              :               // get from passed in mappings
    1021         2207 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
    1022              :             }
    1023              :           else
    1024              :             {
    1025              :               // we should already have this somewhere
    1026           90 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
    1027              :                                                       &arg);
    1028              :             }
    1029              :         }
    1030              : 
    1031        21690 :       bool ok = !arg.is_error ();
    1032        21690 :       if (ok || (trait_mode && i == 0))
    1033        21189 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
    1034              :     }
    1035              : 
    1036        17398 :   if (resolved_mappings.empty ())
    1037           12 :     return SubstitutionArgumentMappings::error ();
    1038              : 
    1039        17386 :   return SubstitutionArgumentMappings (resolved_mappings,
    1040        17386 :                                        mappings.get_binding_args (),
    1041              :                                        mappings.get_regions (),
    1042              :                                        mappings.get_locus (),
    1043        17386 :                                        mappings.get_subst_cb (),
    1044        34772 :                                        mappings.trait_item_mode ());
    1045        17398 : }
    1046              : 
    1047              : bool
    1048            0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
    1049              : {
    1050            0 :   std::vector<SubstitutionArg> resolved_mappings;
    1051            0 :   for (size_t i = 0; i < substitutions.size (); i++)
    1052              :     {
    1053            0 :       auto &subst = substitutions.at (i);
    1054              : 
    1055            0 :       SubstitutionArg arg = SubstitutionArg::error ();
    1056            0 :       if (mappings.size () == substitutions.size ())
    1057              :         {
    1058            0 :           mappings.get_argument_at (i, &arg);
    1059              :         }
    1060              :       else
    1061              :         {
    1062            0 :           if (subst.needs_substitution ())
    1063              :             {
    1064              :               // get from passed in mappings
    1065            0 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
    1066              :             }
    1067              :           else
    1068              :             {
    1069              :               // we should already have this somewhere
    1070            0 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
    1071              :                                                       &arg);
    1072              :             }
    1073              :         }
    1074              : 
    1075            0 :       bool ok = !arg.is_error ();
    1076            0 :       if (ok)
    1077            0 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
    1078              :     }
    1079              : 
    1080            0 :   return !resolved_mappings.empty ();
    1081            0 : }
    1082              : 
    1083              : // this function assumes that the mappings being passed are for the same type as
    1084              : // this new substitution reference so ordering matters here
    1085              : SubstitutionArgumentMappings
    1086           63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
    1087              :   SubstitutionArgumentMappings &mappings) const
    1088              : {
    1089           63 :   std::vector<SubstitutionArg> resolved_mappings;
    1090              : 
    1091           63 :   rust_assert (mappings.size () == get_num_substitutions ());
    1092          126 :   for (size_t i = 0; i < get_num_substitutions (); i++)
    1093              :     {
    1094           63 :       const SubstitutionParamMapping &param_mapping = substitutions.at (i);
    1095           63 :       SubstitutionArg &arg = mappings.get_mappings ().at (i);
    1096              : 
    1097           63 :       if (param_mapping.needs_substitution ())
    1098           63 :         resolved_mappings.emplace_back (&param_mapping, arg.get_tyty ());
    1099              :     }
    1100              : 
    1101           63 :   return SubstitutionArgumentMappings (resolved_mappings,
    1102           63 :                                        mappings.get_binding_args (),
    1103              :                                        mappings.get_regions (),
    1104          126 :                                        mappings.get_locus ());
    1105           63 : }
    1106              : 
    1107              : bool
    1108        17040 : SubstitutionRef::monomorphize ()
    1109              : {
    1110        27466 :   for (const auto &subst : get_substs ())
    1111              :     {
    1112        10426 :       const auto pty = subst.get_param_ty ();
    1113        10426 :       if (!pty->can_resolve ())
    1114          100 :         continue;
    1115              : 
    1116        10326 :       TyTy::BaseType *binding = pty->resolve ();
    1117        10326 :       if (binding->get_kind () == TyTy::TypeKind::PARAM)
    1118         2274 :         continue;
    1119              : 
    1120              :       // For each where-clause bound on this fn-substitution param, find the
    1121              :       // impl block that satisfies the bound for binding and unify
    1122              :       // its signature against binding + bound. This pins inference
    1123              :       // variables that should be constrained
    1124              :       //
    1125              :       //   fn into_iter<I: Iterator> with binding = Range<{integer}>
    1126              :       //
    1127              :       // the only matching
    1128              :       //
    1129              :       //   <A: Step> Iterator for Range<A>
    1130              :       //
    1131              :       // Step for usize impl together force {integer} = usize instead of
    1132              :       // letting it default.
    1133        17216 :       for (const auto &bound : pty->get_specified_bounds ())
    1134              :         {
    1135         9164 :           bool ambigious = false;
    1136         9164 :           auto associated
    1137         9164 :             = Resolver::lookup_associated_impl_block (bound, binding,
    1138              :                                                       &ambigious);
    1139         9164 :           if (associated != nullptr)
    1140         1966 :             associated->bind_impl_for_bound (binding, bound, UNKNOWN_LOCATION);
    1141              :         }
    1142              :     }
    1143              : 
    1144        17040 :   return true;
    1145              : }
    1146              : 
    1147              : } // namespace TyTy
    1148              : } // 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.