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 % 535 466
Test Date: 2026-10-03 16:17:38 Functions: 87.0 % 77 67
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      4883928 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
      36              :                                                     BaseGeneric *param)
      37      4883928 :   : generic (generic), param (param)
      38      4883928 : {}
      39              : 
      40      6116120 : SubstitutionParamMapping::SubstitutionParamMapping (
      41              :   const SubstitutionParamMapping &other)
      42      6116120 :   : generic (other.generic), param (other.param)
      43      6116120 : {}
      44              : 
      45              : std::string
      46        31432 : SubstitutionParamMapping::as_string () const
      47              : {
      48        31432 :   if (param == nullptr)
      49            0 :     return "nullptr";
      50              : 
      51        31432 :   return param->get_name ();
      52              : }
      53              : 
      54              : SubstitutionParamMapping
      55      4870140 : SubstitutionParamMapping::clone () const
      56              : {
      57      4870140 :   return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
      58      4870140 :                                               param->clone ()));
      59              : }
      60              : 
      61              : BaseGeneric *
      62       262122 : SubstitutionParamMapping::get_param_ty ()
      63              : {
      64       262122 :   return param;
      65              : }
      66              : 
      67              : const BaseGeneric *
      68      4395709 : SubstitutionParamMapping::get_param_ty () const
      69              : {
      70      4395709 :   return param;
      71              : }
      72              : 
      73              : HIR::GenericParam &
      74        18732 : SubstitutionParamMapping::get_generic_param ()
      75              : {
      76        18732 :   return generic;
      77              : }
      78              : 
      79              : const HIR::GenericParam &
      80        11760 : SubstitutionParamMapping::get_generic_param () const
      81              : {
      82        11760 :   return generic;
      83              : }
      84              : 
      85              : bool
      86        80232 : SubstitutionParamMapping::needs_substitution () const
      87              : {
      88        80232 :   return !(get_param_ty ()->is_concrete ());
      89              : }
      90              : 
      91              : Identifier
      92         2556 : SubstitutionParamMapping::get_type_representation () const
      93              : {
      94         5112 :   return param->get_symbol ();
      95              : }
      96              : 
      97              : location_t
      98         1118 : SubstitutionParamMapping::get_param_locus () const
      99              : {
     100         1118 :   return generic.get_locus ();
     101              : }
     102              : 
     103              : bool
     104        28209 : SubstitutionParamMapping::param_has_default_ty () const
     105              : {
     106        28209 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     107              :     {
     108        27958 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     109        27958 :       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         1417 : SubstitutionParamMapping::get_default_ty () const
     120              : {
     121         1417 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     122              :     {
     123         1412 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     124         1412 :       TyVar var (type_param.get_type_mappings ().get_hirid ());
     125         1412 :       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        51857 : SubstitutionParamMapping::fill_param_ty (
     150              :   SubstitutionArgumentMappings &subst_mappings, location_t locus,
     151              :   bool needs_bounds_check)
     152              : {
     153        51857 :   SubstitutionArg arg = SubstitutionArg::error ();
     154        51857 :   bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
     155        51857 :   if (!ok)
     156              :     return true;
     157              : 
     158        51857 :   TyTy::BaseType &type = *arg.get_tyty ();
     159        51857 :   std::pair<HirId, HirId> subst_key (param->get_ref (), type.get_ref ());
     160        53723 :   static std::vector<std::pair<HirId, HirId>> active_substs;
     161        51857 :   bool is_recursive_subst
     162        51857 :     = Resolver::ScopedPush<std::pair<HirId, HirId>>::contains (active_substs,
     163              :                                                                subst_key);
     164        51857 :   bool skip_recursive_bounds
     165        51857 :     = 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        51815 :   Resolver::ScopedPush<std::pair<HirId, HirId>> guard (active_substs, subst_key,
     186        51815 :                                                        !is_recursive_subst);
     187              : 
     188        51815 :   if (type.get_kind () == TyTy::TypeKind::INFER)
     189              :     {
     190        14737 :       type.inherit_bounds (*param);
     191              :     }
     192              : 
     193        51815 :   if (type.get_kind () == TypeKind::PARAM)
     194              :     {
     195        11808 :       param = static_cast<BaseGeneric *> (type.clone ());
     196              :     }
     197        40007 :   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        39803 :   else if (param->get_kind () == TypeKind::PARAM)
     207              :     {
     208        39803 :       auto &p = *static_cast<TyTy::ParamType *> (param);
     209              : 
     210              :       // check the substitution is compatible with bounds
     211        39803 :       rust_debug_loc (locus,
     212              :                       "fill_param_ty bounds_compatible: param %s type %s",
     213              :                       param->get_name ().c_str (), type.get_name ().c_str ());
     214        39803 :       if (!skip_recursive_bounds && needs_bounds_check
     215        39803 :           && !p.is_implicit_self_trait ())
     216              :         {
     217        19055 :           if (!param->bounds_compatible (type, locus, true))
     218              :             return false;
     219              :         }
     220              : 
     221              :       // recursively pass this down to all HRTB's
     222        39793 :       if (!skip_recursive_bounds)
     223        87076 :         for (auto &bound : param->get_specified_bounds ())
     224        47283 :           bound.handle_substitions (subst_mappings);
     225              : 
     226        39793 :       param->set_ty_ref (type.get_ref ());
     227              :     }
     228              : 
     229              :   return true;
     230        51857 : }
     231              : 
     232              : void
     233         5847 : SubstitutionParamMapping::override_context ()
     234              : {
     235         5847 :   if (!param->can_resolve ())
     236              :     return;
     237              : 
     238         5833 :   auto &mappings = Analysis::Mappings::get ();
     239         5833 :   auto context = Resolver::TypeCheckContext::get ();
     240              : 
     241         5833 :   context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
     242              :                                                UNKNOWN_NODEID,
     243         5833 :                                                param->get_ref (),
     244         5833 :                                                UNKNOWN_LOCAL_DEFID),
     245         5833 :                         param->resolve ());
     246              : }
     247              : 
     248      4497825 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
     249              :                                   BaseType *argument)
     250      4497825 :   : param (param), argument (argument)
     251              : {
     252      4497825 :   if (param != nullptr)
     253      4270739 :     original_param = param->get_param_ty ();
     254      4497825 : }
     255              : 
     256      9106387 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
     257      9106387 :   : param (other.param), original_param (other.original_param),
     258      9106387 :     argument (other.argument)
     259      9106387 : {}
     260              : 
     261              : SubstitutionArg &
     262       217538 : SubstitutionArg::operator= (const SubstitutionArg &other)
     263              : {
     264       217538 :   param = other.param;
     265       217538 :   argument = other.argument;
     266       217538 :   original_param = other.original_param;
     267              : 
     268       217538 :   return *this;
     269              : }
     270              : 
     271              : BaseType *
     272      5432150 : SubstitutionArg::get_tyty () const
     273              : {
     274      5432150 :   return argument;
     275              : }
     276              : 
     277              : const SubstitutionParamMapping *
     278            0 : SubstitutionArg::get_param_mapping () const
     279              : {
     280            0 :   return param;
     281              : }
     282              : 
     283              : const BaseGeneric *
     284       250489 : SubstitutionArg::get_param_ty () const
     285              : {
     286       250489 :   return original_param;
     287              : }
     288              : 
     289              : SubstitutionArg
     290       227086 : SubstitutionArg::error ()
     291              : {
     292       227086 :   return SubstitutionArg (nullptr, nullptr);
     293              : }
     294              : 
     295              : bool
     296        79090 : SubstitutionArg::is_error () const
     297              : {
     298        79090 :   return param == nullptr || argument == nullptr;
     299              : }
     300              : 
     301              : bool
     302            0 : SubstitutionArg::is_conrete () const
     303              : {
     304            0 :   if (argument == nullptr)
     305              :     return false;
     306              : 
     307            0 :   if (argument->get_kind () == TyTy::TypeKind::PARAM)
     308              :     return false;
     309              : 
     310            0 :   return argument->is_concrete ();
     311              : }
     312              : 
     313              : std::string
     314            0 : SubstitutionArg::as_string () const
     315              : {
     316            0 :   return original_param->as_string ()
     317            0 :          + (argument != nullptr ? ":" + argument->as_string () : "");
     318              : }
     319              : 
     320              : const RegionParamList &
     321      3665939 : SubstitutionArgumentMappings::get_regions () const
     322              : {
     323      3665939 :   return regions;
     324              : }
     325              : 
     326              : RegionParamList &
     327         2156 : SubstitutionArgumentMappings::get_mut_regions ()
     328              : {
     329         2156 :   return regions;
     330              : }
     331              : 
     332              : // SubstitutionArgumentMappings
     333              : 
     334      7506687 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     335              :   std::vector<SubstitutionArg> mappings,
     336              :   std::map<std::string, BaseType *> binding_args, RegionParamList regions,
     337              :   location_t locus, bool trait_item_flag, bool error_flag,
     338              :   std::map<std::string, BaseType *> constraint_args)
     339      7506687 :   : mappings (std::move (mappings)), binding_args (binding_args),
     340      7506687 :     constraint_args (constraint_args), regions (regions), locus (locus),
     341      7506687 :     trait_item_flag (trait_item_flag), error_flag (error_flag)
     342      7506687 : {}
     343              : 
     344      4106175 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     345              :   const SubstitutionArgumentMappings &other)
     346      4106175 :   : mappings (other.mappings), binding_args (other.binding_args),
     347      4106175 :     constraint_args (other.constraint_args), regions (other.regions),
     348      4106175 :     locus (other.locus), trait_item_flag (other.trait_item_flag),
     349      4106175 :     error_flag (other.error_flag)
     350      4106175 : {}
     351              : 
     352              : SubstitutionArgumentMappings &
     353        50907 : SubstitutionArgumentMappings::operator= (
     354              :   const SubstitutionArgumentMappings &other)
     355              : {
     356        50907 :   mappings = other.mappings;
     357        50907 :   binding_args = other.binding_args;
     358        50907 :   constraint_args = other.constraint_args;
     359        50907 :   regions = other.regions;
     360        50907 :   locus = other.locus;
     361        50907 :   trait_item_flag = other.trait_item_flag;
     362        50907 :   error_flag = other.error_flag;
     363              : 
     364        50907 :   return *this;
     365              : }
     366              : 
     367              : SubstitutionArgumentMappings
     368        44670 : SubstitutionArgumentMappings::error ()
     369              : {
     370        44670 :   return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, false, true);
     371              : }
     372              : 
     373              : SubstitutionArgumentMappings
     374      3798155 : SubstitutionArgumentMappings::empty (size_t num_regions)
     375              : {
     376      3798155 :   return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
     377      3798155 :                                        false, false);
     378              : }
     379              : 
     380              : bool
     381        41637 : SubstitutionArgumentMappings::is_error () const
     382              : {
     383        41637 :   return error_flag;
     384              : }
     385              : 
     386              : bool
     387       209025 : SubstitutionArgumentMappings::get_argument_for_symbol (
     388              :   const BaseGeneric *param_to_find, SubstitutionArg *argument) const
     389              : {
     390       269187 :   for (const auto &mapping : mappings)
     391              :     {
     392       249565 :       const auto *p = mapping.get_param_ty ();
     393       249565 :       if (p->get_symbol () == param_to_find->get_symbol ())
     394              :         {
     395       189403 :           *argument = mapping;
     396       189403 :           return true;
     397              :         }
     398              :     }
     399              :   return false;
     400              : }
     401              : tl::optional<size_t>
     402            0 : SubstitutionArgumentMappings::find_symbol (const ParamType &param_to_find) const
     403              : {
     404            0 :   auto it = std::find_if (mappings.begin (), mappings.end (),
     405            0 :                           [param_to_find] (const SubstitutionArg &arg) {
     406            0 :                             return arg.get_param_ty ()->get_symbol ()
     407            0 :                                    == param_to_find.get_symbol ();
     408              :                           });
     409            0 :   if (it == mappings.end ())
     410            0 :     return tl::nullopt;
     411            0 :   return std::distance (mappings.begin (), it);
     412              : }
     413              : 
     414              : bool
     415        18061 : SubstitutionArgumentMappings::get_argument_at (size_t index,
     416              :                                                SubstitutionArg *argument)
     417              : {
     418        18061 :   if (index > mappings.size ())
     419              :     return false;
     420              : 
     421        18061 :   *argument = mappings.at (index);
     422        18061 :   return true;
     423              : }
     424              : 
     425              : bool
     426            0 : SubstitutionArgumentMappings::is_concrete () const
     427              : {
     428            0 :   for (auto &mapping : mappings)
     429              :     {
     430            0 :       if (!mapping.is_conrete ())
     431            0 :         return false;
     432              :     }
     433              :   return true;
     434              : }
     435              : 
     436              : location_t
     437      3683238 : SubstitutionArgumentMappings::get_locus () const
     438              : {
     439      3683238 :   return locus;
     440              : }
     441              : 
     442              : size_t
     443        42159 : SubstitutionArgumentMappings::size () const
     444              : {
     445        42159 :   return mappings.size ();
     446              : }
     447              : 
     448              : bool
     449        21052 : SubstitutionArgumentMappings::is_empty () const
     450              : {
     451        21052 :   return size () == 0;
     452              : }
     453              : 
     454              : std::vector<SubstitutionArg> &
     455       102299 : SubstitutionArgumentMappings::get_mappings ()
     456              : {
     457       102299 :   return mappings;
     458              : }
     459              : 
     460              : const std::vector<SubstitutionArg> &
     461      3619425 : SubstitutionArgumentMappings::get_mappings () const
     462              : {
     463      3619425 :   return mappings;
     464              : }
     465              : 
     466              : std::map<std::string, BaseType *> &
     467        17187 : SubstitutionArgumentMappings::get_binding_args ()
     468              : {
     469        17187 :   return binding_args;
     470              : }
     471              : 
     472              : const std::map<std::string, BaseType *> &
     473      3613169 : SubstitutionArgumentMappings::get_binding_args () const
     474              : {
     475      3613169 :   return binding_args;
     476              : }
     477              : 
     478              : const std::map<std::string, BaseType *> &
     479      3623410 : SubstitutionArgumentMappings::get_constraint_args () const
     480              : {
     481      3623410 :   return constraint_args;
     482              : }
     483              : 
     484              : std::string
     485            0 : SubstitutionArgumentMappings::as_string () const
     486              : {
     487            0 :   std::string buffer;
     488            0 :   for (auto &mapping : mappings)
     489              :     {
     490            0 :       buffer += mapping.as_string () + ", ";
     491              :     }
     492            0 :   return "<" + buffer + ">";
     493            0 : }
     494              : 
     495              : bool
     496        15833 : SubstitutionArgumentMappings::trait_item_mode () const
     497              : {
     498        15833 :   return trait_item_flag;
     499              : }
     500              : 
     501              : // SubstitutionRef
     502              : 
     503      3853916 : SubstitutionRef::SubstitutionRef (
     504              :   std::vector<SubstitutionParamMapping> substitutions,
     505              :   SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
     506      3853916 :   : substitutions (substitutions), used_arguments (arguments),
     507      7707832 :     region_constraints (region_constraints)
     508      3853916 : {}
     509              : 
     510              : bool
     511       187034 : SubstitutionRef::has_substitutions () const
     512              : {
     513       187034 :   return substitutions.size () > 0;
     514              : }
     515              : 
     516              : std::string
     517        98228 : SubstitutionRef::subst_as_string () const
     518              : {
     519        98228 :   std::string buffer;
     520       129660 :   for (size_t i = 0; i < substitutions.size (); i++)
     521              :     {
     522        31432 :       const SubstitutionParamMapping &sub = substitutions.at (i);
     523        62864 :       buffer += sub.as_string ();
     524              : 
     525        31432 :       if ((i + 1) < substitutions.size ())
     526         2783 :         buffer += ", ";
     527              :     }
     528              : 
     529       126877 :   return buffer.empty () ? "" : "<" + buffer + ">";
     530        98228 : }
     531              : 
     532              : bool
     533          119 : SubstitutionRef::supports_associated_bindings () const
     534              : {
     535          119 :   return get_num_associated_bindings () > 0;
     536              : }
     537              : 
     538              : size_t
     539            1 : SubstitutionRef::get_num_associated_bindings () const
     540              : {
     541            1 :   return 0;
     542              : }
     543              : 
     544              : TypeBoundPredicateItem
     545            0 : SubstitutionRef::lookup_associated_type (const std::string &search)
     546              : {
     547            0 :   return TypeBoundPredicateItem::error ();
     548              : }
     549              : 
     550              : size_t
     551        78405 : SubstitutionRef::get_num_substitutions () const
     552              : {
     553        78405 :   return substitutions.size ();
     554              : }
     555              : size_t
     556          241 : SubstitutionRef::get_num_lifetime_params () const
     557              : {
     558          241 :   return used_arguments.get_regions ().size ();
     559              : }
     560              : size_t
     561          506 : SubstitutionRef::get_num_type_params () const
     562              : {
     563          506 :   return get_num_substitutions ();
     564              : }
     565              : 
     566              : std::vector<SubstitutionParamMapping> &
     567       188474 : SubstitutionRef::get_substs ()
     568              : {
     569       188474 :   return substitutions;
     570              : }
     571              : 
     572              : const std::vector<SubstitutionParamMapping> &
     573      3637460 : SubstitutionRef::get_substs () const
     574              : {
     575      3637460 :   return substitutions;
     576              : }
     577              : 
     578              : std::vector<SubstitutionParamMapping>
     579       133007 : SubstitutionRef::clone_substs () const
     580              : {
     581       133007 :   std::vector<SubstitutionParamMapping> clone;
     582       133007 :   clone.reserve (substitutions.size ());
     583              : 
     584       212035 :   for (auto &sub : substitutions)
     585        79028 :     clone.push_back (sub.clone ());
     586              : 
     587       133007 :   return clone;
     588              : }
     589              : 
     590              : void
     591         5272 : SubstitutionRef::override_context ()
     592              : {
     593        11119 :   for (auto &sub : substitutions)
     594              :     {
     595         5847 :       sub.override_context ();
     596              :     }
     597         5272 : }
     598              : 
     599              : bool
     600        78735 : SubstitutionRef::needs_substitution () const
     601              : {
     602        78735 :   return std::any_of (substitutions.begin (), substitutions.end (),
     603              :                       std::mem_fn (
     604        78735 :                         &SubstitutionParamMapping::needs_substitution));
     605              : }
     606              : 
     607              : bool
     608           63 : SubstitutionRef::was_substituted () const
     609              : {
     610           63 :   return !needs_substitution ();
     611              : }
     612              : 
     613              : SubstitutionArgumentMappings &
     614        57245 : SubstitutionRef::get_substitution_arguments ()
     615              : {
     616        57245 :   return used_arguments;
     617              : }
     618              : 
     619              : const SubstitutionArgumentMappings &
     620        33547 : SubstitutionRef::get_substitution_arguments () const
     621              : {
     622        33547 :   return used_arguments;
     623              : }
     624              : 
     625              : size_t
     626        10983 : SubstitutionRef::num_required_substitutions () const
     627              : {
     628        10983 :   size_t n = 0;
     629        24778 :   for (auto &p : substitutions)
     630              :     {
     631        13795 :       if (p.needs_substitution ())
     632        13384 :         n++;
     633              :     }
     634        10983 :   return n;
     635              : }
     636              : 
     637              : size_t
     638        21982 : SubstitutionRef::min_required_substitutions () const
     639              : {
     640        21982 :   size_t n = 0;
     641        49596 :   for (auto &p : substitutions)
     642              :     {
     643        27614 :       if (p.needs_substitution () && !p.param_has_default_ty ())
     644        23017 :         n++;
     645              :     }
     646        21982 :   return n;
     647              : }
     648              : 
     649              : const SubstitutionArgumentMappings &
     650        15335 : SubstitutionRef::get_used_arguments () const
     651              : {
     652        15335 :   return used_arguments;
     653              : }
     654              : 
     655              : tl::optional<SubstitutionArg>
     656          192 : SubstitutionRef::get_arg_at (size_t i) const
     657              : {
     658          192 :   auto param_ty = get_substs ().at (i).get_param_ty ();
     659          192 :   SubstitutionArg arg = SubstitutionArg::error ();
     660          192 :   get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
     661          192 :   if (arg.is_error ())
     662           10 :     return tl::nullopt;
     663          182 :   return arg;
     664              : }
     665              : 
     666              : const RegionConstraints &
     667       121597 : SubstitutionRef::get_region_constraints () const
     668              : {
     669       121597 :   return region_constraints;
     670              : }
     671              : 
     672              : SubstitutionArgumentMappings
     673        10999 : SubstitutionRef::get_mappings_from_generic_args (
     674              :   HIR::GenericArgs &args, const std::vector<Region> &regions)
     675              : {
     676        10999 :   std::map<std::string, BaseType *> binding_arguments;
     677        10999 :   std::map<std::string, BaseType *> constraint_arguments;
     678        10999 :   if (args.get_binding_args ().size () > 0)
     679              :     {
     680          119 :       if (supports_associated_bindings ())
     681              :         {
     682          118 :           if (args.get_binding_args ().size () > get_num_associated_bindings ())
     683              :             {
     684            0 :               rich_location r (line_table, args.get_locus ());
     685            0 :               rust_error_at (r,
     686              :                              "generic item takes at most %lu type binding "
     687              :                              "arguments but %lu were supplied",
     688            0 :                              (unsigned long) get_num_associated_bindings (),
     689            0 :                              (unsigned long) args.get_binding_args ().size ());
     690            0 :               return SubstitutionArgumentMappings::error ();
     691            0 :             }
     692              : 
     693          237 :           for (auto &binding : args.get_binding_args ())
     694              :             {
     695          119 :               BaseType *resolved
     696          119 :                 = Resolver::TypeCheckType::Resolve (binding.get_type ());
     697          119 :               if (resolved == nullptr
     698          119 :                   || resolved->get_kind () == TyTy::TypeKind::ERROR)
     699              :                 {
     700            0 :                   return SubstitutionArgumentMappings::error ();
     701              :                 }
     702              : 
     703              :               // resolve to relevant binding
     704          119 :               auto binding_item = lookup_associated_type (
     705          119 :                 binding.get_identifier ().as_string ());
     706          119 :               if (binding_item.is_error ())
     707              :                 {
     708            0 :                   rust_error_at (
     709              :                     binding.get_locus (), "unknown associated type binding: %s",
     710            0 :                     binding.get_identifier ().as_string ().c_str ());
     711            0 :                   return SubstitutionArgumentMappings::error ();
     712              :                 }
     713              : 
     714          119 :               if (binding.get_kind ()
     715              :                   == HIR::GenericArgsBinding::Kind::Constraint)
     716            8 :                 constraint_arguments[binding.get_identifier ().as_string ()]
     717            8 :                   = resolved;
     718              :               else
     719          111 :                 binding_arguments[binding.get_identifier ().as_string ()]
     720          111 :                   = resolved;
     721          119 :             }
     722              :         }
     723              :       else
     724              :         {
     725            1 :           rich_location r (line_table, args.get_locus ());
     726            3 :           for (auto &binding : args.get_binding_args ())
     727            2 :             r.add_range (binding.get_locus ());
     728              : 
     729            1 :           rust_error_at (r, ErrorCode::E0229,
     730              :                          "associated type bindings are not allowed here");
     731            1 :           return SubstitutionArgumentMappings::error ();
     732            1 :         }
     733              :     }
     734              : 
     735              :   // check if we need to use inherited arguments or nothing
     736        10998 :   size_t offs = 0;
     737        10998 :   size_t total_arguments
     738        10998 :     = args.get_type_args ().size () + args.get_const_args ().size ();
     739        10998 :   if (total_arguments < substitutions.size ())
     740              :     {
     741         2024 :       offs = used_arguments.get_mappings ().empty () ? get_outer_param_count ()
     742          604 :                                                      : used_arguments.size ();
     743         2024 :       total_arguments += offs;
     744              :     }
     745              : 
     746        10998 :   if (total_arguments > substitutions.size ())
     747              :     {
     748            4 :       rich_location r (line_table, args.get_locus ());
     749            4 :       if (!substitutions.empty ())
     750              :         {
     751            3 :           const auto &subst = substitutions.front ();
     752            3 :           const auto &generic = subst.get_generic_param ();
     753            3 :           r.add_range (generic.get_locus ());
     754              :         }
     755              : 
     756            8 :       rust_error_at (
     757              :         r,
     758              :         "generic item takes at most %lu type arguments but %lu were supplied",
     759            4 :         (unsigned long) substitutions.size (),
     760            4 :         (unsigned long) args.get_type_args ().size ());
     761            4 :       return SubstitutionArgumentMappings::error ();
     762            4 :     }
     763              : 
     764        10994 :   if (total_arguments < min_required_substitutions ())
     765              :     {
     766            5 :       rich_location r (line_table, args.get_locus ());
     767            5 :       if (!substitutions.empty ())
     768              :         {
     769            5 :           const auto &subst = substitutions.front ();
     770            5 :           const auto &generic = subst.get_generic_param ();
     771            5 :           r.add_range (generic.get_locus ());
     772              :         }
     773              : 
     774           10 :       rust_error_at (
     775              :         r, ErrorCode::E0107,
     776              :         "generic item takes at least %lu type arguments but %lu were supplied",
     777            5 :         (unsigned long) (min_required_substitutions () - offs),
     778            5 :         (unsigned long) args.get_type_args ().size ());
     779            5 :       return SubstitutionArgumentMappings::error ();
     780            5 :     }
     781              : 
     782        10989 :   std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
     783        22620 :   for (auto &arg : args.get_type_args ())
     784              :     {
     785        11636 :       BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
     786        11635 :       if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
     787              :         {
     788            4 :           return SubstitutionArgumentMappings::error ();
     789              :         }
     790              : 
     791        11635 :       const auto &param_mapping = substitutions.at (offs);
     792        11635 :       const auto &generic = param_mapping.get_generic_param ();
     793        11635 :       if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     794              :         {
     795        11632 :           const auto &type_param
     796              :             = static_cast<const HIR::TypeParam &> (generic);
     797        11632 :           if (type_param.from_impl_trait ())
     798              :             {
     799            1 :               rich_location r (line_table, arg->get_locus ());
     800            1 :               r.add_fixit_remove (arg->get_locus ());
     801            1 :               rust_error_at (r, ErrorCode::E0632,
     802              :                              "cannot provide explicit generic arguments when "
     803              :                              "%<impl Trait%> is used in argument position");
     804            1 :               return SubstitutionArgumentMappings::error ();
     805            1 :             }
     806              :         }
     807            3 :       else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     808              :         {
     809            3 :           if (resolved->get_kind () != TyTy::TypeKind::CONST)
     810              :             {
     811            3 :               rich_location r (line_table, arg->get_locus ());
     812            3 :               r.add_fixit_remove (arg->get_locus ());
     813            3 :               rust_error_at (r, ErrorCode::E0747,
     814              :                              "type provided when a constant was expected");
     815            3 :               return SubstitutionArgumentMappings::error ();
     816            3 :             }
     817              :         }
     818              : 
     819        11631 :       mappings.emplace_back (&param_mapping, resolved);
     820        11631 :       offs++;
     821              :     }
     822              : 
     823        11100 :   for (auto &arg : args.get_const_args ())
     824              :     {
     825          117 :       auto &expr = *arg.get_expression ().get ();
     826          117 :       BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
     827          234 :       if (expr_type == nullptr || expr_type->is<ErrorType> ())
     828            1 :         return SubstitutionArgumentMappings::error ();
     829              : 
     830              :       // validate this param is really a const generic
     831          117 :       const auto &param_mapping = substitutions.at (offs);
     832          117 :       const auto &generic = param_mapping.get_generic_param ();
     833          117 :       if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
     834              :         {
     835            0 :           rich_location r (line_table, arg.get_locus ());
     836            0 :           r.add_fixit_remove (expr.get_locus ());
     837            0 :           rust_error_at (r, "invalid position for a const generic argument");
     838            0 :           return SubstitutionArgumentMappings::error ();
     839            0 :         }
     840              : 
     841              :       // get the const generic specified type
     842          117 :       const auto base_generic = param_mapping.get_param_ty ();
     843          117 :       rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
     844          117 :       const auto const_param
     845          117 :         = static_cast<const TyTy::ConstParamType *> (base_generic);
     846          117 :       auto specified_type = const_param->get_specified_type ();
     847              : 
     848              :       // validate this const generic is of the correct type
     849          117 :       TyTy::BaseType *coereced_type = nullptr;
     850          117 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     851              :         {
     852           22 :           auto const_expr_type = expr_type->as_const_type ();
     853           22 :           auto const_value_type = const_expr_type->get_specified_type ();
     854           22 :           coereced_type
     855           22 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     856           22 :                                        TyTy::TyWithLocation (specified_type),
     857              :                                        TyTy::TyWithLocation (const_value_type,
     858           22 :                                                              expr.get_locus ()),
     859              :                                        arg.get_locus ());
     860              :         }
     861              :       else
     862              :         {
     863           95 :           coereced_type
     864           95 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     865           95 :                                        TyTy::TyWithLocation (specified_type),
     866              :                                        TyTy::TyWithLocation (expr_type,
     867           95 :                                                              expr.get_locus ()),
     868              :                                        arg.get_locus ());
     869              :         }
     870              : 
     871          234 :       if (coereced_type == nullptr || coereced_type->is<ErrorType> ())
     872            0 :         return SubstitutionArgumentMappings::error ();
     873              : 
     874          117 :       TyTy::BaseType *const_value_ty = nullptr;
     875          117 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     876           22 :         const_value_ty = expr_type;
     877              :       else
     878              :         {
     879              :           // const fold it if available
     880           95 :           auto ctx = Compile::Context::get ();
     881           95 :           tree folded
     882           95 :             = Compile::HIRCompileBase::query_compile_const_expr (ctx,
     883              :                                                                  coereced_type,
     884              :                                                                  expr);
     885              : 
     886           95 :           if (folded == error_mark_node)
     887              :             {
     888            1 :               rich_location r (line_table, arg.get_locus ());
     889            1 :               r.add_range (expr.get_locus ());
     890            1 :               rust_error_at (r, "failed to resolve const expression");
     891            1 :               return SubstitutionArgumentMappings::error ();
     892            1 :             }
     893              : 
     894              :           // Use a fresh HirId to avoid conflicts with the expr's type
     895           94 :           auto &global_mappings = Analysis::Mappings::get ();
     896           94 :           HirId const_value_id = global_mappings.get_next_hir_id ();
     897           94 :           const_value_ty
     898           94 :             = new TyTy::ConstValueType (folded, coereced_type, const_value_id,
     899           94 :                                         const_value_id, {});
     900              : 
     901              :           // Insert the ConstValueType into the context so it can be looked up
     902           94 :           auto context = Resolver::TypeCheckContext::get ();
     903           94 :           context->insert_type (
     904           94 :             Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0),
     905              :             const_value_ty);
     906              :         }
     907              : 
     908          116 :       mappings.emplace_back (&param_mapping, const_value_ty);
     909          116 :       offs++;
     910              :     }
     911              : 
     912              :   // we must need to fill out defaults
     913        10983 :   size_t left_over
     914        10983 :     = num_required_substitutions () - min_required_substitutions ();
     915        10983 :   if (left_over > 0)
     916              :     {
     917         3304 :       for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
     918              :         {
     919         1417 :           SubstitutionParamMapping &param = substitutions.at (offs);
     920         1417 :           rust_assert (param.param_has_default_ty ());
     921              : 
     922         1417 :           BaseType *resolved = param.get_default_ty ();
     923         1417 :           if (resolved->get_kind () == TypeKind::ERROR)
     924            0 :             return SubstitutionArgumentMappings::error ();
     925              : 
     926              :           // this resolved default might already contain default parameters
     927         1417 :           if (!resolved->is_concrete ())
     928              :             {
     929         1395 :               SubstitutionArgumentMappings intermediate (
     930              :                 mappings, binding_arguments,
     931         1395 :                 {used_arguments.get_regions ().size ()}, args.get_locus ());
     932         1395 :               resolved = Resolver::SubstMapperInternal::Resolve (resolved,
     933              :                                                                  intermediate);
     934              : 
     935         1395 :               if (resolved->get_kind () == TypeKind::ERROR)
     936            0 :                 return SubstitutionArgumentMappings::error ();
     937         1395 :             }
     938              : 
     939         1417 :           mappings.emplace_back (&param, resolved);
     940              :         }
     941              :     }
     942              : 
     943        10983 :   return {mappings,
     944              :           binding_arguments,
     945        21966 :           RegionParamList::from_subst (used_arguments.get_regions ().size (),
     946              :                                        regions),
     947              :           args.get_locus (),
     948              :           false,
     949              :           false,
     950        32949 :           constraint_arguments};
     951        21986 : }
     952              : 
     953              : BaseType *
     954         8163 : SubstitutionRef::infer_substitions (location_t locus)
     955              : {
     956         8163 :   std::vector<SubstitutionArg> args;
     957         8163 :   std::map<std::string, BaseType *> argument_mappings;
     958        17940 :   for (auto &p : get_substs ())
     959              :     {
     960         9777 :       if (p.needs_substitution ())
     961              :         {
     962         9733 :           const HIR::GenericParam &generic = p.get_generic_param ();
     963         9733 :           const std::string &symbol = p.get_param_ty ()->get_symbol ();
     964         9733 :           auto it = argument_mappings.find (symbol);
     965         9733 :           bool have_mapping = it != argument_mappings.end ();
     966              : 
     967         9733 :           if (have_mapping)
     968              :             {
     969          121 :               args.emplace_back (&p, it->second);
     970              :             }
     971         9612 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     972              :             {
     973         9593 :               TyVar infer_var = TyVar::get_implicit_infer_var (locus);
     974         9593 :               args.emplace_back (&p, infer_var.get_tyty ());
     975         9593 :               argument_mappings[symbol] = infer_var.get_tyty ();
     976              :             }
     977           19 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     978              :             {
     979           19 :               TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
     980           19 :               args.emplace_back (&p, infer_var.get_tyty ());
     981           19 :               argument_mappings[symbol] = infer_var.get_tyty ();
     982              :             }
     983         9733 :         }
     984              :       else
     985              :         {
     986           44 :           args.emplace_back (&p, p.get_param_ty ()->resolve ());
     987              :         }
     988              :     }
     989              : 
     990              :   // FIXME do we need to add inference variables to all the possible bindings?
     991              :   // it might just lead to inference variable hell not 100% sure if rustc does
     992              :   // this i think the language might needs this to be explicitly set
     993              : 
     994         8163 :   SubstitutionArgumentMappings infer_arguments (std::move (args),
     995              :                                                 {} /* binding_arguments */,
     996              :                                                 used_arguments.get_regions (),
     997         8163 :                                                 locus);
     998         8163 :   return handle_substitions (infer_arguments);
     999         8163 : }
    1000              : 
    1001              : SubstitutionArgumentMappings
    1002        15821 : SubstitutionRef::adjust_mappings_for_this (
    1003              :   SubstitutionArgumentMappings &mappings, bool trait_mode)
    1004              : {
    1005        15821 :   std::vector<SubstitutionArg> resolved_mappings;
    1006        36254 :   for (size_t i = 0; i < substitutions.size (); i++)
    1007              :     {
    1008        20433 :       auto &subst = substitutions.at (i);
    1009              : 
    1010        20433 :       SubstitutionArg arg = SubstitutionArg::error ();
    1011        20433 :       if (mappings.size () == substitutions.size ())
    1012              :         {
    1013        18061 :           mappings.get_argument_at (i, &arg);
    1014              :         }
    1015              :       else
    1016              :         {
    1017         2372 :           if (subst.needs_substitution ())
    1018              :             {
    1019              :               // get from passed in mappings
    1020         2282 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
    1021              :             }
    1022              :           else
    1023              :             {
    1024              :               // we should already have this somewhere
    1025           90 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
    1026              :                                                       &arg);
    1027              :             }
    1028              :         }
    1029              : 
    1030        20433 :       bool ok = !arg.is_error ();
    1031        20433 :       if (ok || (trait_mode && i == 0))
    1032        19931 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
    1033              :     }
    1034              : 
    1035        15821 :   if (resolved_mappings.empty ())
    1036           12 :     return SubstitutionArgumentMappings::error ();
    1037              : 
    1038        15809 :   return SubstitutionArgumentMappings (resolved_mappings,
    1039        15809 :                                        mappings.get_binding_args (),
    1040              :                                        mappings.get_regions (),
    1041              :                                        mappings.get_locus (),
    1042              :                                        mappings.trait_item_mode (), false,
    1043        31618 :                                        mappings.get_constraint_args ());
    1044        15821 : }
    1045              : 
    1046              : bool
    1047            0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
    1048              : {
    1049            0 :   std::vector<SubstitutionArg> resolved_mappings;
    1050            0 :   for (size_t i = 0; i < substitutions.size (); i++)
    1051              :     {
    1052            0 :       auto &subst = substitutions.at (i);
    1053              : 
    1054            0 :       SubstitutionArg arg = SubstitutionArg::error ();
    1055            0 :       if (mappings.size () == substitutions.size ())
    1056              :         {
    1057            0 :           mappings.get_argument_at (i, &arg);
    1058              :         }
    1059              :       else
    1060              :         {
    1061            0 :           if (subst.needs_substitution ())
    1062              :             {
    1063              :               // get from passed in mappings
    1064            0 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
    1065              :             }
    1066              :           else
    1067              :             {
    1068              :               // we should already have this somewhere
    1069            0 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
    1070              :                                                       &arg);
    1071              :             }
    1072              :         }
    1073              : 
    1074            0 :       bool ok = !arg.is_error ();
    1075            0 :       if (ok)
    1076            0 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
    1077              :     }
    1078              : 
    1079            0 :   return !resolved_mappings.empty ();
    1080            0 : }
    1081              : 
    1082              : // this function assumes that the mappings being passed are for the same type as
    1083              : // this new substitution reference so ordering matters here
    1084              : SubstitutionArgumentMappings
    1085           63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
    1086              :   SubstitutionArgumentMappings &mappings) const
    1087              : {
    1088           63 :   std::vector<SubstitutionArg> resolved_mappings;
    1089              : 
    1090           63 :   rust_assert (mappings.size () == get_num_substitutions ());
    1091          126 :   for (size_t i = 0; i < get_num_substitutions (); i++)
    1092              :     {
    1093           63 :       const SubstitutionParamMapping &param_mapping = substitutions.at (i);
    1094           63 :       SubstitutionArg &arg = mappings.get_mappings ().at (i);
    1095              : 
    1096           63 :       if (param_mapping.needs_substitution ())
    1097           63 :         resolved_mappings.emplace_back (&param_mapping, arg.get_tyty ());
    1098              :     }
    1099              : 
    1100           63 :   return SubstitutionArgumentMappings (resolved_mappings,
    1101           63 :                                        mappings.get_binding_args (),
    1102              :                                        mappings.get_regions (),
    1103              :                                        mappings.get_locus (), false, false,
    1104          126 :                                        mappings.get_constraint_args ());
    1105           63 : }
    1106              : 
    1107              : bool
    1108        18318 : SubstitutionRef::monomorphize ()
    1109              : {
    1110        29737 :   for (const auto &subst : get_substs ())
    1111              :     {
    1112        11419 :       const auto pty = subst.get_param_ty ();
    1113        11419 :       if (!pty->can_resolve ())
    1114          109 :         continue;
    1115              : 
    1116        11310 :       TyTy::BaseType *binding = pty->resolve ();
    1117        11310 :       if (binding->get_kind () == TyTy::TypeKind::PARAM)
    1118         2427 :         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        18884 :       for (const auto &bound : pty->get_specified_bounds ())
    1134              :         {
    1135        10001 :           bool ambigious = false;
    1136        10001 :           auto associated
    1137        10001 :             = Resolver::lookup_associated_impl_block (bound, binding,
    1138              :                                                       &ambigious);
    1139        10001 :           if (associated != nullptr)
    1140         2322 :             associated->bind_impl_for_bound (binding, bound, UNKNOWN_LOCATION);
    1141              :         }
    1142              :     }
    1143              : 
    1144        18318 :   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.