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-02-28 14:20:25 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     83598200 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
      36     83598200 :                                                     BaseGeneric *param)
      37     83598200 :   : generic (generic), param (param)
      38     83598200 : {}
      39              : 
      40     93354187 : SubstitutionParamMapping::SubstitutionParamMapping (
      41     93354187 :   const SubstitutionParamMapping &other)
      42     93354187 :   : generic (other.generic), param (other.param)
      43     93354187 : {}
      44              : 
      45              : std::string
      46       505521 : SubstitutionParamMapping::as_string () const
      47              : {
      48       505521 :   if (param == nullptr)
      49            0 :     return "nullptr";
      50              : 
      51       505521 :   return param->get_name ();
      52              : }
      53              : 
      54              : SubstitutionParamMapping
      55     83584791 : SubstitutionParamMapping::clone () const
      56              : {
      57     83584791 :   return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
      58     83584791 :                                               param->clone ()));
      59              : }
      60              : 
      61              : BaseGeneric *
      62       201201 : SubstitutionParamMapping::get_param_ty ()
      63              : {
      64       201201 :   return param;
      65              : }
      66              : 
      67              : const BaseGeneric *
      68     75848527 : SubstitutionParamMapping::get_param_ty () const
      69              : {
      70     75848527 :   return param;
      71              : }
      72              : 
      73              : HIR::GenericParam &
      74        16899 : SubstitutionParamMapping::get_generic_param ()
      75              : {
      76        16899 :   return generic;
      77              : }
      78              : 
      79              : const HIR::GenericParam &
      80         9896 : SubstitutionParamMapping::get_generic_param () const
      81              : {
      82         9896 :   return generic;
      83              : }
      84              : 
      85              : bool
      86       110227 : SubstitutionParamMapping::needs_substitution () const
      87              : {
      88       110227 :   return !(get_param_ty ()->is_concrete ());
      89              : }
      90              : 
      91              : Identifier
      92         2366 : SubstitutionParamMapping::get_type_representation () const
      93              : {
      94         4732 :   return param->get_symbol ();
      95              : }
      96              : 
      97              : location_t
      98          993 : SubstitutionParamMapping::get_param_locus () const
      99              : {
     100          993 :   return generic.get_locus ();
     101              : }
     102              : 
     103              : bool
     104        23663 : SubstitutionParamMapping::param_has_default_ty () const
     105              : {
     106        23663 :   if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     107              :     {
     108        23415 :       const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
     109        23415 :       return type_param.has_type ();
     110              :     }
     111              : 
     112          248 :   rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
     113          248 :   const auto &const_param
     114              :     = static_cast<const HIR::ConstGenericParam &> (generic);
     115          248 :   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        37466 : SubstitutionParamMapping::fill_param_ty (
     150              :   SubstitutionArgumentMappings &subst_mappings, location_t locus,
     151              :   bool needs_bounds_check)
     152              : {
     153        37466 :   SubstitutionArg arg = SubstitutionArg::error ();
     154        37466 :   bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
     155        37466 :   if (!ok)
     156              :     return true;
     157              : 
     158        37466 :   TyTy::BaseType &type = *arg.get_tyty ();
     159        37466 :   if (type.get_kind () == TyTy::TypeKind::INFER)
     160              :     {
     161        12107 :       type.inherit_bounds (*param);
     162              :     }
     163              : 
     164        37466 :   if (type.get_kind () == TypeKind::PARAM)
     165              :     {
     166         7303 :       param = static_cast<BaseGeneric *> (type.clone ());
     167              :     }
     168        30163 :   else if (type.get_kind () == TyTy::TypeKind::CONST)
     169              :     {
     170          203 :       rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
     171          203 :       auto *const_type = type.as_const_type ();
     172          203 :       if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
     173           21 :         param = static_cast<BaseGeneric *> (type.clone ());
     174              :       else
     175          182 :         param->set_ty_ref (type.get_ref ());
     176              :     }
     177        29960 :   else if (param->get_kind () == TypeKind::PARAM)
     178              :     {
     179        29960 :       auto &p = *static_cast<TyTy::ParamType *> (param);
     180              : 
     181              :       // check the substitution is compatible with bounds
     182        29960 :       rust_debug_loc (locus,
     183              :                       "fill_param_ty bounds_compatible: param %s type %s",
     184        59920 :                       param->get_name ().c_str (), type.get_name ().c_str ());
     185        29960 :       if (needs_bounds_check && !p.is_implicit_self_trait ())
     186              :         {
     187        14892 :           if (!param->bounds_compatible (type, locus, true))
     188              :             return false;
     189              :         }
     190              : 
     191              :       // recursively pass this down to all HRTB's
     192        66750 :       for (auto &bound : param->get_specified_bounds ())
     193        36796 :         bound.handle_substitions (subst_mappings);
     194              : 
     195        29954 :       param->set_ty_ref (type.get_ref ());
     196        29954 :       subst_mappings.on_param_subst (p, arg);
     197              :     }
     198              : 
     199              :   return true;
     200              : }
     201              : 
     202              : void
     203         4487 : SubstitutionParamMapping::override_context ()
     204              : {
     205         4487 :   if (!param->can_resolve ())
     206              :     return;
     207              : 
     208         4473 :   auto &mappings = Analysis::Mappings::get ();
     209         4473 :   auto context = Resolver::TypeCheckContext::get ();
     210              : 
     211         4473 :   context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
     212              :                                                UNKNOWN_NODEID,
     213         4473 :                                                param->get_ref (),
     214         4473 :                                                UNKNOWN_LOCAL_DEFID),
     215         4473 :                         param->resolve ());
     216              : }
     217              : 
     218     75867133 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
     219     75867133 :                                   BaseType *argument)
     220     75867133 :   : param (param), argument (argument)
     221              : {
     222     75867133 :   if (param != nullptr)
     223     75697981 :     original_param = param->get_param_ty ();
     224     75867133 : }
     225              : 
     226    306050011 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
     227    306050011 :   : param (other.param), original_param (other.original_param),
     228    306050011 :     argument (other.argument)
     229    306050011 : {}
     230              : 
     231              : SubstitutionArg &
     232       161729 : SubstitutionArg::operator= (const SubstitutionArg &other)
     233              : {
     234       161729 :   param = other.param;
     235       161729 :   argument = other.argument;
     236       161729 :   original_param = other.original_param;
     237              : 
     238       161729 :   return *this;
     239              : }
     240              : 
     241              : BaseType *
     242     78386295 : SubstitutionArg::get_tyty () const
     243              : {
     244     78386295 :   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       181372 : SubstitutionArg::get_param_ty () const
     255              : {
     256       181372 :   return original_param;
     257              : }
     258              : 
     259              : SubstitutionArg
     260       169152 : SubstitutionArg::error ()
     261              : {
     262       169152 :   return SubstitutionArg (nullptr, nullptr);
     263              : }
     264              : 
     265              : bool
     266        63444 : SubstitutionArg::is_error () const
     267              : {
     268        63444 :   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     73988881 : SubstitutionArgumentMappings::get_regions () const
     292              : {
     293     73988881 :   return regions;
     294              : }
     295              : 
     296              : RegionParamList &
     297         2046 : SubstitutionArgumentMappings::get_mut_regions ()
     298              : {
     299         2046 :   return regions;
     300              : }
     301              : 
     302              : // SubstitutionArgumentMappings
     303              : 
     304    148159297 : 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    148159297 :   bool error_flag)
     309    148159297 :   : mappings (std::move (mappings)), binding_args (binding_args),
     310    148159297 :     regions (regions), locus (locus), param_subst_cb (param_subst_cb),
     311    148159297 :     trait_item_flag (trait_item_flag), error_flag (error_flag)
     312    148159297 : {}
     313              : 
     314     74531846 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
     315     74531846 :   const SubstitutionArgumentMappings &other)
     316     74531846 :   : mappings (other.mappings), binding_args (other.binding_args),
     317     74531846 :     regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
     318     74531846 :     trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
     319     74531846 : {}
     320              : 
     321              : SubstitutionArgumentMappings &
     322        41819 : SubstitutionArgumentMappings::operator= (
     323              :   const SubstitutionArgumentMappings &other)
     324              : {
     325        41819 :   mappings = other.mappings;
     326        41819 :   binding_args = other.binding_args;
     327        41819 :   regions = other.regions;
     328        41819 :   locus = other.locus;
     329        41819 :   param_subst_cb = nullptr;
     330        41819 :   trait_item_flag = other.trait_item_flag;
     331        41819 :   error_flag = other.error_flag;
     332              : 
     333        41819 :   return *this;
     334              : }
     335              : 
     336              : SubstitutionArgumentMappings
     337        46336 : SubstitutionArgumentMappings::error ()
     338              : {
     339        92672 :   return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
     340        46336 :                                        false, true);
     341              : }
     342              : 
     343              : SubstitutionArgumentMappings
     344     74131702 : SubstitutionArgumentMappings::empty (size_t num_regions)
     345              : {
     346    148263404 :   return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
     347     74131702 :                                        nullptr, false, false);
     348              : }
     349              : 
     350              : bool
     351        34278 : SubstitutionArgumentMappings::is_error () const
     352              : {
     353        34278 :   return error_flag;
     354              : }
     355              : 
     356              : bool
     357       153225 : SubstitutionArgumentMappings::get_argument_for_symbol (
     358              :   const BaseGeneric *param_to_find, SubstitutionArg *argument) const
     359              : {
     360       196548 :   for (const auto &mapping : mappings)
     361              :     {
     362       181372 :       const auto *p = mapping.get_param_ty ();
     363       181372 :       if (p->get_symbol () == param_to_find->get_symbol ())
     364              :         {
     365       138049 :           *argument = mapping;
     366       138049 :           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     73996408 : SubstitutionArgumentMappings::get_locus () const
     408              : {
     409     73996408 :   return locus;
     410              : }
     411              : 
     412              : size_t
     413        43152 : SubstitutionArgumentMappings::size () const
     414              : {
     415        43152 :   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        55813 : SubstitutionArgumentMappings::get_mappings ()
     426              : {
     427        55813 :   return mappings;
     428              : }
     429              : 
     430              : const std::vector<SubstitutionArg> &
     431    299143885 : SubstitutionArgumentMappings::get_mappings () const
     432              : {
     433    299143885 :   return mappings;
     434              : }
     435              : 
     436              : std::map<std::string, BaseType *> &
     437        61294 : SubstitutionArgumentMappings::get_binding_args ()
     438              : {
     439        61294 :   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        74882 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
     461              :                                               const SubstitutionArg &a) const
     462              : {
     463        74882 :   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     74216628 : SubstitutionRef::SubstitutionRef (
     484              :   std::vector<SubstitutionParamMapping> substitutions,
     485     74216628 :   SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
     486     74216628 :   : substitutions (substitutions), used_arguments (arguments),
     487    148433256 :     region_constraints (region_constraints)
     488     74216628 : {}
     489              : 
     490              : bool
     491       184777 : SubstitutionRef::has_substitutions () const
     492              : {
     493       184777 :   return substitutions.size () > 0;
     494              : }
     495              : 
     496              : std::string
     497      1838572 : SubstitutionRef::subst_as_string () const
     498              : {
     499      1838572 :   std::string buffer;
     500      2344093 :   for (size_t i = 0; i < substitutions.size (); i++)
     501              :     {
     502       505521 :       const SubstitutionParamMapping &sub = substitutions.at (i);
     503      1011042 :       buffer += sub.as_string ();
     504              : 
     505       505521 :       if ((i + 1) < substitutions.size ())
     506        58200 :         buffer += ", ";
     507              :     }
     508              : 
     509      2285893 :   return buffer.empty () ? "" : "<" + buffer + ">";
     510      1838572 : }
     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        95165 : SubstitutionRef::get_num_substitutions () const
     532              : {
     533        95165 :   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       130534 : SubstitutionRef::get_substs ()
     548              : {
     549       130534 :   return substitutions;
     550              : }
     551              : 
     552              : const std::vector<SubstitutionParamMapping> &
     553     73966946 : SubstitutionRef::get_substs () const
     554              : {
     555     73966946 :   return substitutions;
     556              : }
     557              : 
     558              : std::vector<SubstitutionParamMapping>
     559       172469 : SubstitutionRef::clone_substs () const
     560              : {
     561       172469 :   std::vector<SubstitutionParamMapping> clone;
     562       172469 :   clone.reserve (substitutions.size ());
     563              : 
     564       240947 :   for (auto &sub : substitutions)
     565        68478 :     clone.push_back (sub.clone ());
     566              : 
     567       172469 :   return clone;
     568              : }
     569              : 
     570              : void
     571         3964 : SubstitutionRef::override_context ()
     572              : {
     573         8451 :   for (auto &sub : substitutions)
     574              :     {
     575         4487 :       sub.override_context ();
     576              :     }
     577         3964 : }
     578              : 
     579              : bool
     580       156741 : SubstitutionRef::needs_substitution () const
     581              : {
     582       156741 :   return std::any_of (substitutions.begin (), substitutions.end (),
     583              :                       std::mem_fn (
     584       156741 :                         &SubstitutionParamMapping::needs_substitution));
     585              : }
     586              : 
     587              : bool
     588           63 : SubstitutionRef::was_substituted () const
     589              : {
     590           63 :   return !needs_substitution ();
     591              : }
     592              : 
     593              : SubstitutionArgumentMappings &
     594        54618 : SubstitutionRef::get_substitution_arguments ()
     595              : {
     596        54618 :   return used_arguments;
     597              : }
     598              : 
     599              : const SubstitutionArgumentMappings &
     600        24160 : SubstitutionRef::get_substitution_arguments () const
     601              : {
     602        24160 :   return used_arguments;
     603              : }
     604              : 
     605              : size_t
     606         9250 : SubstitutionRef::num_required_substitutions () const
     607              : {
     608         9250 :   size_t n = 0;
     609        20833 :   for (auto &p : substitutions)
     610              :     {
     611        11583 :       if (p.needs_substitution ())
     612        11256 :         n++;
     613              :     }
     614         9250 :   return n;
     615              : }
     616              : 
     617              : size_t
     618        18510 : SubstitutionRef::min_required_substitutions () const
     619              : {
     620        18510 :   size_t n = 0;
     621        41690 :   for (auto &p : substitutions)
     622              :     {
     623        23180 :       if (p.needs_substitution () && !p.param_has_default_ty ())
     624        19375 :         n++;
     625              :     }
     626        18510 :   return n;
     627              : }
     628              : 
     629              : const SubstitutionArgumentMappings &
     630        14065 : SubstitutionRef::get_used_arguments () const
     631              : {
     632        14065 :   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       171165 : SubstitutionRef::get_region_constraints () const
     648              : {
     649       171165 :   return region_constraints;
     650              : }
     651              : 
     652              : SubstitutionArgumentMappings
     653         9261 : SubstitutionRef::get_mappings_from_generic_args (
     654              :   HIR::GenericArgs &args, const std::vector<Region> &regions)
     655              : {
     656         9261 :   std::map<std::string, BaseType *> binding_arguments;
     657         9261 :   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         9260 :   size_t offs = used_arguments.size ();
     711         9260 :   size_t total_arguments
     712         9260 :     = args.get_type_args ().size () + args.get_const_args ().size () + offs;
     713         9260 :   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         9257 :   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         9254 :   std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
     750        19026 :   for (auto &arg : args.get_type_args ())
     751              :     {
     752         9776 :       BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
     753         9776 :       if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
     754              :         {
     755            4 :           return SubstitutionArgumentMappings::error ();
     756              :         }
     757              : 
     758         9776 :       const auto &param_mapping = substitutions.at (offs);
     759         9776 :       const auto &generic = param_mapping.get_generic_param ();
     760         9776 :       if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     761              :         {
     762         9773 :           const auto &type_param
     763              :             = static_cast<const HIR::TypeParam &> (generic);
     764         9773 :           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         9772 :       mappings.emplace_back (&param_mapping, resolved);
     787         9772 :       offs++;
     788              :     }
     789              : 
     790         9365 :   for (auto &arg : args.get_const_args ())
     791              :     {
     792          115 :       auto &expr = *arg.get_expression ().get ();
     793          115 :       BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
     794          230 :       if (expr_type == nullptr || expr_type->is<ErrorType> ())
     795            0 :         return SubstitutionArgumentMappings::error ();
     796              : 
     797              :       // validate this param is really a const generic
     798          115 :       const auto &param_mapping = substitutions.at (offs);
     799          115 :       const auto &generic = param_mapping.get_generic_param ();
     800          115 :       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          115 :       const auto base_generic = param_mapping.get_param_ty ();
     810          115 :       rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
     811          115 :       const auto const_param
     812          115 :         = static_cast<const TyTy::ConstParamType *> (base_generic);
     813          115 :       auto specified_type = const_param->get_specified_type ();
     814              : 
     815              :       // validate this const generic is of the correct type
     816          115 :       TyTy::BaseType *coereced_type = nullptr;
     817          115 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     818              :         {
     819           21 :           auto const_expr_type = expr_type->as_const_type ();
     820           21 :           auto const_value_type = const_expr_type->get_specified_type ();
     821           21 :           coereced_type
     822           21 :             = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
     823           21 :                                        TyTy::TyWithLocation (specified_type),
     824              :                                        TyTy::TyWithLocation (const_value_type,
     825           21 :                                                              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          230 :       if (coereced_type == nullptr || coereced_type->is<ErrorType> ())
     839            0 :         return SubstitutionArgumentMappings::error ();
     840              : 
     841          115 :       TyTy::BaseType *const_value_ty = nullptr;
     842          115 :       if (expr_type->get_kind () == TyTy::TypeKind::CONST)
     843           21 :         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          115 :       mappings.emplace_back (&param_mapping, const_value_ty);
     876          115 :       offs++;
     877              :     }
     878              : 
     879              :   // we must need to fill out defaults
     880         9250 :   size_t left_over
     881         9250 :     = num_required_substitutions () - min_required_substitutions ();
     882         9250 :   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         9250 :   return {mappings, binding_arguments,
     911        18500 :           RegionParamList::from_subst (used_arguments.get_regions ().size (),
     912              :                                        regions),
     913        27750 :           args.get_locus ()};
     914         9254 : }
     915              : 
     916              : BaseType *
     917         6659 : SubstitutionRef::infer_substitions (location_t locus)
     918              : {
     919         6659 :   std::vector<SubstitutionArg> args;
     920         6659 :   std::map<std::string, BaseType *> argument_mappings;
     921        14845 :   for (auto &p : get_substs ())
     922              :     {
     923         8186 :       if (p.needs_substitution ())
     924              :         {
     925         8117 :           const HIR::GenericParam &generic = p.get_generic_param ();
     926         8117 :           const std::string &symbol = p.get_param_ty ()->get_symbol ();
     927         8117 :           auto it = argument_mappings.find (symbol);
     928         8117 :           bool have_mapping = it != argument_mappings.end ();
     929              : 
     930         8117 :           if (have_mapping)
     931              :             {
     932          121 :               args.emplace_back (&p, it->second);
     933              :             }
     934         7996 :           else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
     935              :             {
     936         7977 :               TyVar infer_var = TyVar::get_implicit_infer_var (locus);
     937         7977 :               args.emplace_back (&p, infer_var.get_tyty ());
     938         7977 :               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         8117 :         }
     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         6659 :   SubstitutionArgumentMappings infer_arguments (std::move (args),
     958              :                                                 {} /* binding_arguments */,
     959              :                                                 used_arguments.get_regions (),
     960         6659 :                                                 locus);
     961         6659 :   return handle_substitions (infer_arguments);
     962         6659 : }
     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        15403 : SubstitutionRef::monomorphize ()
    1085              : {
    1086        24981 :   for (const auto &subst : get_substs ())
    1087              :     {
    1088         9578 :       const auto pty = subst.get_param_ty ();
    1089         9578 :       if (!pty->can_resolve ())
    1090          100 :         continue;
    1091              : 
    1092         9478 :       TyTy::BaseType *binding = pty->resolve ();
    1093         9478 :       if (binding->get_kind () == TyTy::TypeKind::PARAM)
    1094         2256 :         continue;
    1095              : 
    1096        15566 :       for (const auto &bound : pty->get_specified_bounds ())
    1097              :         {
    1098         8344 :           bool ambigious = false;
    1099         8344 :           auto associated
    1100         8344 :             = Resolver::lookup_associated_impl_block (bound, binding,
    1101              :                                                       &ambigious);
    1102         8344 :           if (associated != nullptr)
    1103         1946 :             associated->setup_associated_types (binding, bound);
    1104              :         }
    1105              :     }
    1106              : 
    1107        15403 :   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.