(root)/
gcc-13.2.0/
gcc/
rust/
typecheck/
rust-tyty-subst.h
       1  // Copyright (C) 2020-2023 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-bounds.h"
      26  
      27  namespace Rust {
      28  namespace TyTy {
      29  
      30  class BaseType;
      31  class ParamType;
      32  class SubstitutionArgumentMappings;
      33  class SubstitutionParamMapping
      34  {
      35  public:
      36    SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
      37  
      38    SubstitutionParamMapping (const SubstitutionParamMapping &other);
      39  
      40    std::string as_string () const;
      41  
      42    bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
      43  		      Location locus);
      44  
      45    SubstitutionParamMapping clone () const;
      46  
      47    ParamType *get_param_ty ();
      48  
      49    const ParamType *get_param_ty () const;
      50  
      51    const HIR::TypeParam &get_generic_param () const;
      52  
      53    // this is used for the backend to override the HirId ref of the param to
      54    // what the concrete type is for the rest of the context
      55    void override_context ();
      56  
      57    bool needs_substitution () const;
      58  
      59    Location get_param_locus () const;
      60  
      61    bool param_has_default_ty () const;
      62  
      63    BaseType *get_default_ty () const;
      64  
      65    bool need_substitution () const;
      66  
      67  private:
      68    const HIR::TypeParam &generic;
      69    ParamType *param;
      70  };
      71  
      72  class SubstitutionArg
      73  {
      74  public:
      75    SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
      76  
      77    // FIXME
      78    // the copy constructors need removed - they are unsafe see
      79    // TypeBoundPredicate
      80    SubstitutionArg (const SubstitutionArg &other);
      81  
      82    SubstitutionArg &operator= (const SubstitutionArg &other);
      83  
      84    BaseType *get_tyty ();
      85  
      86    const BaseType *get_tyty () const;
      87  
      88    const SubstitutionParamMapping *get_param_mapping () const;
      89  
      90    static SubstitutionArg error ();
      91  
      92    bool is_error () const;
      93  
      94    bool is_conrete () const;
      95  
      96    std::string as_string () const;
      97  
      98  private:
      99    const SubstitutionParamMapping *param;
     100    BaseType *argument;
     101  };
     102  
     103  typedef std::function<void (const ParamType &, const SubstitutionArg &)>
     104    ParamSubstCb;
     105  class SubstitutionArgumentMappings
     106  {
     107  public:
     108    SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
     109  				std::map<std::string, BaseType *> binding_args,
     110  				Location locus,
     111  				ParamSubstCb param_subst_cb = nullptr,
     112  				bool trait_item_flag = false);
     113  
     114    SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
     115    SubstitutionArgumentMappings &
     116    operator= (const SubstitutionArgumentMappings &other);
     117  
     118    SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
     119    SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
     120      = default;
     121  
     122    static SubstitutionArgumentMappings error ();
     123  
     124    bool is_error () const;
     125  
     126    bool get_argument_for_symbol (const ParamType *param_to_find,
     127  				SubstitutionArg *argument);
     128  
     129    bool get_argument_at (size_t index, SubstitutionArg *argument);
     130  
     131    // is_concrete means if the used args is non error, ie: non empty this will
     132    // verify if actual real types have been put in place of are they still
     133    // ParamTy
     134    bool is_concrete () const;
     135  
     136    Location get_locus () const;
     137  
     138    size_t size () const;
     139  
     140    bool is_empty () const;
     141  
     142    std::vector<SubstitutionArg> &get_mappings ();
     143  
     144    const std::vector<SubstitutionArg> &get_mappings () const;
     145  
     146    std::map<std::string, BaseType *> &get_binding_args ();
     147  
     148    const std::map<std::string, BaseType *> &get_binding_args () const;
     149  
     150    std::string as_string () const;
     151  
     152    void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
     153  
     154    ParamSubstCb get_subst_cb () const;
     155  
     156    bool trait_item_mode () const;
     157  
     158  private:
     159    std::vector<SubstitutionArg> mappings;
     160    std::map<std::string, BaseType *> binding_args;
     161    Location locus;
     162    ParamSubstCb param_subst_cb;
     163    bool trait_item_flag;
     164  };
     165  
     166  class SubstitutionRef
     167  {
     168  public:
     169    SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
     170  		   SubstitutionArgumentMappings arguments);
     171  
     172    bool has_substitutions () const;
     173  
     174    std::string subst_as_string () const;
     175  
     176    bool supports_associated_bindings () const;
     177  
     178    // this is overridden in TypeBoundPredicate
     179    // which support bindings we don't add them directly to the SubstitutionRef
     180    // base class because this class represents the fn<X: Foo, Y: Bar>. The only
     181    // construct which supports associated types
     182    virtual size_t get_num_associated_bindings () const;
     183  
     184    // this is overridden in TypeBoundPredicate
     185    virtual TypeBoundPredicateItem
     186    lookup_associated_type (const std::string &search);
     187  
     188    size_t get_num_substitutions () const;
     189  
     190    std::vector<SubstitutionParamMapping> &get_substs ();
     191  
     192    const std::vector<SubstitutionParamMapping> &get_substs () const;
     193  
     194    std::vector<SubstitutionParamMapping> clone_substs () const;
     195  
     196    void override_context ();
     197  
     198    bool needs_substitution () const;
     199  
     200    bool was_substituted () const;
     201  
     202    SubstitutionArgumentMappings &get_substitution_arguments ();
     203    const SubstitutionArgumentMappings &get_substitution_arguments () const;
     204  
     205    // this is the count of type params that are not substituted fuly
     206    size_t num_required_substitutions () const;
     207  
     208    // this is the count of type params that need substituted taking into account
     209    // possible defaults
     210    size_t min_required_substitutions () const;
     211  
     212    // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
     213    // in the case of Foo<i32,f32>{...}
     214    //
     215    // the substitions we have here define X,Y but the arguments have no bindings
     216    // so its a matter of ordering
     217    SubstitutionArgumentMappings
     218    get_mappings_from_generic_args (HIR::GenericArgs &args);
     219  
     220    // Recursive substitutions
     221    // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
     222    //
     223    // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
     224    // Which binds to A,B
     225    SubstitutionArgumentMappings
     226    adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
     227  
     228    // Are the mappings here actually bound to this type. For example imagine the
     229    // case:
     230    //
     231    // struct Foo<T>(T);
     232    // impl<T> Foo<T> {
     233    //   fn test(self) { ... }
     234    // }
     235    //
     236    // In this case we have a generic ADT of Foo and an impl block of a generic T
     237    // on Foo for the Self type. When we it comes to path resolution we can have:
     238    //
     239    // Foo::<i32>::test()
     240    //
     241    // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
     242    // Self ADT bound to the T from the impl block. This means when it comes to
     243    // the next segment of test which resolves to the function we need to check
     244    // wether the arguments in the struct definition of foo can be bound here
     245    // before substituting the previous segments type here. This functions acts as
     246    // a guard for the solve_mappings_from_receiver_for_self to handle the case
     247    // where arguments are not bound. This is important for this next case:
     248    //
     249    // struct Baz<A, B>(A, B);
     250    // impl Baz<i32, f32> {
     251    //   fn test<X>(a: X) -> X {
     252    //       a
     253    //   }
     254    // }
     255    //
     256    // In this case Baz has been already substituted for the impl's Self to become
     257    // ADT<i32, f32> so that the function test only has 1 generic argument of X.
     258    // The path for this will be:
     259    //
     260    // Baz::test::<_>(123)
     261    //
     262    // So the first segment here will be Baz<_, _> to try and infer the arguments
     263    // which will be taken from the impl's Self type in this case since it is
     264    // already substituted and like the previous case the check to see if we need
     265    // to inherit the previous segments generic arguments takes place but the
     266    // generic arguments are not bound to this type as they have already been
     267    // substituted.
     268    //
     269    // Its important to remember from the first example the FnType actually looks
     270    // like:
     271    //
     272    // fn <T>test(self :Foo<T>(T))
     273    //
     274    // As the generic parameters are "bound" to each of the items in the impl
     275    // block. So this check is about wether the arguments we have here can
     276    // actually be bound to this type.
     277    bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
     278  
     279    // struct Foo<A, B>(A, B);
     280    //
     281    // impl<T> Foo<T, f32>;
     282    //     -> fn test<X>(self, a: X) -> X
     283    //
     284    // We might invoke this via:
     285    //
     286    // a = Foo(123, 456f32);
     287    // b = a.test::<bool>(false);
     288    //
     289    // we need to figure out relevant generic arguemts for self to apply to the
     290    // fntype
     291    SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
     292      SubstitutionArgumentMappings &mappings) const;
     293  
     294    // TODO comment
     295    SubstitutionArgumentMappings
     296    solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
     297  
     298    // TODO comment
     299    BaseType *infer_substitions (Location locus);
     300  
     301    // this clears any possible projections from higher ranked trait bounds which
     302    // could be hanging around from a previous resolution
     303    void prepare_higher_ranked_bounds ();
     304  
     305    // FIXME
     306    // this is bad name for this, i think it should be something like
     307    // compute-higher-ranked-bounds
     308    bool monomorphize ();
     309  
     310    // TODO comment
     311    virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
     312      = 0;
     313  
     314    SubstitutionArgumentMappings get_used_arguments () const;
     315  
     316  protected:
     317    Resolver::AssociatedImplTrait *lookup_associated_impl (
     318      const SubstitutionParamMapping &subst, const TypeBoundPredicate &bound,
     319      const TyTy::BaseType *binding, bool *error_flag) const;
     320  
     321    std::vector<SubstitutionParamMapping> substitutions;
     322    SubstitutionArgumentMappings used_arguments;
     323  };
     324  
     325  } // namespace TyTy
     326  } // namespace Rust
     327  #endif // RUST_TYTY_SUBST_H