LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-subst.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.0 % 522 449
Test Date: 2026-04-20 14:57:17 Functions: 87.3 % 79 69
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     83668017 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
      36     83668017 :                                                     BaseGeneric *param)
      37     83668017 :   : generic (generic), param (param)
      38     83668017 : {}
      39              : 
      40     93424739 : SubstitutionParamMapping::SubstitutionParamMapping (
      41     93424739 :   const SubstitutionParamMapping &other)
      42     93424739 :   : generic (other.generic), param (other.param)
      43     93424739 : {}
      44              : 
      45              : std::string
      46       508375 : SubstitutionParamMapping::as_string () const
      47              : {
      48       508375 :   if (param == nullptr)
      49            0 :     return "nullptr";
      50              : 
      51       508375 :   return param->get_name ();
      52              : }
      53              : 
      54              : SubstitutionParamMapping
      55     83654304 : SubstitutionParamMapping::clone () const
      56              : {
      57     83654304 :   return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
      58     83654304 :                                               param->clone ()));
      59              : }
      60              : 
      61              : BaseGeneric *
      62       205726 : SubstitutionParamMapping::get_param_ty ()
      63              : {
      64       205726 :   return param;
      65              : }
      66              : 
      67              : const BaseGeneric *
      68     75919909 : SubstitutionParamMapping::get_param_ty () const
      69              : {
      70     75919909 :   return param;
      71              : }
      72              : 
      73              : HIR::GenericParam &
      74        17780 : SubstitutionParamMapping::get_generic_param ()
      75              : {
      76        17780 :   return generic;
      77              : }
      78              : 
      79              : const HIR::GenericParam &
      80         9898 : SubstitutionParamMapping::get_generic_param () const
      81              : {
      82         9898 :   return generic;
      83              : }
      84              : 
      85              : bool
      86       111696 : SubstitutionParamMapping::needs_substitution () const
      87              : {
      88       111696 :   return !(get_param_ty ()->is_concrete ());
      89              : }
      90              : 
      91              : Identifier
      92         2368 : SubstitutionParamMapping::get_type_representation () const
      93              : {
      94         4736 :   return param->get_symbol ();
      95              : }
      96              : 
      97              : location_t
      98          995 : SubstitutionParamMapping::get_param_locus () const
      99              : {
     100          995 :   return generic.get_locus ();
     101              : }
     102              : 
     103              : bool
     104        23667 : SubstitutionParamMapping::param_has_default_ty () const
     105              : {
     106        23667 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     107              :     {
     108        23417 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     109        23417 :       return type_param.has_type ();
     110              :     }
     111              : 
     112          250 :   rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
     113          250 :   const auto &const_param
     114              :     = static_cast<const HIR::ConstGenericParam &> (generic);
     115          250 :   return const_param.has_default_expression ();
     116              : }
     117              : 
     118              : BaseType *
     119         1137 : SubstitutionParamMapping::get_default_ty () const
     120              : {
     121         1137 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     122              :     {
     123         1132 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     124         1132 :       TyVar var (type_param.get_type_mappings ().get_hirid ());
     125         1132 :       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        38200 : SubstitutionParamMapping::fill_param_ty (
     150              :   SubstitutionArgumentMappings &subst_mappings, location_t locus,
     151              :   bool needs_bounds_check)
     152              : {
     153        38200 :   SubstitutionArg arg = SubstitutionArg::error ();
     154        38200 :   bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
     155        38200 :   if (!ok)
     156              :     return true;
     157              : 
     158        38200 :   TyTy::BaseType &type = *arg.get_tyty ();
     159        38200 :   if (type.get_kind () == TyTy::TypeKind::INFER)
     160              :     {
     161        12839 :       type.inherit_bounds (*param);
     162              :     }
     163              : 
     164        38200 :   if (type.get_kind () == TypeKind::PARAM)
     165              :     {
     166         7303 :       param = static_cast<BaseGeneric *> (type.clone ());
     167              :     }
     168        30897 :   else if (type.get_kind () == TyTy::TypeKind::CONST)
     169              :     {
     170          204 :       rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
     171          204 :       auto *const_type = type.as_const_type ();
     172          204 :       if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
     173           22 :         param = static_cast<BaseGeneric *> (type.clone ());
     174              :       else
     175          182 :         param->set_ty_ref (type.get_ref ());
     176              :     }
     177        30693 :   else if (param->get_kind () == TypeKind::PARAM)
     178              :     {
     179        30693 :       auto &p = *static_cast<TyTy::ParamType *> (param);
     180              : 
     181              :       // check the substitution is compatible with bounds
     182        30693 :       rust_debug_loc (locus,
     183              :                       "fill_param_ty bounds_compatible: param %s type %s",
     184        61386 :                       param->get_name ().c_str (), type.get_name ().c_str ());
     185        30693 :       if (needs_bounds_check && !p.is_implicit_self_trait ())
     186              :         {
     187        15624 :           if (!param->bounds_compatible (type, locus, true))
     188              :             return false;
     189              :         }
     190              : 
     191              :       // recursively pass this down to all HRTB's
     192        68216 :       for (auto &bound : param->get_specified_bounds ())
     193        37529 :         bound.handle_substitions (subst_mappings);
     194              : 
     195        30687 :       param->set_ty_ref (type.get_ref ());
     196        30687 :       subst_mappings.on_param_subst (p, arg);
     197              :     }
     198              : 
     199              :   return true;
     200              : }
     201              : 
     202              : void
     203         5200 : SubstitutionParamMapping::override_context ()
     204              : {
     205         5200 :   if (!param->can_resolve ())
     206              :     return;
     207              : 
     208         5186 :   auto &mappings = Analysis::Mappings::get ();
     209         5186 :   auto context = Resolver::TypeCheckContext::get ();
     210              : 
     211         5186 :   context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
     212              :                                                UNKNOWN_NODEID,
     213         5186 :                                                param->get_ref (),
     214         5186 :                                                UNKNOWN_LOCAL_DEFID),
     215         5186 :                         param->resolve ());
     216              : }
     217              : 
     218     75939272 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
     219     75939272 :                                   BaseType *argument)
     220     75939272 :   : param (param), argument (argument)
     221              : {
     222     75939272 :   if (param != nullptr)
     223     75767178 :     original_param = param->get_param_ty ();
     224     75939272 : }
     225              : 
     226    306323230 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
     227    306323230 :   : param (other.param), original_param (other.original_param),
     228    306323230 :     argument (other.argument)
     229    306323230 : {}
     230              : 
     231              : SubstitutionArg &
     232       163939 : SubstitutionArg::operator= (const SubstitutionArg &other)
     233              : {
     234       163939 :   param = other.param;
     235       163939 :   argument = other.argument;
     236       163939 :   original_param = other.original_param;
     237              : 
     238       163939 :   return *this;
     239              : }
     240              : 
     241              : BaseType *
     242     78455796 : SubstitutionArg::get_tyty () const
     243              : {
     244     78455796 :   return argument;
     245              : }
     246              : 
     247              : const SubstitutionParamMapping *
     248         8345 : SubstitutionArg::get_param_mapping () const
     249              : {
     250         8345 :   return param;
     251              : }
     252              : 
     253              : const BaseGeneric *
     254       184314 : SubstitutionArg::get_param_ty () const
     255              : {
     256       184314 :   return original_param;
     257              : }
     258              : 
     259              : SubstitutionArg
     260       172094 : SubstitutionArg::error ()
     261              : {
     262       172094 :   return SubstitutionArg (nullptr, nullptr);
     263              : }
     264              : 
     265              : bool
     266        63445 : SubstitutionArg::is_error () const
     267              : {
     268        63445 :   return param == nullptr || argument == nullptr;
     269              : }
     270              : 
     271              : bool
     272            0 : SubstitutionArg::is_conrete () const
     273              : {
     274            0 :   if (argument == nullptr)
     275              :     return false;
     276              : 
     277            0 :   if (argument->get_kind () == TyTy::TypeKind::PARAM)
     278              :     return false;
     279              : 
     280            0 :   return argument->is_concrete ();
     281              : }
     282              : 
     283              : std::string
     284            0 : SubstitutionArg::as_string () const
     285              : {
     286            0 :   return original_param->as_string ()
     287            0 :          + (argument != nullptr ? ":" + argument->as_string () : "");
     288              : }
     289              : 
     290              : const RegionParamList &
     291     74057674 : SubstitutionArgumentMappings::get_regions () const
     292              : {
     293     74057674 :   return regions;
     294              : }
     295              : 
     296              : RegionParamList &
     297         2046 : SubstitutionArgumentMappings::get_mut_regions ()
     298              : {
     299         2046 :   return regions;
     300              : }
     301              : 
     302              : // SubstitutionArgumentMappings
     303              : 
     304    148301401 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     305              :   std::vector<SubstitutionArg> mappings,
     306              :   std::map<std::string, BaseType *> binding_args, RegionParamList regions,
     307              :   location_t locus, ParamSubstCb param_subst_cb, bool trait_item_flag,
     308    148301401 :   bool error_flag)
     309    148301401 :   : mappings (std::move (mappings)), binding_args (binding_args),
     310    148301401 :     regions (regions), locus (locus), param_subst_cb (param_subst_cb),
     311    148301401 :     trait_item_flag (trait_item_flag), error_flag (error_flag)
     312    148301401 : {}
     313              : 
     314     74606408 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     315     74606408 :   const SubstitutionArgumentMappings &other)
     316     74606408 :   : mappings (other.mappings), binding_args (other.binding_args),
     317     74606408 :     regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
     318     74606408 :     trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
     319     74606408 : {}
     320              : 
     321              : SubstitutionArgumentMappings &
     322        42555 : SubstitutionArgumentMappings::operator= (
     323              :   const SubstitutionArgumentMappings &other)
     324              : {
     325        42555 :   mappings = other.mappings;
     326        42555 :   binding_args = other.binding_args;
     327        42555 :   regions = other.regions;
     328        42555 :   locus = other.locus;
     329        42555 :   param_subst_cb = nullptr;
     330        42555 :   trait_item_flag = other.trait_item_flag;
     331        42555 :   error_flag = other.error_flag;
     332              : 
     333        42555 :   return *this;
     334              : }
     335              : 
     336              : SubstitutionArgumentMappings
     337        46352 : SubstitutionArgumentMappings::error ()
     338              : {
     339        92704 :   return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
     340        46352 :                                        false, true);
     341              : }
     342              : 
     343              : SubstitutionArgumentMappings
     344     74205048 : SubstitutionArgumentMappings::empty (size_t num_regions)
     345              : {
     346    148410096 :   return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
     347     74205048 :                                        nullptr, false, false);
     348              : }
     349              : 
     350              : bool
     351        34280 : SubstitutionArgumentMappings::is_error () const
     352              : {
     353        34280 :   return error_flag;
     354              : }
     355              : 
     356              : bool
     357       156167 : SubstitutionArgumentMappings::get_argument_for_symbol (
     358              :   const BaseGeneric *param_to_find, SubstitutionArg *argument) const
     359              : {
     360       200222 :   for (const auto &mapping : mappings)
     361              :     {
     362       184314 :       const auto *p = mapping.get_param_ty ();
     363       184314 :       if (p->get_symbol () == param_to_find->get_symbol ())
     364              :         {
     365       140259 :           *argument = mapping;
     366       140259 :           return true;
     367              :         }
     368              :     }
     369              :   return false;
     370              : }
     371              : tl::optional<size_t>
     372            0 : SubstitutionArgumentMappings::find_symbol (const ParamType &param_to_find) const
     373              : {
     374            0 :   auto it = std::find_if (mappings.begin (), mappings.end (),
     375            0 :                           [param_to_find] (const SubstitutionArg &arg) {
     376            0 :                             return arg.get_param_ty ()->get_symbol ()
     377            0 :                                    == param_to_find.get_symbol ();
     378              :                           });
     379            0 :   if (it == mappings.end ())
     380            0 :     return tl::nullopt;
     381            0 :   return std::distance (mappings.begin (), it);
     382              : }
     383              : 
     384              : bool
     385        15927 : SubstitutionArgumentMappings::get_argument_at (size_t index,
     386              :                                                SubstitutionArg *argument)
     387              : {
     388        15927 :   if (index > mappings.size ())
     389              :     return false;
     390              : 
     391        15927 :   *argument = mappings.at (index);
     392        15927 :   return true;
     393              : }
     394              : 
     395              : bool
     396            0 : SubstitutionArgumentMappings::is_concrete () const
     397              : {
     398            0 :   for (auto &mapping : mappings)
     399              :     {
     400            0 :       if (!mapping.is_conrete ())
     401            0 :         return false;
     402              :     }
     403              :   return true;
     404              : }
     405              : 
     406              : location_t
     407     74065150 : SubstitutionArgumentMappings::get_locus () const
     408              : {
     409     74065150 :   return locus;
     410              : }
     411              : 
     412              : size_t
     413        43154 : SubstitutionArgumentMappings::size () const
     414              : {
     415        43154 :   return mappings.size ();
     416              : }
     417              : 
     418              : bool
     419        15645 : SubstitutionArgumentMappings::is_empty () const
     420              : {
     421        15645 :   return size () == 0;
     422              : }
     423              : 
     424              : std::vector<SubstitutionArg> &
     425        56272 : SubstitutionArgumentMappings::get_mappings ()
     426              : {
     427        56272 :   return mappings;
     428              : }
     429              : 
     430              : const std::vector<SubstitutionArg> &
     431    299415919 : SubstitutionArgumentMappings::get_mappings () const
     432              : {
     433    299415919 :   return mappings;
     434              : }
     435              : 
     436              : std::map<std::string, BaseType *> &
     437        62028 : SubstitutionArgumentMappings::get_binding_args ()
     438              : {
     439        62028 :   return binding_args;
     440              : }
     441              : 
     442              : const std::map<std::string, BaseType *> &
     443            0 : SubstitutionArgumentMappings::get_binding_args () const
     444              : {
     445            0 :   return binding_args;
     446              : }
     447              : 
     448              : std::string
     449            0 : SubstitutionArgumentMappings::as_string () const
     450              : {
     451            0 :   std::string buffer;
     452            0 :   for (auto &mapping : mappings)
     453              :     {
     454            0 :       buffer += mapping.as_string () + ", ";
     455              :     }
     456            0 :   return "<" + buffer + ">";
     457            0 : }
     458              : 
     459              : void
     460        75616 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
     461              :                                               const SubstitutionArg &a) const
     462              : {
     463        75616 :   if (param_subst_cb == nullptr)
     464              :     return;
     465              : 
     466          575 :   param_subst_cb (p, a);
     467              : }
     468              : 
     469              : ParamSubstCb
     470        19838 : SubstitutionArgumentMappings::get_subst_cb () const
     471              : {
     472        19838 :   return param_subst_cb;
     473              : }
     474              : 
     475              : bool
     476        14455 : SubstitutionArgumentMappings::trait_item_mode () const
     477              : {
     478        14455 :   return trait_item_flag;
     479              : }
     480              : 
     481              : // SubstitutionRef
     482              : 
     483     74289265 : SubstitutionRef::SubstitutionRef (
     484              :   std::vector<SubstitutionParamMapping> substitutions,
     485     74289265 :   SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
     486     74289265 :   : substitutions (substitutions), used_arguments (arguments),
     487    148578530 :     region_constraints (region_constraints)
     488     74289265 : {}
     489              : 
     490              : bool
     491       186359 : SubstitutionRef::has_substitutions () const
     492              : {
     493       186359 :   return substitutions.size () > 0;
     494              : }
     495              : 
     496              : std::string
     497      1842999 : SubstitutionRef::subst_as_string () const
     498              : {
     499      1842999 :   std::string buffer;
     500      2351374 :   for (size_t i = 0; i < substitutions.size (); i++)
     501              :     {
     502       508375 :       const SubstitutionParamMapping &sub = substitutions.at (i);
     503      1016750 :       buffer += sub.as_string ();
     504              : 
     505       508375 :       if ((i + 1) < substitutions.size ())
     506        58200 :         buffer += ", ";
     507              :     }
     508              : 
     509      2293174 :   return buffer.empty () ? "" : "<" + buffer + ">";
     510      1842999 : }
     511              : 
     512              : bool
     513           73 : SubstitutionRef::supports_associated_bindings () const
     514              : {
     515           73 :   return get_num_associated_bindings () > 0;
     516              : }
     517              : 
     518              : size_t
     519            1 : SubstitutionRef::get_num_associated_bindings () const
     520              : {
     521            1 :   return 0;
     522              : }
     523              : 
     524              : TypeBoundPredicateItem
     525            0 : SubstitutionRef::lookup_associated_type (const std::string &search)
     526              : {
     527            0 :   return TypeBoundPredicateItem::error ();
     528              : }
     529              : 
     530              : size_t
     531        95889 : SubstitutionRef::get_num_substitutions () const
     532              : {
     533        95889 :   return substitutions.size ();
     534              : }
     535              : size_t
     536          135 : SubstitutionRef::get_num_lifetime_params () const
     537              : {
     538          135 :   return used_arguments.get_regions ().size ();
     539              : }
     540              : size_t
     541          538 : SubstitutionRef::get_num_type_params () const
     542              : {
     543          538 :   return get_num_substitutions ();
     544              : }
     545              : 
     546              : std::vector<SubstitutionParamMapping> &
     547       135407 : SubstitutionRef::get_substs ()
     548              : {
     549       135407 :   return substitutions;
     550              : }
     551              : 
     552              : const std::vector<SubstitutionParamMapping> &
     553     74036426 : SubstitutionRef::get_substs () const
     554              : {
     555     74036426 :   return substitutions;
     556              : }
     557              : 
     558              : std::vector<SubstitutionParamMapping>
     559       173223 : SubstitutionRef::clone_substs () const
     560              : {
     561       173223 :   std::vector<SubstitutionParamMapping> clone;
     562       173223 :   clone.reserve (substitutions.size ());
     563              : 
     564       242435 :   for (auto &sub : substitutions)
     565        69212 :     clone.push_back (sub.clone ());
     566              : 
     567       173223 :   return clone;
     568              : }
     569              : 
     570              : void
     571         4677 : SubstitutionRef::override_context ()
     572              : {
     573         9877 :   for (auto &sub : substitutions)
     574              :     {
     575         5200 :       sub.override_context ();
     576              :     }
     577         4677 : }
     578              : 
     579              : bool
     580       158320 : SubstitutionRef::needs_substitution () const
     581              : {
     582       158320 :   return std::any_of (substitutions.begin (), substitutions.end (),
     583              :                       std::mem_fn (
     584       158320 :                         &SubstitutionParamMapping::needs_substitution));
     585              : }
     586              : 
     587              : bool
     588           63 : SubstitutionRef::was_substituted () const
     589              : {
     590           63 :   return !needs_substitution ();
     591              : }
     592              : 
     593              : SubstitutionArgumentMappings &
     594        54621 : SubstitutionRef::get_substitution_arguments ()
     595              : {
     596        54621 :   return used_arguments;
     597              : }
     598              : 
     599              : const SubstitutionArgumentMappings &
     600        24875 : SubstitutionRef::get_substitution_arguments () const
     601              : {
     602        24875 :   return used_arguments;
     603              : }
     604              : 
     605              : size_t
     606         9252 : SubstitutionRef::num_required_substitutions () const
     607              : {
     608         9252 :   size_t n = 0;
     609        20837 :   for (auto &p : substitutions)
     610              :     {
     611        11585 :       if (p.needs_substitution ())
     612        11258 :         n++;
     613              :     }
     614         9252 :   return n;
     615              : }
     616              : 
     617              : size_t
     618        18514 : SubstitutionRef::min_required_substitutions () const
     619              : {
     620        18514 :   size_t n = 0;
     621        41698 :   for (auto &p : substitutions)
     622              :     {
     623        23184 :       if (p.needs_substitution () && !p.param_has_default_ty ())
     624        19379 :         n++;
     625              :     }
     626        18514 :   return n;
     627              : }
     628              : 
     629              : const SubstitutionArgumentMappings &
     630        14116 : SubstitutionRef::get_used_arguments () const
     631              : {
     632        14116 :   return used_arguments;
     633              : }
     634              : 
     635              : tl::optional<SubstitutionArg>
     636          168 : SubstitutionRef::get_arg_at (size_t i) const
     637              : {
     638          168 :   auto param_ty = get_substs ().at (i).get_param_ty ();
     639          168 :   SubstitutionArg arg = SubstitutionArg::error ();
     640          168 :   get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
     641          168 :   if (arg.is_error ())
     642            8 :     return tl::nullopt;
     643          160 :   return arg;
     644              : }
     645              : 
     646              : const RegionConstraints &
     647       171919 : SubstitutionRef::get_region_constraints () const
     648              : {
     649       171919 :   return region_constraints;
     650              : }
     651              : 
     652              : SubstitutionArgumentMappings
     653         9263 : SubstitutionRef::get_mappings_from_generic_args (
     654              :   HIR::GenericArgs &args, const std::vector<Region> &regions)
     655              : {
     656         9263 :   std::map<std::string, BaseType *> binding_arguments;
     657         9263 :   if (args.get_binding_args ().size () > 0)
     658              :     {
     659           73 :       if (supports_associated_bindings ())
     660              :         {
     661           72 :           if (args.get_binding_args ().size () > get_num_associated_bindings ())
     662              :             {
     663            0 :               rich_location r (line_table, args.get_locus ());
     664            0 :               rust_error_at (r,
     665              :                              "generic item takes at most %lu type binding "
     666              :                              "arguments but %lu were supplied",
     667            0 :                              (unsigned long) get_num_associated_bindings (),
     668            0 :                              (unsigned long) args.get_binding_args ().size ());
     669            0 :               return SubstitutionArgumentMappings::error ();
     670            0 :             }
     671              : 
     672          144 :           for (auto &binding : args.get_binding_args ())
     673              :             {
     674           72 :               BaseType *resolved
     675           72 :                 = Resolver::TypeCheckType::Resolve (binding.get_type ());
     676           72 :               if (resolved == nullptr
     677           72 :                   || resolved->get_kind () == TyTy::TypeKind::ERROR)
     678              :                 {
     679            0 :                   return SubstitutionArgumentMappings::error ();
     680              :                 }
     681              : 
     682              :               // resolve to relevant binding
     683           72 :               auto binding_item = lookup_associated_type (
     684           72 :                 binding.get_identifier ().as_string ());
     685           72 :               if (binding_item.is_error ())
     686              :                 {
     687            0 :                   rust_error_at (
     688              :                     binding.get_locus (), "unknown associated type binding: %s",
     689            0 :                     binding.get_identifier ().as_string ().c_str ());
     690            0 :                   return SubstitutionArgumentMappings::error ();
     691              :                 }
     692              : 
     693           72 :               binding_arguments[binding.get_identifier ().as_string ()]
     694           72 :                 = resolved;
     695           72 :             }
     696              :         }
     697              :       else
     698              :         {
     699            1 :           rich_location r (line_table, args.get_locus ());
     700            3 :           for (auto &binding : args.get_binding_args ())
     701            2 :             r.add_range (binding.get_locus ());
     702              : 
     703            1 :           rust_error_at (r, ErrorCode::E0229,
     704              :                          "associated type bindings are not allowed here");
     705            1 :           return SubstitutionArgumentMappings::error ();
     706            1 :         }
     707              :     }
     708              : 
     709              :   // for inherited arguments
     710         9262 :   size_t offs = used_arguments.size ();
     711         9262 :   size_t total_arguments
     712         9262 :     = args.get_type_args ().size () + args.get_const_args ().size () + offs;
     713         9262 :   if (total_arguments > substitutions.size ())
     714              :     {
     715            3 :       rich_location r (line_table, args.get_locus ());
     716            3 :       if (!substitutions.empty ())
     717              :         {
     718            2 :           const auto &subst = substitutions.front ();
     719            2 :           const auto &generic = subst.get_generic_param ();
     720            2 :           r.add_range (generic.get_locus ());
     721              :         }
     722              : 
     723            6 :       rust_error_at (
     724              :         r,
     725              :         "generic item takes at most %lu type arguments but %lu were supplied",
     726            3 :         (unsigned long) substitutions.size (),
     727            3 :         (unsigned long) args.get_type_args ().size ());
     728            3 :       return SubstitutionArgumentMappings::error ();
     729            3 :     }
     730              : 
     731         9259 :   if (total_arguments < min_required_substitutions ())
     732              :     {
     733            3 :       rich_location r (line_table, args.get_locus ());
     734            3 :       if (!substitutions.empty ())
     735              :         {
     736            3 :           const auto &subst = substitutions.front ();
     737            3 :           const auto &generic = subst.get_generic_param ();
     738            3 :           r.add_range (generic.get_locus ());
     739              :         }
     740              : 
     741            6 :       rust_error_at (
     742              :         r, ErrorCode::E0107,
     743              :         "generic item takes at least %lu type arguments but %lu were supplied",
     744            3 :         (unsigned long) (min_required_substitutions () - offs),
     745            3 :         (unsigned long) args.get_type_args ().size ());
     746            3 :       return SubstitutionArgumentMappings::error ();
     747            3 :     }
     748              : 
     749         9256 :   std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
     750        19029 :   for (auto &arg : args.get_type_args ())
     751              :     {
     752         9777 :       BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
     753         9777 :       if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
     754              :         {
     755            4 :           return SubstitutionArgumentMappings::error ();
     756              :         }
     757              : 
     758         9777 :       const auto &param_mapping = substitutions.at (offs);
     759         9777 :       const auto &generic = param_mapping.get_generic_param ();
     760         9777 :       if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     761              :         {
     762         9774 :           const auto &type_param
     763              :             = static_cast<const HIR::TypeParam &> (generic);
     764         9774 :           if (type_param.from_impl_trait ())
     765              :             {
     766            1 :               rich_location r (line_table, arg->get_locus ());
     767            1 :               r.add_fixit_remove (arg->get_locus ());
     768            1 :               rust_error_at (r, ErrorCode::E0632,
     769              :                              "cannot provide explicit generic arguments when "
     770              :                              "%<impl Trait%> is used in argument position");
     771            1 :               return SubstitutionArgumentMappings::error ();
     772            1 :             }
     773              :         }
     774            3 :       else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     775              :         {
     776            3 :           if (resolved->get_kind () != TyTy::TypeKind::CONST)
     777              :             {
     778            3 :               rich_location r (line_table, arg->get_locus ());
     779            3 :               r.add_fixit_remove (arg->get_locus ());
     780            3 :               rust_error_at (r, ErrorCode::E0747,
     781              :                              "type provided when a constant was expected");
     782            3 :               return SubstitutionArgumentMappings::error ();
     783            3 :             }
     784              :         }
     785              : 
     786         9773 :       mappings.emplace_back (&param_mapping, resolved);
     787         9773 :       offs++;
     788              :     }
     789              : 
     790         9368 :   for (auto &arg : args.get_const_args ())
     791              :     {
     792          116 :       auto &expr = *arg.get_expression ().get ();
     793          116 :       BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
     794          232 :       if (expr_type == nullptr || expr_type->is<ErrorType> ())
     795            0 :         return SubstitutionArgumentMappings::error ();
     796              : 
     797              :       // validate this param is really a const generic
     798          116 :       const auto &param_mapping = substitutions.at (offs);
     799          116 :       const auto &generic = param_mapping.get_generic_param ();
     800          116 :       if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
     801              :         {
     802            0 :           rich_location r (line_table, arg.get_locus ());
     803            0 :           r.add_fixit_remove (expr.get_locus ());
     804            0 :           rust_error_at (r, "invalid position for a const generic argument");
     805            0 :           return SubstitutionArgumentMappings::error ();
     806            0 :         }
     807              : 
     808              :       // get the const generic specified type
     809          116 :       const auto base_generic = param_mapping.get_param_ty ();
     810          116 :       rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
     811          116 :       const auto const_param
     812          116 :         = static_cast<const TyTy::ConstParamType *> (base_generic);
     813          116 :       auto specified_type = const_param->get_specified_type ();
     814              : 
     815              :       // validate this const generic is of the correct type
     816          116 :       TyTy::BaseType *coereced_type = nullptr;
     817          116 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     818              :         {
     819           22 :           auto const_expr_type = expr_type->as_const_type ();
     820           22 :           auto const_value_type = const_expr_type->get_specified_type ();
     821           22 :           coereced_type
     822           22 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     823           22 :                                        TyTy::TyWithLocation (specified_type),
     824              :                                        TyTy::TyWithLocation (const_value_type,
     825           22 :                                                              expr.get_locus ()),
     826              :                                        arg.get_locus ());
     827              :         }
     828              :       else
     829              :         {
     830           94 :           coereced_type
     831           94 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     832           94 :                                        TyTy::TyWithLocation (specified_type),
     833              :                                        TyTy::TyWithLocation (expr_type,
     834           94 :                                                              expr.get_locus ()),
     835              :                                        arg.get_locus ());
     836              :         }
     837              : 
     838          232 :       if (coereced_type == nullptr || coereced_type->is<ErrorType> ())
     839            0 :         return SubstitutionArgumentMappings::error ();
     840              : 
     841          116 :       TyTy::BaseType *const_value_ty = nullptr;
     842          116 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     843           22 :         const_value_ty = expr_type;
     844              :       else
     845              :         {
     846              :           // const fold it if available
     847           94 :           auto ctx = Compile::Context::get ();
     848           94 :           tree folded
     849           94 :             = Compile::HIRCompileBase::query_compile_const_expr (ctx,
     850              :                                                                  coereced_type,
     851              :                                                                  expr);
     852              : 
     853           94 :           if (folded == error_mark_node)
     854              :             {
     855            0 :               rich_location r (line_table, arg.get_locus ());
     856            0 :               r.add_range (expr.get_locus ());
     857            0 :               rust_error_at (r, "failed to resolve const expression");
     858            0 :               return SubstitutionArgumentMappings::error ();
     859            0 :             }
     860              : 
     861              :           // Use a fresh HirId to avoid conflicts with the expr's type
     862           94 :           auto &global_mappings = Analysis::Mappings::get ();
     863           94 :           HirId const_value_id = global_mappings.get_next_hir_id ();
     864           94 :           const_value_ty
     865           94 :             = new TyTy::ConstValueType (folded, coereced_type, const_value_id,
     866           94 :                                         const_value_id, {});
     867              : 
     868              :           // Insert the ConstValueType into the context so it can be looked up
     869           94 :           auto context = Resolver::TypeCheckContext::get ();
     870           94 :           context->insert_type (
     871           94 :             Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0),
     872              :             const_value_ty);
     873              :         }
     874              : 
     875          116 :       mappings.emplace_back (&param_mapping, const_value_ty);
     876          116 :       offs++;
     877              :     }
     878              : 
     879              :   // we must need to fill out defaults
     880         9252 :   size_t left_over
     881         9252 :     = num_required_substitutions () - min_required_substitutions ();
     882         9252 :   if (left_over > 0)
     883              :     {
     884         2712 :       for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
     885              :         {
     886         1137 :           SubstitutionParamMapping &param = substitutions.at (offs);
     887         1137 :           rust_assert (param.param_has_default_ty ());
     888              : 
     889         1137 :           BaseType *resolved = param.get_default_ty ();
     890         1137 :           if (resolved->get_kind () == TypeKind::ERROR)
     891            0 :             return SubstitutionArgumentMappings::error ();
     892              : 
     893              :           // this resolved default might already contain default parameters
     894         1137 :           if (!resolved->is_concrete ())
     895              :             {
     896         1118 :               SubstitutionArgumentMappings intermediate (
     897              :                 mappings, binding_arguments,
     898         1118 :                 {used_arguments.get_regions ().size ()}, args.get_locus ());
     899         1118 :               resolved = Resolver::SubstMapperInternal::Resolve (resolved,
     900              :                                                                  intermediate);
     901              : 
     902         1118 :               if (resolved->get_kind () == TypeKind::ERROR)
     903            0 :                 return SubstitutionArgumentMappings::error ();
     904         1118 :             }
     905              : 
     906         1137 :           mappings.emplace_back (&param, resolved);
     907              :         }
     908              :     }
     909              : 
     910         9252 :   return {mappings, binding_arguments,
     911        18504 :           RegionParamList::from_subst (used_arguments.get_regions ().size (),
     912              :                                        regions),
     913        27756 :           args.get_locus ()};
     914         9256 : }
     915              : 
     916              : BaseType *
     917         7391 : SubstitutionRef::infer_substitions (location_t locus)
     918              : {
     919         7391 :   std::vector<SubstitutionArg> args;
     920         7391 :   std::map<std::string, BaseType *> argument_mappings;
     921        16309 :   for (auto &p : get_substs ())
     922              :     {
     923         8918 :       if (p.needs_substitution ())
     924              :         {
     925         8849 :           const HIR::GenericParam &generic = p.get_generic_param ();
     926         8849 :           const std::string &symbol = p.get_param_ty ()->get_symbol ();
     927         8849 :           auto it = argument_mappings.find (symbol);
     928         8849 :           bool have_mapping = it != argument_mappings.end ();
     929              : 
     930         8849 :           if (have_mapping)
     931              :             {
     932          121 :               args.emplace_back (&p, it->second);
     933              :             }
     934         8728 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     935              :             {
     936         8709 :               TyVar infer_var = TyVar::get_implicit_infer_var (locus);
     937         8709 :               args.emplace_back (&p, infer_var.get_tyty ());
     938         8709 :               argument_mappings[symbol] = infer_var.get_tyty ();
     939              :             }
     940           19 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
     941              :             {
     942           19 :               TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
     943           19 :               args.emplace_back (&p, infer_var.get_tyty ());
     944           19 :               argument_mappings[symbol] = infer_var.get_tyty ();
     945              :             }
     946         8849 :         }
     947              :       else
     948              :         {
     949           69 :           args.emplace_back (&p, p.get_param_ty ()->resolve ());
     950              :         }
     951              :     }
     952              : 
     953              :   // FIXME do we need to add inference variables to all the possible bindings?
     954              :   // it might just lead to inference variable hell not 100% sure if rustc does
     955              :   // this i think the language might needs this to be explicitly set
     956              : 
     957         7391 :   SubstitutionArgumentMappings infer_arguments (std::move (args),
     958              :                                                 {} /* binding_arguments */,
     959              :                                                 used_arguments.get_regions (),
     960         7391 :                                                 locus);
     961         7391 :   return handle_substitions (infer_arguments);
     962         7391 : }
     963              : 
     964              : SubstitutionArgumentMappings
     965        13966 : SubstitutionRef::adjust_mappings_for_this (
     966              :   SubstitutionArgumentMappings &mappings, bool trait_mode)
     967              : {
     968        13966 :   std::vector<SubstitutionArg> resolved_mappings;
     969        32150 :   for (size_t i = 0; i < substitutions.size (); i++)
     970              :     {
     971        18184 :       auto &subst = substitutions.at (i);
     972              : 
     973        18184 :       SubstitutionArg arg = SubstitutionArg::error ();
     974        18184 :       if (mappings.size () == substitutions.size ())
     975              :         {
     976        15927 :           mappings.get_argument_at (i, &arg);
     977              :         }
     978              :       else
     979              :         {
     980         2257 :           if (subst.needs_substitution ())
     981              :             {
     982              :               // get from passed in mappings
     983         2169 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
     984              :             }
     985              :           else
     986              :             {
     987              :               // we should already have this somewhere
     988           88 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
     989              :                                                       &arg);
     990              :             }
     991              :         }
     992              : 
     993        18184 :       bool ok = !arg.is_error ();
     994        18184 :       if (ok || (trait_mode && i == 0))
     995        17695 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
     996              :     }
     997              : 
     998        13966 :   if (resolved_mappings.empty ())
     999            8 :     return SubstitutionArgumentMappings::error ();
    1000              : 
    1001        13958 :   return SubstitutionArgumentMappings (resolved_mappings,
    1002        13958 :                                        mappings.get_binding_args (),
    1003              :                                        mappings.get_regions (),
    1004              :                                        mappings.get_locus (),
    1005        13958 :                                        mappings.get_subst_cb (),
    1006        27916 :                                        mappings.trait_item_mode ());
    1007        13966 : }
    1008              : 
    1009              : bool
    1010            0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
    1011              : {
    1012            0 :   std::vector<SubstitutionArg> resolved_mappings;
    1013            0 :   for (size_t i = 0; i < substitutions.size (); i++)
    1014              :     {
    1015            0 :       auto &subst = substitutions.at (i);
    1016              : 
    1017            0 :       SubstitutionArg arg = SubstitutionArg::error ();
    1018            0 :       if (mappings.size () == substitutions.size ())
    1019              :         {
    1020            0 :           mappings.get_argument_at (i, &arg);
    1021              :         }
    1022              :       else
    1023              :         {
    1024            0 :           if (subst.needs_substitution ())
    1025              :             {
    1026              :               // get from passed in mappings
    1027            0 :               mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
    1028              :             }
    1029              :           else
    1030              :             {
    1031              :               // we should already have this somewhere
    1032            0 :               used_arguments.get_argument_for_symbol (subst.get_param_ty (),
    1033              :                                                       &arg);
    1034              :             }
    1035              :         }
    1036              : 
    1037            0 :       bool ok = !arg.is_error ();
    1038            0 :       if (ok)
    1039            0 :         resolved_mappings.emplace_back (&subst, arg.get_tyty ());
    1040              :     }
    1041              : 
    1042            0 :   return !resolved_mappings.empty ();
    1043            0 : }
    1044              : 
    1045              : // this function assumes that the mappings being passed are for the same type as
    1046              : // this new substitution reference so ordering matters here
    1047              : SubstitutionArgumentMappings
    1048           63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
    1049              :   SubstitutionArgumentMappings &mappings) const
    1050              : {
    1051           63 :   std::vector<SubstitutionArg> resolved_mappings;
    1052              : 
    1053           63 :   rust_assert (mappings.size () == get_num_substitutions ());
    1054          126 :   for (size_t i = 0; i < get_num_substitutions (); i++)
    1055              :     {
    1056           63 :       const SubstitutionParamMapping &param_mapping = substitutions.at (i);
    1057           63 :       SubstitutionArg &arg = mappings.get_mappings ().at (i);
    1058              : 
    1059           63 :       if (param_mapping.needs_substitution ())
    1060           63 :         resolved_mappings.emplace_back (&param_mapping, arg.get_tyty ());
    1061              :     }
    1062              : 
    1063           63 :   return SubstitutionArgumentMappings (resolved_mappings,
    1064           63 :                                        mappings.get_binding_args (),
    1065              :                                        mappings.get_regions (),
    1066          126 :                                        mappings.get_locus ());
    1067           63 : }
    1068              : 
    1069              : void
    1070         4305 : SubstitutionRef::prepare_higher_ranked_bounds ()
    1071              : {
    1072         7210 :   for (const auto &subst : get_substs ())
    1073              :     {
    1074         2905 :       const auto pty = subst.get_param_ty ();
    1075         6289 :       for (const auto &bound : pty->get_specified_bounds ())
    1076              :         {
    1077         3384 :           const auto ref = bound.get ();
    1078         3384 :           ref->clear_associated_type_projections ();
    1079              :         }
    1080              :     }
    1081         4305 : }
    1082              : 
    1083              : bool
    1084        16873 : SubstitutionRef::monomorphize ()
    1085              : {
    1086        27164 :   for (const auto &subst : get_substs ())
    1087              :     {
    1088        10291 :       const auto pty = subst.get_param_ty ();
    1089        10291 :       if (!pty->can_resolve ())
    1090          100 :         continue;
    1091              : 
    1092        10191 :       TyTy::BaseType *binding = pty->resolve ();
    1093        10191 :       if (binding->get_kind () == TyTy::TypeKind::PARAM)
    1094         2256 :         continue;
    1095              : 
    1096        16992 :       for (const auto &bound : pty->get_specified_bounds ())
    1097              :         {
    1098         9057 :           bool ambigious = false;
    1099         9057 :           auto associated
    1100         9057 :             = Resolver::lookup_associated_impl_block (bound, binding,
    1101              :                                                       &ambigious);
    1102         9057 :           if (associated != nullptr)
    1103         1946 :             associated->setup_associated_types (binding, bound);
    1104              :         }
    1105              :     }
    1106              : 
    1107        16873 :   return true;
    1108              : }
    1109              : 
    1110              : } // namespace TyTy
    1111              : } // 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.