LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-tyty-subst.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.7 % 23 22
Test Date: 2026-10-03 16:17:38 Functions: 100.0 % 5 5
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      4140386 : 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     22938243 : class RegionParamList
     106              : {
     107              :   std::vector<Region> regions;
     108              : 
     109              : public:
     110      3866276 :   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         3393 :   WARN_UNUSED_RESULT const Region *begin () const { return regions.data (); }
     117         3393 :   WARN_UNUSED_RESULT const Region *end () const
     118              :   {
     119         3427 :     return regions.data () + regions.size ();
     120              :   }
     121        19936 :   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        10983 :   static RegionParamList from_subst (size_t num_regions,
     128              :                                      std::vector<Region> subst)
     129              :   {
     130        10983 :     RegionParamList list (num_regions);
     131        11009 :     for (size_t i = 0; i < MIN (num_regions, subst.size ()); i++)
     132           52 :       list.regions.at (i) = subst.at (i);
     133        10986 :     for (size_t i = subst.size (); i < num_regions; i++)
     134              :       {
     135            3 :         list.regions.at (i) = Region::make_anonymous ();
     136              :       }
     137        10983 :     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              : class SubstitutionArgumentMappings
     174              : {
     175              : public:
     176              :   SubstitutionArgumentMappings (
     177              :     std::vector<SubstitutionArg> mappings,
     178              :     std::map<std::string, BaseType *> binding_args, RegionParamList regions,
     179              :     location_t locus, bool trait_item_flag = false, bool error_flag = false,
     180              :     std::map<std::string, BaseType *> constraint_args = {});
     181              : 
     182              :   SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
     183              :   SubstitutionArgumentMappings &
     184              :   operator= (const SubstitutionArgumentMappings &other);
     185              : 
     186       126000 :   SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
     187      3688074 :   SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
     188              :     = default;
     189              : 
     190              :   static SubstitutionArgumentMappings error ();
     191              : 
     192              :   /** Creates empty substitution argument mappings with unresolved regions */
     193              :   static SubstitutionArgumentMappings empty (size_t num_regions = 0);
     194              : 
     195              :   static RegionParamList
     196          779 :   regions_from_nullable_args (SubstitutionArgumentMappings *args)
     197              :   {
     198          779 :     if (args == nullptr)
     199            0 :       return RegionParamList (0);
     200              : 
     201          779 :     return args->get_regions ();
     202              :   }
     203              : 
     204              :   bool is_error () const;
     205              : 
     206              :   bool get_argument_for_symbol (const BaseGeneric *param_to_find,
     207              :                                 SubstitutionArg *argument) const;
     208              : 
     209              :   /** Return type parameter index for symbol */
     210              :   tl::optional<size_t> find_symbol (const ParamType &param_to_find) const;
     211              : 
     212              :   bool get_argument_at (size_t index, SubstitutionArg *argument);
     213              : 
     214              :   // is_concrete means if the used args is non error, ie: non empty this will
     215              :   // verify if actual real types have been put in place of are they still
     216              :   // ParamTy
     217              :   bool is_concrete () const;
     218              : 
     219              :   location_t get_locus () const;
     220              : 
     221              :   size_t size () const;
     222              : 
     223              :   bool is_empty () const;
     224              : 
     225              :   std::vector<SubstitutionArg> &get_mappings ();
     226              : 
     227              :   const std::vector<SubstitutionArg> &get_mappings () const;
     228              : 
     229              :   std::map<std::string, BaseType *> &get_binding_args ();
     230              : 
     231              :   const std::map<std::string, BaseType *> &get_binding_args () const;
     232              : 
     233              :   const std::map<std::string, BaseType *> &get_constraint_args () const;
     234              : 
     235              :   const RegionParamList &get_regions () const;
     236              :   RegionParamList &get_mut_regions ();
     237              : 
     238              :   std::string as_string () const;
     239              : 
     240              :   bool trait_item_mode () const;
     241              : 
     242              : private:
     243              :   std::vector<SubstitutionArg> mappings;
     244              :   std::map<std::string, BaseType *> binding_args;
     245              :   std::map<std::string, BaseType *> constraint_args;
     246              :   RegionParamList regions;
     247              :   location_t locus;
     248              :   bool trait_item_flag;
     249              :   bool error_flag;
     250              : };
     251              : 
     252              : class TypeBoundPredicateItem;
     253              : class SubstitutionRef
     254              : {
     255              : public:
     256              :   SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
     257              :                    SubstitutionArgumentMappings arguments,
     258              :                    RegionConstraints region_constraints);
     259              : 
     260              :   bool has_substitutions () const;
     261              : 
     262              :   std::string subst_as_string () const;
     263              : 
     264              :   bool supports_associated_bindings () const;
     265              : 
     266              :   // this is overridden in TypeBoundPredicate
     267              :   // which support bindings we don't add them directly to the SubstitutionRef
     268              :   // base class because this class represents the fn<X: Foo, Y: Bar>. The only
     269              :   // construct which supports associated types
     270              :   virtual size_t get_num_associated_bindings () const;
     271              : 
     272              :   // Number of substitution params inherited from an outer scope (e.g. trait
     273              :   // params inherited by a GAT). These are not supplied by the user when writing
     274              :   // angle-bracket args and are skipped during arity checking.
     275         1420 :   virtual size_t get_outer_param_count () const { return 0; }
     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              :   // FIXME
     402              :   // this is bad name for this, i think it should be something like
     403              :   // compute-higher-ranked-bounds
     404              :   bool monomorphize ();
     405              : 
     406              :   // TODO comment
     407              :   virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
     408              :     = 0;
     409              : 
     410              :   WARN_UNUSED_RESULT const SubstitutionArgumentMappings &
     411              :   get_used_arguments () const;
     412              : 
     413              :   WARN_UNUSED_RESULT tl::optional<SubstitutionArg> get_arg_at (size_t i) const;
     414              : 
     415              :   const RegionConstraints &get_region_constraints () const;
     416              : 
     417              : protected:
     418              :   std::vector<SubstitutionParamMapping> substitutions;
     419              :   SubstitutionArgumentMappings used_arguments;
     420              :   RegionConstraints region_constraints;
     421              : };
     422              : 
     423              : } // namespace TyTy
     424              : } // namespace Rust
     425              : #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.