libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / typecheck / rust-tyty-subst.h
blob4f0fab37b44fb3f06a5fb3ed83a80d14007eb0f7
1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
19 #ifndef RUST_TYTY_SUBST_H
20 #define RUST_TYTY_SUBST_H
22 #include "rust-system.h"
23 #include "rust-location.h"
24 #include "rust-hir-full-decls.h"
25 #include "rust-tyty-bounds.h"
26 #include "rust-tyty-region.h"
27 #include "optional.h"
29 namespace Rust {
30 namespace TyTy {
32 class ParamType;
34 struct RegionConstraints
36 /** 'a: 'b */
37 std::vector<std::pair<Region, Region>> region_region;
38 /** T: 'a */
39 std::vector<std::pair<ParamType *, Region>> type_region;
42 class BaseType;
43 class SubstitutionArgumentMappings;
44 class SubstitutionParamMapping
46 public:
47 SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
49 SubstitutionParamMapping (const SubstitutionParamMapping &other);
51 std::string as_string () const;
53 bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
54 location_t locus);
56 SubstitutionParamMapping clone () const;
58 ParamType *get_param_ty ();
60 const ParamType *get_param_ty () const;
62 const HIR::TypeParam &get_generic_param () const;
64 // this is used for the backend to override the HirId ref of the param to
65 // what the concrete type is for the rest of the context
66 void override_context ();
68 bool needs_substitution () const;
70 location_t get_param_locus () const;
72 bool param_has_default_ty () const;
74 BaseType *get_default_ty () const;
76 bool need_substitution () const;
78 private:
79 const HIR::TypeParam &generic;
80 ParamType *param;
83 /**
84 * Represents the part of the parameter list that contains lifetime
85 * parameters.
87 * ```
88 * Foo<'a, 'b, i32, 8>
89 * ^^^^^^
90 * ```
92 * It has fixed size based on the number of lifetime parameters and they are
93 * indexed based on their order.
95 * All regions are initially set to unresolved. When type instantiation is
96 * encountered, all explicitly mentioned lifetimes are resolved to bound
97 * lifetimes. The remaining unresolved lifetimes are set to anonymous. During
98 * BIR construction, all lifetimes are replaced with free region variables.
99 * Inference of anonymous regions happens automatically using BIR subtyping
100 * pass.
102 class RegionParamList
104 std::vector<Region> regions;
106 public:
107 RegionParamList (size_t num_regions) : regions (num_regions) {}
109 Region *begin () { return regions.data (); }
110 Region *end () { return regions.data () + regions.size (); }
111 Region &operator[] (size_t index) { return regions.at (index); }
112 const Region &operator[] (size_t index) const { return regions.at (index); }
113 WARN_UNUSED_RESULT const Region *begin () const { return regions.data (); }
114 WARN_UNUSED_RESULT const Region *end () const
116 return regions.data () + regions.size ();
118 size_t size () const { return regions.size (); }
121 * Takes regions from the `subst` parameter and fills the rest with anonymous
122 * regions.
124 static RegionParamList from_subst (size_t num_regions,
125 std::vector<Region> subst)
127 RegionParamList list (num_regions);
128 for (size_t i = 0; i < subst.size (); i++)
129 list.regions.at (i) = subst.at (i);
130 for (size_t i = subst.size (); i < num_regions; i++)
132 list.regions.at (i) = Region::make_anonymous ();
134 return list;
138 class SubstitutionArg
140 public:
141 SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
143 // FIXME
144 // the copy constructors need removed - they are unsafe see
145 // TypeBoundPredicate
146 SubstitutionArg (const SubstitutionArg &other);
148 SubstitutionArg &operator= (const SubstitutionArg &other);
150 BaseType *get_tyty ();
152 const BaseType *get_tyty () const;
154 const SubstitutionParamMapping *get_param_mapping () const;
156 const ParamType *get_param_ty () const;
158 static SubstitutionArg error ();
160 bool is_error () const;
162 bool is_conrete () const;
164 std::string as_string () const;
166 private:
167 const SubstitutionParamMapping *param;
168 const ParamType *original_param;
169 BaseType *argument;
172 typedef std::function<void (const ParamType &, const SubstitutionArg &)>
173 ParamSubstCb;
174 class SubstitutionArgumentMappings
176 public:
177 SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
178 std::map<std::string, BaseType *> binding_args,
179 RegionParamList regions, location_t locus,
180 ParamSubstCb param_subst_cb = nullptr,
181 bool trait_item_flag = false,
182 bool error_flag = false);
184 SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
185 SubstitutionArgumentMappings &
186 operator= (const SubstitutionArgumentMappings &other);
188 SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
189 SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
190 = default;
192 static SubstitutionArgumentMappings error ();
194 /** Creates empty substitution argument mappings with unresolved regions */
195 static SubstitutionArgumentMappings empty (size_t num_regions = 0);
197 static RegionParamList
198 regions_from_nullable_args (SubstitutionArgumentMappings *args)
200 if (args == nullptr)
201 return RegionParamList (0);
203 return args->get_regions ();
206 bool is_error () const;
208 bool get_argument_for_symbol (const ParamType *param_to_find,
209 SubstitutionArg *argument) const;
211 /** Return type parameter index for symbol */
212 tl::optional<size_t> find_symbol (const ParamType &param_to_find) const;
214 bool get_argument_at (size_t index, SubstitutionArg *argument);
216 // is_concrete means if the used args is non error, ie: non empty this will
217 // verify if actual real types have been put in place of are they still
218 // ParamTy
219 bool is_concrete () const;
221 location_t get_locus () const;
223 size_t size () const;
225 bool is_empty () const;
227 std::vector<SubstitutionArg> &get_mappings ();
229 const std::vector<SubstitutionArg> &get_mappings () const;
231 std::map<std::string, BaseType *> &get_binding_args ();
233 const std::map<std::string, BaseType *> &get_binding_args () const;
235 const RegionParamList &get_regions () const;
236 RegionParamList &get_mut_regions ();
238 std::string as_string () const;
240 void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
242 ParamSubstCb get_subst_cb () const;
244 bool trait_item_mode () const;
246 private:
247 std::vector<SubstitutionArg> mappings;
248 std::map<std::string, BaseType *> binding_args;
249 RegionParamList regions;
250 location_t locus;
251 ParamSubstCb param_subst_cb;
252 bool trait_item_flag;
253 bool error_flag;
256 class SubstitutionRef
258 public:
259 SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
260 SubstitutionArgumentMappings arguments,
261 RegionConstraints region_constraints);
263 bool has_substitutions () const;
265 std::string subst_as_string () const;
267 bool supports_associated_bindings () const;
269 // this is overridden in TypeBoundPredicate
270 // which support bindings we don't add them directly to the SubstitutionRef
271 // base class because this class represents the fn<X: Foo, Y: Bar>. The only
272 // construct which supports associated types
273 virtual size_t get_num_associated_bindings () const;
275 // this is overridden in TypeBoundPredicate
276 virtual TypeBoundPredicateItem
277 lookup_associated_type (const std::string &search);
279 size_t get_num_substitutions () const;
281 size_t get_num_lifetime_params () const;
283 size_t get_num_type_params () const;
285 std::vector<SubstitutionParamMapping> &get_substs ();
287 const std::vector<SubstitutionParamMapping> &get_substs () const;
289 std::vector<SubstitutionParamMapping> clone_substs () const;
291 void override_context ();
293 bool needs_substitution () const;
295 bool was_substituted () const;
297 SubstitutionArgumentMappings &get_substitution_arguments ();
298 const SubstitutionArgumentMappings &get_substitution_arguments () const;
300 // this is the count of type params that are not substituted fuly
301 size_t num_required_substitutions () const;
303 // this is the count of type params that need substituted taking into account
304 // possible defaults
305 size_t min_required_substitutions () const;
307 // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
308 // in the case of Foo<i32,f32>{...}
310 // the substitions we have here define X,Y but the arguments have no bindings
311 // so its a matter of ordering
312 SubstitutionArgumentMappings
313 get_mappings_from_generic_args (HIR::GenericArgs &args,
314 const std::vector<Region> &regions);
316 // Recursive substitutions
317 // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
319 // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
320 // Which binds to A,B
321 SubstitutionArgumentMappings
322 adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
324 // Are the mappings here actually bound to this type. For example imagine the
325 // case:
327 // struct Foo<T>(T);
328 // impl<T> Foo<T> {
329 // fn test(self) { ... }
330 // }
332 // In this case we have a generic ADT of Foo and an impl block of a generic T
333 // on Foo for the Self type. When we it comes to path resolution we can have:
335 // Foo::<i32>::test()
337 // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
338 // Self ADT bound to the T from the impl block. This means when it comes to
339 // the next segment of test which resolves to the function we need to check
340 // wether the arguments in the struct definition of foo can be bound here
341 // before substituting the previous segments type here. This functions acts as
342 // a guard for the solve_mappings_from_receiver_for_self to handle the case
343 // where arguments are not bound. This is important for this next case:
345 // struct Baz<A, B>(A, B);
346 // impl Baz<i32, f32> {
347 // fn test<X>(a: X) -> X {
348 // a
349 // }
350 // }
352 // In this case Baz has been already substituted for the impl's Self to become
353 // ADT<i32, f32> so that the function test only has 1 generic argument of X.
354 // The path for this will be:
356 // Baz::test::<_>(123)
358 // So the first segment here will be Baz<_, _> to try and infer the arguments
359 // which will be taken from the impl's Self type in this case since it is
360 // already substituted and like the previous case the check to see if we need
361 // to inherit the previous segments generic arguments takes place but the
362 // generic arguments are not bound to this type as they have already been
363 // substituted.
365 // Its important to remember from the first example the FnType actually looks
366 // like:
368 // fn <T>test(self :Foo<T>(T))
370 // As the generic parameters are "bound" to each of the items in the impl
371 // block. So this check is about wether the arguments we have here can
372 // actually be bound to this type.
373 bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
375 // struct Foo<A, B>(A, B);
377 // impl<T> Foo<T, f32>;
378 // -> fn test<X>(self, a: X) -> X
380 // We might invoke this via:
382 // a = Foo(123, 456f32);
383 // b = a.test::<bool>(false);
385 // we need to figure out relevant generic arguemts for self to apply to the
386 // fntype
387 SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
388 SubstitutionArgumentMappings &mappings) const;
390 // Given a type such as:
392 // fn<X,Y>(a:&X, b:Y) -> (...)
394 // This function will inject implicit inference variables for the type
395 // parameters X and Y
396 BaseType *infer_substitions (location_t locus);
398 // this clears any possible projections from higher ranked trait bounds which
399 // could be hanging around from a previous resolution
400 void prepare_higher_ranked_bounds ();
402 // FIXME
403 // this is bad name for this, i think it should be something like
404 // compute-higher-ranked-bounds
405 bool monomorphize ();
407 // TODO comment
408 virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
409 = 0;
411 WARN_UNUSED_RESULT const SubstitutionArgumentMappings &
412 get_used_arguments () const;
414 WARN_UNUSED_RESULT tl::optional<SubstitutionArg> get_arg_at (size_t i) const;
416 const RegionConstraints &get_region_constraints () const;
418 protected:
419 std::vector<SubstitutionParamMapping> substitutions;
420 SubstitutionArgumentMappings used_arguments;
421 RegionConstraints region_constraints;
424 } // namespace TyTy
425 } // namespace Rust
426 #endif // RUST_TYTY_SUBST_H