LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-subst.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 22 22
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 4 4
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              : #ifndef RUST_TYTY_SUBST_H
      20              : #define RUST_TYTY_SUBST_H
      21              : 
      22              : #include "rust-system.h"
      23              : #include "rust-location.h"
      24              : #include "rust-hir-full-decls.h"
      25              : #include "rust-tyty-region.h"
      26              : #include "rust-ast.h"
      27              : #include "optional.h"
      28              : 
      29              : namespace Rust {
      30              : namespace TyTy {
      31              : 
      32              : class ParamType;
      33              : class BaseGeneric;
      34              : 
      35     74664042 : struct RegionConstraints
      36              : {
      37              :   /** 'a: 'b */
      38              :   std::vector<std::pair<Region, Region>> region_region;
      39              :   /** T: 'a */
      40              :   std::vector<std::pair<ParamType *, Region>> type_region;
      41              : };
      42              : 
      43              : class BaseType;
      44              : class SubstitutionArgumentMappings;
      45              : class SubstitutionParamMapping
      46              : {
      47              : public:
      48              :   SubstitutionParamMapping (HIR::GenericParam &generic, BaseGeneric *param);
      49              : 
      50              :   SubstitutionParamMapping (const SubstitutionParamMapping &other);
      51              : 
      52              :   std::string as_string () const;
      53              : 
      54              :   bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
      55              :                       location_t locus, bool needs_bounds_check = true);
      56              : 
      57              :   SubstitutionParamMapping clone () const;
      58              : 
      59              :   BaseGeneric *get_param_ty ();
      60              :   const BaseGeneric *get_param_ty () const;
      61              : 
      62              :   HIR::GenericParam &get_generic_param ();
      63              :   const HIR::GenericParam &get_generic_param () const;
      64              : 
      65              :   Identifier get_type_representation () const;
      66              : 
      67              :   // this is used for the backend to override the HirId ref of the param to
      68              :   // what the concrete type is for the rest of the context
      69              :   void override_context ();
      70              : 
      71              :   bool needs_substitution () const;
      72              : 
      73              :   location_t get_param_locus () const;
      74              : 
      75              :   bool param_has_default_ty () const;
      76              : 
      77              :   BaseType *get_default_ty () const;
      78              : 
      79              :   bool need_substitution () const;
      80              : 
      81              : private:
      82              :   HIR::GenericParam &generic;
      83              :   BaseGeneric *param;
      84              : };
      85              : 
      86              : /**
      87              :  * Represents the part of the parameter list that contains lifetime
      88              :  * parameters.
      89              :  *
      90              :  * ```
      91              :  * Foo<'a, 'b, i32, 8>
      92              :  *     ^^^^^^
      93              :  * ```
      94              :  *
      95              :  * It has fixed size based on the number of lifetime parameters and they are
      96              :  * indexed based on their order.
      97              :  *
      98              :  * All regions are initially set to unresolved. When type instantiation is
      99              :  * encountered, all explicitly mentioned lifetimes are resolved to bound
     100              :  * lifetimes. The remaining unresolved lifetimes are set to anonymous. During
     101              :  * BIR construction, all lifetimes are replaced with free region variables.
     102              :  * Inference of anonymous regions happens automatically using BIR subtyping
     103              :  * pass.
     104              :  */
     105    445023432 : class RegionParamList
     106              : {
     107              :   std::vector<Region> regions;
     108              : 
     109              : public:
     110     74192714 :   RegionParamList (size_t num_regions) : regions (num_regions) {}
     111              : 
     112              :   Region *begin () { return regions.data (); }
     113              :   Region *end () { return regions.data () + regions.size (); }
     114            1 :   Region &operator[] (size_t index) { return regions.at (index); }
     115           44 :   const Region &operator[] (size_t index) const { return regions.at (index); }
     116         3079 :   WARN_UNUSED_RESULT const Region *begin () const { return regions.data (); }
     117         3079 :   WARN_UNUSED_RESULT const Region *end () const
     118              :   {
     119         3112 :     return regions.data () + regions.size ();
     120              :   }
     121        17130 :   size_t size () const { return regions.size (); }
     122              : 
     123              :   /**
     124              :    * Takes regions from the `subst` parameter and fills the rest with anonymous
     125              :    * regions.
     126              :    */
     127         9250 :   static RegionParamList from_subst (size_t num_regions,
     128              :                                      std::vector<Region> subst)
     129              :   {
     130         9250 :     RegionParamList list (num_regions);
     131         9276 :     for (size_t i = 0; i < MIN (num_regions, subst.size ()); i++)
     132           52 :       list.regions.at (i) = subst.at (i);
     133         9253 :     for (size_t i = subst.size (); i < num_regions; i++)
     134              :       {
     135            3 :         list.regions.at (i) = Region::make_anonymous ();
     136              :       }
     137         9250 :     return list;
     138              :   }
     139              : };
     140              : 
     141              : class SubstitutionArg
     142              : {
     143              : public:
     144              :   SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
     145              : 
     146              :   // FIXME
     147              :   // the copy constructors need removed - they are unsafe see
     148              :   // TypeBoundPredicate
     149              :   SubstitutionArg (const SubstitutionArg &other);
     150              : 
     151              :   SubstitutionArg &operator= (const SubstitutionArg &other);
     152              : 
     153              :   BaseType *get_tyty () const;
     154              : 
     155              :   const SubstitutionParamMapping *get_param_mapping () const;
     156              : 
     157              :   const BaseGeneric *get_param_ty () const;
     158              : 
     159              :   static SubstitutionArg error ();
     160              : 
     161              :   bool is_error () const;
     162              : 
     163              :   bool is_conrete () const;
     164              : 
     165              :   std::string as_string () const;
     166              : 
     167              : private:
     168              :   const SubstitutionParamMapping *param;
     169              :   const BaseGeneric *original_param;
     170              :   BaseType *argument;
     171              : };
     172              : 
     173              : typedef std::function<void (const ParamType &, const SubstitutionArg &)>
     174              :   ParamSubstCb;
     175              : class SubstitutionArgumentMappings
     176              : {
     177              : public:
     178              :   SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
     179              :                                 std::map<std::string, BaseType *> binding_args,
     180              :                                 RegionParamList regions, location_t locus,
     181              :                                 ParamSubstCb param_subst_cb = nullptr,
     182              :                                 bool trait_item_flag = false,
     183              :                                 bool error_flag = false);
     184              : 
     185              :   SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
     186              :   SubstitutionArgumentMappings &
     187              :   operator= (const SubstitutionArgumentMappings &other);
     188              : 
     189       163440 :   SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
     190     74026830 :   SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
     191              :     = default;
     192              : 
     193              :   static SubstitutionArgumentMappings error ();
     194              : 
     195              :   /** Creates empty substitution argument mappings with unresolved regions */
     196              :   static SubstitutionArgumentMappings empty (size_t num_regions = 0);
     197              : 
     198              :   static RegionParamList
     199         5195 :   regions_from_nullable_args (SubstitutionArgumentMappings *args)
     200              :   {
     201         5195 :     if (args == nullptr)
     202         4300 :       return RegionParamList (0);
     203              : 
     204          895 :     return args->get_regions ();
     205              :   }
     206              : 
     207              :   bool is_error () const;
     208              : 
     209              :   bool get_argument_for_symbol (const BaseGeneric *param_to_find,
     210              :                                 SubstitutionArg *argument) const;
     211              : 
     212              :   /** Return type parameter index for symbol */
     213              :   tl::optional<size_t> find_symbol (const ParamType &param_to_find) const;
     214              : 
     215              :   bool get_argument_at (size_t index, SubstitutionArg *argument);
     216              : 
     217              :   // is_concrete means if the used args is non error, ie: non empty this will
     218              :   // verify if actual real types have been put in place of are they still
     219              :   // ParamTy
     220              :   bool is_concrete () const;
     221              : 
     222              :   location_t get_locus () const;
     223              : 
     224              :   size_t size () const;
     225              : 
     226              :   bool is_empty () const;
     227              : 
     228              :   std::vector<SubstitutionArg> &get_mappings ();
     229              : 
     230              :   const std::vector<SubstitutionArg> &get_mappings () const;
     231              : 
     232              :   std::map<std::string, BaseType *> &get_binding_args ();
     233              : 
     234              :   const std::map<std::string, BaseType *> &get_binding_args () const;
     235              : 
     236              :   const RegionParamList &get_regions () const;
     237              :   RegionParamList &get_mut_regions ();
     238              : 
     239              :   std::string as_string () const;
     240              : 
     241              :   void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
     242              : 
     243              :   ParamSubstCb get_subst_cb () const;
     244              : 
     245              :   bool trait_item_mode () const;
     246              : 
     247              : private:
     248              :   std::vector<SubstitutionArg> mappings;
     249              :   std::map<std::string, BaseType *> binding_args;
     250              :   RegionParamList regions;
     251              :   location_t locus;
     252              :   ParamSubstCb param_subst_cb;
     253              :   bool trait_item_flag;
     254              :   bool error_flag;
     255              : };
     256              : 
     257              : class TypeBoundPredicateItem;
     258              : class SubstitutionRef
     259              : {
     260              : public:
     261              :   SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
     262              :                    SubstitutionArgumentMappings arguments,
     263              :                    RegionConstraints region_constraints);
     264              : 
     265              :   bool has_substitutions () const;
     266              : 
     267              :   std::string subst_as_string () const;
     268              : 
     269              :   bool supports_associated_bindings () const;
     270              : 
     271              :   // this is overridden in TypeBoundPredicate
     272              :   // which support bindings we don't add them directly to the SubstitutionRef
     273              :   // base class because this class represents the fn<X: Foo, Y: Bar>. The only
     274              :   // construct which supports associated types
     275              :   virtual size_t get_num_associated_bindings () const;
     276              : 
     277              :   // this is overridden in TypeBoundPredicate
     278              :   virtual TypeBoundPredicateItem
     279              :   lookup_associated_type (const std::string &search);
     280              : 
     281              :   size_t get_num_substitutions () const;
     282              : 
     283              :   size_t get_num_lifetime_params () const;
     284              : 
     285              :   size_t get_num_type_params () const;
     286              : 
     287              :   std::vector<SubstitutionParamMapping> &get_substs ();
     288              : 
     289              :   const std::vector<SubstitutionParamMapping> &get_substs () const;
     290              : 
     291              :   std::vector<SubstitutionParamMapping> clone_substs () const;
     292              : 
     293              :   void override_context ();
     294              : 
     295              :   bool needs_substitution () const;
     296              : 
     297              :   bool was_substituted () const;
     298              : 
     299              :   SubstitutionArgumentMappings &get_substitution_arguments ();
     300              :   const SubstitutionArgumentMappings &get_substitution_arguments () const;
     301              : 
     302              :   // this is the count of type params that are not substituted fuly
     303              :   size_t num_required_substitutions () const;
     304              : 
     305              :   // this is the count of type params that need substituted taking into account
     306              :   // possible defaults
     307              :   size_t min_required_substitutions () const;
     308              : 
     309              :   // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
     310              :   // in the case of Foo<i32,f32>{...}
     311              :   //
     312              :   // the substitions we have here define X,Y but the arguments have no bindings
     313              :   // so its a matter of ordering
     314              :   SubstitutionArgumentMappings
     315              :   get_mappings_from_generic_args (HIR::GenericArgs &args,
     316              :                                   const std::vector<Region> &regions);
     317              : 
     318              :   // Recursive substitutions
     319              :   // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
     320              :   //
     321              :   // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
     322              :   // Which binds to A,B
     323              :   SubstitutionArgumentMappings
     324              :   adjust_mappings_for_this (SubstitutionArgumentMappings &mappings,
     325              :                             bool trait_mode = false);
     326              : 
     327              :   // Are the mappings here actually bound to this type. For example imagine the
     328              :   // case:
     329              :   //
     330              :   // struct Foo<T>(T);
     331              :   // impl<T> Foo<T> {
     332              :   //   fn test(self) { ... }
     333              :   // }
     334              :   //
     335              :   // In this case we have a generic ADT of Foo and an impl block of a generic T
     336              :   // on Foo for the Self type. When we it comes to path resolution we can have:
     337              :   //
     338              :   // Foo::<i32>::test()
     339              :   //
     340              :   // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
     341              :   // Self ADT bound to the T from the impl block. This means when it comes to
     342              :   // the next segment of test which resolves to the function we need to check
     343              :   // wether the arguments in the struct definition of foo can be bound here
     344              :   // before substituting the previous segments type here. This functions acts as
     345              :   // a guard for the solve_mappings_from_receiver_for_self to handle the case
     346              :   // where arguments are not bound. This is important for this next case:
     347              :   //
     348              :   // struct Baz<A, B>(A, B);
     349              :   // impl Baz<i32, f32> {
     350              :   //   fn test<X>(a: X) -> X {
     351              :   //       a
     352              :   //   }
     353              :   // }
     354              :   //
     355              :   // In this case Baz has been already substituted for the impl's Self to become
     356              :   // ADT<i32, f32> so that the function test only has 1 generic argument of X.
     357              :   // The path for this will be:
     358              :   //
     359              :   // Baz::test::<_>(123)
     360              :   //
     361              :   // So the first segment here will be Baz<_, _> to try and infer the arguments
     362              :   // which will be taken from the impl's Self type in this case since it is
     363              :   // already substituted and like the previous case the check to see if we need
     364              :   // to inherit the previous segments generic arguments takes place but the
     365              :   // generic arguments are not bound to this type as they have already been
     366              :   // substituted.
     367              :   //
     368              :   // Its important to remember from the first example the FnType actually looks
     369              :   // like:
     370              :   //
     371              :   // fn <T>test(self :Foo<T>(T))
     372              :   //
     373              :   // As the generic parameters are "bound" to each of the items in the impl
     374              :   // block. So this check is about wether the arguments we have here can
     375              :   // actually be bound to this type.
     376              :   bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
     377              : 
     378              :   // struct Foo<A, B>(A, B);
     379              :   //
     380              :   // impl<T> Foo<T, f32>;
     381              :   //     -> fn test<X>(self, a: X) -> X
     382              :   //
     383              :   // We might invoke this via:
     384              :   //
     385              :   // a = Foo(123, 456f32);
     386              :   // b = a.test::<bool>(false);
     387              :   //
     388              :   // we need to figure out relevant generic arguemts for self to apply to the
     389              :   // fntype
     390              :   SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
     391              :     SubstitutionArgumentMappings &mappings) const;
     392              : 
     393              :   // Given a type such as:
     394              :   //
     395              :   //   fn<X,Y>(a:&X, b:Y) -> (...)
     396              :   //
     397              :   // This function will inject implicit inference variables for the type
     398              :   // parameters X and Y
     399              :   BaseType *infer_substitions (location_t locus);
     400              : 
     401              :   // this clears any possible projections from higher ranked trait bounds which
     402              :   // could be hanging around from a previous resolution
     403              :   void prepare_higher_ranked_bounds ();
     404              : 
     405              :   // FIXME
     406              :   // this is bad name for this, i think it should be something like
     407              :   // compute-higher-ranked-bounds
     408              :   bool monomorphize ();
     409              : 
     410              :   // TODO comment
     411              :   virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
     412              :     = 0;
     413              : 
     414              :   WARN_UNUSED_RESULT const SubstitutionArgumentMappings &
     415              :   get_used_arguments () const;
     416              : 
     417              :   WARN_UNUSED_RESULT tl::optional<SubstitutionArg> get_arg_at (size_t i) const;
     418              : 
     419              :   const RegionConstraints &get_region_constraints () const;
     420              : 
     421              : protected:
     422              :   std::vector<SubstitutionParamMapping> substitutions;
     423              :   SubstitutionArgumentMappings used_arguments;
     424              :   RegionConstraints region_constraints;
     425              : };
     426              : 
     427              : } // namespace TyTy
     428              : } // namespace Rust
     429              : #endif // RUST_TYTY_SUBST_H
        

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.