LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-subst.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.2 % 548 478
Test Date: 2026-10-24 16:24:59 Functions: 87.2 % 78 68
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.5.0-beta

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