Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : 83592882 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
36 : 83592882 : BaseGeneric *param)
37 : 83592882 : : generic (generic), param (param)
38 : 83592882 : {}
39 : :
40 : 93348801 : SubstitutionParamMapping::SubstitutionParamMapping (
41 : 93348801 : const SubstitutionParamMapping &other)
42 : 93348801 : : generic (other.generic), param (other.param)
43 : 93348801 : {}
44 : :
45 : : std::string
46 : 505431 : SubstitutionParamMapping::as_string () const
47 : : {
48 : 505431 : if (param == nullptr)
49 : 0 : return "nullptr";
50 : :
51 : 505431 : return param->get_name ();
52 : : }
53 : :
54 : : SubstitutionParamMapping
55 : 83579507 : SubstitutionParamMapping::clone () const
56 : : {
57 : 83579507 : return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
58 : 83579507 : param->clone ()));
59 : : }
60 : :
61 : : BaseGeneric *
62 : 201061 : SubstitutionParamMapping::get_param_ty ()
63 : : {
64 : 201061 : return param;
65 : : }
66 : :
67 : : const BaseGeneric *
68 : 75843285 : SubstitutionParamMapping::get_param_ty () const
69 : : {
70 : 75843285 : return param;
71 : : }
72 : :
73 : : HIR::GenericParam &
74 : 16883 : SubstitutionParamMapping::get_generic_param ()
75 : : {
76 : 16883 : return generic;
77 : : }
78 : :
79 : : const HIR::GenericParam &
80 : 9874 : SubstitutionParamMapping::get_generic_param () const
81 : : {
82 : 9874 : return generic;
83 : : }
84 : :
85 : : bool
86 : 110161 : SubstitutionParamMapping::needs_substitution () const
87 : : {
88 : 110161 : return !(get_param_ty ()->is_concrete ());
89 : : }
90 : :
91 : : Identifier
92 : 2366 : SubstitutionParamMapping::get_type_representation () const
93 : : {
94 : 4732 : return param->get_symbol ();
95 : : }
96 : :
97 : : location_t
98 : 993 : SubstitutionParamMapping::get_param_locus () const
99 : : {
100 : 993 : return generic.get_locus ();
101 : : }
102 : :
103 : : bool
104 : 23619 : SubstitutionParamMapping::param_has_default_ty () const
105 : : {
106 : 23619 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
107 : : {
108 : 23371 : const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
109 : 23371 : return type_param.has_type ();
110 : : }
111 : :
112 : 248 : rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
113 : 248 : const auto &const_param
114 : : = static_cast<const HIR::ConstGenericParam &> (generic);
115 : 248 : return const_param.has_default_expression ();
116 : : }
117 : :
118 : : BaseType *
119 : 1137 : SubstitutionParamMapping::get_default_ty () const
120 : : {
121 : 1137 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
122 : : {
123 : 1132 : const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
124 : 1132 : TyVar var (type_param.get_type_mappings ().get_hirid ());
125 : 1132 : 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 : 37442 : SubstitutionParamMapping::fill_param_ty (
150 : : SubstitutionArgumentMappings &subst_mappings, location_t locus,
151 : : bool needs_bounds_check)
152 : : {
153 : 37442 : SubstitutionArg arg = SubstitutionArg::error ();
154 : 37442 : bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
155 : 37442 : if (!ok)
156 : : return true;
157 : :
158 : 37442 : TyTy::BaseType &type = *arg.get_tyty ();
159 : 37442 : if (type.get_kind () == TyTy::TypeKind::INFER)
160 : : {
161 : 12107 : type.inherit_bounds (*param);
162 : : }
163 : :
164 : 37442 : if (type.get_kind () == TypeKind::PARAM)
165 : : {
166 : 7303 : param = static_cast<BaseGeneric *> (type.clone ());
167 : : }
168 : 30139 : else if (type.get_kind () == TyTy::TypeKind::CONST)
169 : : {
170 : 203 : rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
171 : 203 : auto *const_type = type.as_const_type ();
172 : 203 : if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
173 : 21 : param = static_cast<BaseGeneric *> (type.clone ());
174 : : else
175 : 182 : param->set_ty_ref (type.get_ref ());
176 : : }
177 : 29936 : else if (param->get_kind () == TypeKind::PARAM)
178 : : {
179 : 29936 : auto &p = *static_cast<TyTy::ParamType *> (param);
180 : :
181 : : // check the substitution is compatible with bounds
182 : 29936 : rust_debug_loc (locus,
183 : : "fill_param_ty bounds_compatible: param %s type %s",
184 : 59872 : param->get_name ().c_str (), type.get_name ().c_str ());
185 : 29936 : if (needs_bounds_check && !p.is_implicit_self_trait ())
186 : : {
187 : 14885 : if (!param->bounds_compatible (type, locus, true))
188 : : return false;
189 : : }
190 : :
191 : : // recursively pass this down to all HRTB's
192 : 66702 : for (auto &bound : param->get_specified_bounds ())
193 : 36772 : bound.handle_substitions (subst_mappings);
194 : :
195 : 29930 : param->set_ty_ref (type.get_ref ());
196 : 29930 : subst_mappings.on_param_subst (p, arg);
197 : : }
198 : :
199 : : return true;
200 : : }
201 : :
202 : : void
203 : 4487 : SubstitutionParamMapping::override_context ()
204 : : {
205 : 4487 : if (!param->can_resolve ())
206 : : return;
207 : :
208 : 4473 : auto &mappings = Analysis::Mappings::get ();
209 : 4473 : auto context = Resolver::TypeCheckContext::get ();
210 : :
211 : 4473 : context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
212 : : UNKNOWN_NODEID,
213 : 4473 : param->get_ref (),
214 : 4473 : UNKNOWN_LOCAL_DEFID),
215 : 4473 : param->resolve ());
216 : : }
217 : :
218 : 75861848 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
219 : 75861848 : BaseType *argument)
220 : 75861848 : : param (param), argument (argument)
221 : : {
222 : 75861848 : if (param != nullptr)
223 : 75692805 : original_param = param->get_param_ty ();
224 : 75861848 : }
225 : :
226 : 306029576 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
227 : 306029576 : : param (other.param), original_param (other.original_param),
228 : 306029576 : argument (other.argument)
229 : 306029576 : {}
230 : :
231 : : SubstitutionArg &
232 : 161655 : SubstitutionArg::operator= (const SubstitutionArg &other)
233 : : {
234 : 161655 : param = other.param;
235 : 161655 : argument = other.argument;
236 : 161655 : original_param = other.original_param;
237 : :
238 : 161655 : return *this;
239 : : }
240 : :
241 : : BaseType *
242 : 78380860 : SubstitutionArg::get_tyty () const
243 : : {
244 : 78380860 : return argument;
245 : : }
246 : :
247 : : const SubstitutionParamMapping *
248 : 8343 : SubstitutionArg::get_param_mapping () const
249 : : {
250 : 8343 : return param;
251 : : }
252 : :
253 : : const BaseGeneric *
254 : 181293 : SubstitutionArg::get_param_ty () const
255 : : {
256 : 181293 : return original_param;
257 : : }
258 : :
259 : : SubstitutionArg
260 : 169043 : SubstitutionArg::error ()
261 : : {
262 : 169043 : return SubstitutionArg (nullptr, nullptr);
263 : : }
264 : :
265 : : bool
266 : 63425 : SubstitutionArg::is_error () const
267 : : {
268 : 63425 : return param == nullptr || argument == nullptr;
269 : : }
270 : :
271 : : bool
272 : 0 : SubstitutionArg::is_conrete () const
273 : : {
274 : 0 : if (argument == nullptr)
275 : : return false;
276 : :
277 : 0 : if (argument->get_kind () == TyTy::TypeKind::PARAM)
278 : : return false;
279 : :
280 : 0 : return argument->is_concrete ();
281 : : }
282 : :
283 : : std::string
284 : 0 : SubstitutionArg::as_string () const
285 : : {
286 : 0 : return original_param->as_string ()
287 : 0 : + (argument != nullptr ? ":" + argument->as_string () : "");
288 : : }
289 : :
290 : : const RegionParamList &
291 : 73983681 : SubstitutionArgumentMappings::get_regions () const
292 : : {
293 : 73983681 : return regions;
294 : : }
295 : :
296 : : RegionParamList &
297 : 2046 : SubstitutionArgumentMappings::get_mut_regions ()
298 : : {
299 : 2046 : return regions;
300 : : }
301 : :
302 : : // SubstitutionArgumentMappings
303 : :
304 : 148148773 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
305 : : std::vector<SubstitutionArg> mappings,
306 : : std::map<std::string, BaseType *> binding_args, RegionParamList regions,
307 : : location_t locus, ParamSubstCb param_subst_cb, bool trait_item_flag,
308 : 148148773 : bool error_flag)
309 : 148148773 : : mappings (std::move (mappings)), binding_args (binding_args),
310 : 148148773 : regions (regions), locus (locus), param_subst_cb (param_subst_cb),
311 : 148148773 : trait_item_flag (trait_item_flag), error_flag (error_flag)
312 : 148148773 : {}
313 : :
314 : 74525711 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
315 : 74525711 : const SubstitutionArgumentMappings &other)
316 : 74525711 : : mappings (other.mappings), binding_args (other.binding_args),
317 : 74525711 : regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
318 : 74525711 : trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
319 : 74525711 : {}
320 : :
321 : : SubstitutionArgumentMappings &
322 : 41765 : SubstitutionArgumentMappings::operator= (
323 : : const SubstitutionArgumentMappings &other)
324 : : {
325 : 41765 : mappings = other.mappings;
326 : 41765 : binding_args = other.binding_args;
327 : 41765 : regions = other.regions;
328 : 41765 : locus = other.locus;
329 : 41765 : param_subst_cb = nullptr;
330 : 41765 : trait_item_flag = other.trait_item_flag;
331 : 41765 : error_flag = other.error_flag;
332 : :
333 : 41765 : return *this;
334 : : }
335 : :
336 : : SubstitutionArgumentMappings
337 : 46308 : SubstitutionArgumentMappings::error ()
338 : : {
339 : 92616 : return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
340 : 46308 : false, true);
341 : : }
342 : :
343 : : SubstitutionArgumentMappings
344 : 74126340 : SubstitutionArgumentMappings::empty (size_t num_regions)
345 : : {
346 : 148252680 : return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
347 : 74126340 : nullptr, false, false);
348 : : }
349 : :
350 : : bool
351 : 34245 : SubstitutionArgumentMappings::is_error () const
352 : : {
353 : 34245 : return error_flag;
354 : : }
355 : :
356 : : bool
357 : 153118 : SubstitutionArgumentMappings::get_argument_for_symbol (
358 : : const BaseGeneric *param_to_find, SubstitutionArg *argument) const
359 : : {
360 : 196434 : for (const auto &mapping : mappings)
361 : : {
362 : 181293 : const auto *p = mapping.get_param_ty ();
363 : 181293 : if (p->get_symbol () == param_to_find->get_symbol ())
364 : : {
365 : 137977 : *argument = mapping;
366 : 137977 : return true;
367 : : }
368 : : }
369 : : return false;
370 : : }
371 : : tl::optional<size_t>
372 : 0 : SubstitutionArgumentMappings::find_symbol (const ParamType ¶m_to_find) const
373 : : {
374 : 0 : auto it = std::find_if (mappings.begin (), mappings.end (),
375 : 0 : [param_to_find] (const SubstitutionArg &arg) {
376 : 0 : return arg.get_param_ty ()->get_symbol ()
377 : 0 : == param_to_find.get_symbol ();
378 : : });
379 : 0 : if (it == mappings.end ())
380 : 0 : return tl::nullopt;
381 : 0 : return std::distance (mappings.begin (), it);
382 : : }
383 : :
384 : : bool
385 : 15925 : SubstitutionArgumentMappings::get_argument_at (size_t index,
386 : : SubstitutionArg *argument)
387 : : {
388 : 15925 : if (index > mappings.size ())
389 : : return false;
390 : :
391 : 15925 : *argument = mappings.at (index);
392 : 15925 : return true;
393 : : }
394 : :
395 : : bool
396 : 0 : SubstitutionArgumentMappings::is_concrete () const
397 : : {
398 : 0 : for (auto &mapping : mappings)
399 : : {
400 : 0 : if (!mapping.is_conrete ())
401 : 0 : return false;
402 : : }
403 : : return true;
404 : : }
405 : :
406 : : location_t
407 : 73991286 : SubstitutionArgumentMappings::get_locus () const
408 : : {
409 : 73991286 : return locus;
410 : : }
411 : :
412 : : size_t
413 : 43115 : SubstitutionArgumentMappings::size () const
414 : : {
415 : 43115 : return mappings.size ();
416 : : }
417 : :
418 : : bool
419 : 15632 : SubstitutionArgumentMappings::is_empty () const
420 : : {
421 : 15632 : return size () == 0;
422 : : }
423 : :
424 : : std::vector<SubstitutionArg> &
425 : 55718 : SubstitutionArgumentMappings::get_mappings ()
426 : : {
427 : 55718 : return mappings;
428 : : }
429 : :
430 : : const std::vector<SubstitutionArg> &
431 : 299123523 : SubstitutionArgumentMappings::get_mappings () const
432 : : {
433 : 299123523 : return mappings;
434 : : }
435 : :
436 : : std::map<std::string, BaseType *> &
437 : 61253 : SubstitutionArgumentMappings::get_binding_args ()
438 : : {
439 : 61253 : return binding_args;
440 : : }
441 : :
442 : : const std::map<std::string, BaseType *> &
443 : 0 : SubstitutionArgumentMappings::get_binding_args () const
444 : : {
445 : 0 : return binding_args;
446 : : }
447 : :
448 : : std::string
449 : 0 : SubstitutionArgumentMappings::as_string () const
450 : : {
451 : 0 : std::string buffer;
452 : 0 : for (auto &mapping : mappings)
453 : : {
454 : 0 : buffer += mapping.as_string () + ", ";
455 : : }
456 : 0 : return "<" + buffer + ">";
457 : 0 : }
458 : :
459 : : void
460 : 74841 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
461 : : const SubstitutionArg &a) const
462 : : {
463 : 74841 : if (param_subst_cb == nullptr)
464 : : return;
465 : :
466 : 575 : param_subst_cb (p, a);
467 : : }
468 : :
469 : : ParamSubstCb
470 : 19834 : SubstitutionArgumentMappings::get_subst_cb () const
471 : : {
472 : 19834 : return param_subst_cb;
473 : : }
474 : :
475 : : bool
476 : 14453 : SubstitutionArgumentMappings::trait_item_mode () const
477 : : {
478 : 14453 : return trait_item_flag;
479 : : }
480 : :
481 : : // SubstitutionRef
482 : :
483 : 74210952 : SubstitutionRef::SubstitutionRef (
484 : : std::vector<SubstitutionParamMapping> substitutions,
485 : 74210952 : SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
486 : 74210952 : : substitutions (substitutions), used_arguments (arguments),
487 : 148421904 : region_constraints (region_constraints)
488 : 74210952 : {}
489 : :
490 : : bool
491 : 184716 : SubstitutionRef::has_substitutions () const
492 : : {
493 : 184716 : return substitutions.size () > 0;
494 : : }
495 : :
496 : : std::string
497 : 1837831 : SubstitutionRef::subst_as_string () const
498 : : {
499 : 1837831 : std::string buffer;
500 : 2343262 : for (size_t i = 0; i < substitutions.size (); i++)
501 : : {
502 : 505431 : const SubstitutionParamMapping &sub = substitutions.at (i);
503 : 1010862 : buffer += sub.as_string ();
504 : :
505 : 505431 : if ((i + 1) < substitutions.size ())
506 : 58200 : buffer += ", ";
507 : : }
508 : :
509 : 2285062 : return buffer.empty () ? "" : "<" + buffer + ">";
510 : 1837831 : }
511 : :
512 : : bool
513 : 73 : SubstitutionRef::supports_associated_bindings () const
514 : : {
515 : 73 : return get_num_associated_bindings () > 0;
516 : : }
517 : :
518 : : size_t
519 : 1 : SubstitutionRef::get_num_associated_bindings () const
520 : : {
521 : 1 : return 0;
522 : : }
523 : :
524 : : TypeBoundPredicateItem
525 : 0 : SubstitutionRef::lookup_associated_type (const std::string &search)
526 : : {
527 : 0 : return TypeBoundPredicateItem::error ();
528 : : }
529 : :
530 : : size_t
531 : 95052 : SubstitutionRef::get_num_substitutions () const
532 : : {
533 : 95052 : return substitutions.size ();
534 : : }
535 : : size_t
536 : 135 : SubstitutionRef::get_num_lifetime_params () const
537 : : {
538 : 135 : return used_arguments.get_regions ().size ();
539 : : }
540 : : size_t
541 : 538 : SubstitutionRef::get_num_type_params () const
542 : : {
543 : 538 : return get_num_substitutions ();
544 : : }
545 : :
546 : : std::vector<SubstitutionParamMapping> &
547 : 130342 : SubstitutionRef::get_substs ()
548 : : {
549 : 130342 : return substitutions;
550 : : }
551 : :
552 : : const std::vector<SubstitutionParamMapping> &
553 : 73961791 : SubstitutionRef::get_substs () const
554 : : {
555 : 73961791 : return substitutions;
556 : : }
557 : :
558 : : std::vector<SubstitutionParamMapping>
559 : 172094 : SubstitutionRef::clone_substs () const
560 : : {
561 : 172094 : std::vector<SubstitutionParamMapping> clone;
562 : 172094 : clone.reserve (substitutions.size ());
563 : :
564 : 240542 : for (auto &sub : substitutions)
565 : 68448 : clone.push_back (sub.clone ());
566 : :
567 : 172094 : return clone;
568 : : }
569 : :
570 : : void
571 : 3964 : SubstitutionRef::override_context ()
572 : : {
573 : 8451 : for (auto &sub : substitutions)
574 : : {
575 : 4487 : sub.override_context ();
576 : : }
577 : 3964 : }
578 : :
579 : : bool
580 : 156582 : SubstitutionRef::needs_substitution () const
581 : : {
582 : 156582 : return std::any_of (substitutions.begin (), substitutions.end (),
583 : : std::mem_fn (
584 : 156582 : &SubstitutionParamMapping::needs_substitution));
585 : : }
586 : :
587 : : bool
588 : 63 : SubstitutionRef::was_substituted () const
589 : : {
590 : 63 : return !needs_substitution ();
591 : : }
592 : :
593 : : SubstitutionArgumentMappings &
594 : 54596 : SubstitutionRef::get_substitution_arguments ()
595 : : {
596 : 54596 : return used_arguments;
597 : : }
598 : :
599 : : const SubstitutionArgumentMappings &
600 : 24157 : SubstitutionRef::get_substitution_arguments () const
601 : : {
602 : 24157 : return used_arguments;
603 : : }
604 : :
605 : : size_t
606 : 9228 : SubstitutionRef::num_required_substitutions () const
607 : : {
608 : 9228 : size_t n = 0;
609 : 20789 : for (auto &p : substitutions)
610 : : {
611 : 11561 : if (p.needs_substitution ())
612 : 11234 : n++;
613 : : }
614 : 9228 : return n;
615 : : }
616 : :
617 : : size_t
618 : 18466 : SubstitutionRef::min_required_substitutions () const
619 : : {
620 : 18466 : size_t n = 0;
621 : 41602 : for (auto &p : substitutions)
622 : : {
623 : 23136 : if (p.needs_substitution () && !p.param_has_default_ty ())
624 : 19331 : n++;
625 : : }
626 : 18466 : return n;
627 : : }
628 : :
629 : : const SubstitutionArgumentMappings &
630 : 13999 : SubstitutionRef::get_used_arguments () const
631 : : {
632 : 13999 : return used_arguments;
633 : : }
634 : :
635 : : tl::optional<SubstitutionArg>
636 : 168 : SubstitutionRef::get_arg_at (size_t i) const
637 : : {
638 : 168 : auto param_ty = get_substs ().at (i).get_param_ty ();
639 : 168 : SubstitutionArg arg = SubstitutionArg::error ();
640 : 168 : get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
641 : 168 : if (arg.is_error ())
642 : 8 : return tl::nullopt;
643 : 160 : return arg;
644 : : }
645 : :
646 : : const RegionConstraints &
647 : 170818 : SubstitutionRef::get_region_constraints () const
648 : : {
649 : 170818 : return region_constraints;
650 : : }
651 : :
652 : : SubstitutionArgumentMappings
653 : 9239 : SubstitutionRef::get_mappings_from_generic_args (
654 : : HIR::GenericArgs &args, const std::vector<Region> ®ions)
655 : : {
656 : 9239 : std::map<std::string, BaseType *> binding_arguments;
657 : 9239 : if (args.get_binding_args ().size () > 0)
658 : : {
659 : 73 : if (supports_associated_bindings ())
660 : : {
661 : 72 : if (args.get_binding_args ().size () > get_num_associated_bindings ())
662 : : {
663 : 0 : rich_location r (line_table, args.get_locus ());
664 : 0 : rust_error_at (r,
665 : : "generic item takes at most %lu type binding "
666 : : "arguments but %lu were supplied",
667 : 0 : (unsigned long) get_num_associated_bindings (),
668 : 0 : (unsigned long) args.get_binding_args ().size ());
669 : 0 : return SubstitutionArgumentMappings::error ();
670 : 0 : }
671 : :
672 : 144 : for (auto &binding : args.get_binding_args ())
673 : : {
674 : 72 : BaseType *resolved
675 : 72 : = Resolver::TypeCheckType::Resolve (binding.get_type ());
676 : 72 : if (resolved == nullptr
677 : 72 : || resolved->get_kind () == TyTy::TypeKind::ERROR)
678 : : {
679 : 0 : return SubstitutionArgumentMappings::error ();
680 : : }
681 : :
682 : : // resolve to relevant binding
683 : 72 : auto binding_item = lookup_associated_type (
684 : 72 : binding.get_identifier ().as_string ());
685 : 72 : if (binding_item.is_error ())
686 : : {
687 : 0 : rust_error_at (
688 : : binding.get_locus (), "unknown associated type binding: %s",
689 : 0 : binding.get_identifier ().as_string ().c_str ());
690 : 0 : return SubstitutionArgumentMappings::error ();
691 : : }
692 : :
693 : 72 : binding_arguments[binding.get_identifier ().as_string ()]
694 : 72 : = resolved;
695 : 72 : }
696 : : }
697 : : else
698 : : {
699 : 1 : rich_location r (line_table, args.get_locus ());
700 : 3 : for (auto &binding : args.get_binding_args ())
701 : 2 : r.add_range (binding.get_locus ());
702 : :
703 : 1 : rust_error_at (r, ErrorCode::E0229,
704 : : "associated type bindings are not allowed here");
705 : 1 : return SubstitutionArgumentMappings::error ();
706 : 1 : }
707 : : }
708 : :
709 : : // for inherited arguments
710 : 9238 : size_t offs = used_arguments.size ();
711 : 9238 : size_t total_arguments
712 : 9238 : = args.get_type_args ().size () + args.get_const_args ().size () + offs;
713 : 9238 : if (total_arguments > substitutions.size ())
714 : : {
715 : 3 : rich_location r (line_table, args.get_locus ());
716 : 3 : if (!substitutions.empty ())
717 : : {
718 : 2 : const auto &subst = substitutions.front ();
719 : 2 : const auto &generic = subst.get_generic_param ();
720 : 2 : r.add_range (generic.get_locus ());
721 : : }
722 : :
723 : 6 : rust_error_at (
724 : : r,
725 : : "generic item takes at most %lu type arguments but %lu were supplied",
726 : 3 : (unsigned long) substitutions.size (),
727 : 3 : (unsigned long) args.get_type_args ().size ());
728 : 3 : return SubstitutionArgumentMappings::error ();
729 : 3 : }
730 : :
731 : 9235 : if (total_arguments < min_required_substitutions ())
732 : : {
733 : 3 : rich_location r (line_table, args.get_locus ());
734 : 3 : if (!substitutions.empty ())
735 : : {
736 : 3 : const auto &subst = substitutions.front ();
737 : 3 : const auto &generic = subst.get_generic_param ();
738 : 3 : r.add_range (generic.get_locus ());
739 : : }
740 : :
741 : 6 : rust_error_at (
742 : : r, ErrorCode::E0107,
743 : : "generic item takes at least %lu type arguments but %lu were supplied",
744 : 3 : (unsigned long) (min_required_substitutions () - offs),
745 : 3 : (unsigned long) args.get_type_args ().size ());
746 : 3 : return SubstitutionArgumentMappings::error ();
747 : 3 : }
748 : :
749 : 9232 : std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
750 : 18982 : for (auto &arg : args.get_type_args ())
751 : : {
752 : 9754 : BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
753 : 9754 : if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
754 : : {
755 : 4 : return SubstitutionArgumentMappings::error ();
756 : : }
757 : :
758 : 9754 : const auto ¶m_mapping = substitutions.at (offs);
759 : 9754 : const auto &generic = param_mapping.get_generic_param ();
760 : 9754 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
761 : : {
762 : 9751 : const auto &type_param
763 : : = static_cast<const HIR::TypeParam &> (generic);
764 : 9751 : if (type_param.from_impl_trait ())
765 : : {
766 : 1 : rich_location r (line_table, arg->get_locus ());
767 : 1 : r.add_fixit_remove (arg->get_locus ());
768 : 1 : rust_error_at (r, ErrorCode::E0632,
769 : : "cannot provide explicit generic arguments when "
770 : : "%<impl Trait%> is used in argument position");
771 : 1 : return SubstitutionArgumentMappings::error ();
772 : 1 : }
773 : : }
774 : 3 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
775 : : {
776 : 3 : if (resolved->get_kind () != TyTy::TypeKind::CONST)
777 : : {
778 : 3 : rich_location r (line_table, arg->get_locus ());
779 : 3 : r.add_fixit_remove (arg->get_locus ());
780 : 3 : rust_error_at (r, ErrorCode::E0747,
781 : : "type provided when a constant was expected");
782 : 3 : return SubstitutionArgumentMappings::error ();
783 : 3 : }
784 : : }
785 : :
786 : 9750 : mappings.emplace_back (¶m_mapping, resolved);
787 : 9750 : offs++;
788 : : }
789 : :
790 : 9343 : for (auto &arg : args.get_const_args ())
791 : : {
792 : 115 : auto &expr = *arg.get_expression ().get ();
793 : 115 : BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
794 : 230 : if (expr_type == nullptr || expr_type->is<ErrorType> ())
795 : 0 : return SubstitutionArgumentMappings::error ();
796 : :
797 : : // validate this param is really a const generic
798 : 115 : const auto ¶m_mapping = substitutions.at (offs);
799 : 115 : const auto &generic = param_mapping.get_generic_param ();
800 : 115 : if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
801 : : {
802 : 0 : rich_location r (line_table, arg.get_locus ());
803 : 0 : r.add_fixit_remove (expr.get_locus ());
804 : 0 : rust_error_at (r, "invalid position for a const generic argument");
805 : 0 : return SubstitutionArgumentMappings::error ();
806 : 0 : }
807 : :
808 : : // get the const generic specified type
809 : 115 : const auto base_generic = param_mapping.get_param_ty ();
810 : 115 : rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
811 : 115 : const auto const_param
812 : 115 : = static_cast<const TyTy::ConstParamType *> (base_generic);
813 : 115 : auto specified_type = const_param->get_specified_type ();
814 : :
815 : : // validate this const generic is of the correct type
816 : 115 : TyTy::BaseType *coereced_type = nullptr;
817 : 115 : if (expr_type->get_kind () == TyTy::TypeKind::CONST)
818 : : {
819 : 21 : auto const_expr_type = expr_type->as_const_type ();
820 : 21 : auto const_value_type = const_expr_type->get_specified_type ();
821 : 21 : coereced_type
822 : 21 : = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
823 : 21 : TyTy::TyWithLocation (specified_type),
824 : : TyTy::TyWithLocation (const_value_type,
825 : 21 : expr.get_locus ()),
826 : : arg.get_locus ());
827 : : }
828 : : else
829 : : {
830 : 94 : coereced_type
831 : 94 : = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
832 : 94 : TyTy::TyWithLocation (specified_type),
833 : : TyTy::TyWithLocation (expr_type,
834 : 94 : expr.get_locus ()),
835 : : arg.get_locus ());
836 : : }
837 : :
838 : 230 : if (coereced_type == nullptr || coereced_type->is<ErrorType> ())
839 : 0 : return SubstitutionArgumentMappings::error ();
840 : :
841 : 115 : TyTy::BaseType *const_value_ty = nullptr;
842 : 115 : if (expr_type->get_kind () == TyTy::TypeKind::CONST)
843 : 21 : const_value_ty = expr_type;
844 : : else
845 : : {
846 : : // const fold it if available
847 : 94 : auto ctx = Compile::Context::get ();
848 : 94 : tree folded
849 : 94 : = Compile::HIRCompileBase::query_compile_const_expr (ctx,
850 : : coereced_type,
851 : : expr);
852 : :
853 : 94 : if (folded == error_mark_node)
854 : : {
855 : 0 : rich_location r (line_table, arg.get_locus ());
856 : 0 : r.add_range (expr.get_locus ());
857 : 0 : rust_error_at (r, "failed to resolve const expression");
858 : 0 : return SubstitutionArgumentMappings::error ();
859 : 0 : }
860 : :
861 : : // Use a fresh HirId to avoid conflicts with the expr's type
862 : 94 : auto &global_mappings = Analysis::Mappings::get ();
863 : 94 : HirId const_value_id = global_mappings.get_next_hir_id ();
864 : 94 : const_value_ty
865 : 94 : = new TyTy::ConstValueType (folded, coereced_type, const_value_id,
866 : 94 : const_value_id, {});
867 : :
868 : : // Insert the ConstValueType into the context so it can be looked up
869 : 94 : auto context = Resolver::TypeCheckContext::get ();
870 : 94 : context->insert_type (
871 : 94 : Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0),
872 : : const_value_ty);
873 : : }
874 : :
875 : 115 : mappings.emplace_back (¶m_mapping, const_value_ty);
876 : 115 : offs++;
877 : : }
878 : :
879 : : // we must need to fill out defaults
880 : 9228 : size_t left_over
881 : 9228 : = num_required_substitutions () - min_required_substitutions ();
882 : 9228 : if (left_over > 0)
883 : : {
884 : 2712 : for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
885 : : {
886 : 1137 : SubstitutionParamMapping ¶m = substitutions.at (offs);
887 : 1137 : rust_assert (param.param_has_default_ty ());
888 : :
889 : 1137 : BaseType *resolved = param.get_default_ty ();
890 : 1137 : if (resolved->get_kind () == TypeKind::ERROR)
891 : 0 : return SubstitutionArgumentMappings::error ();
892 : :
893 : : // this resolved default might already contain default parameters
894 : 1137 : if (!resolved->is_concrete ())
895 : : {
896 : 1118 : SubstitutionArgumentMappings intermediate (
897 : : mappings, binding_arguments,
898 : 1118 : {used_arguments.get_regions ().size ()}, args.get_locus ());
899 : 1118 : resolved = Resolver::SubstMapperInternal::Resolve (resolved,
900 : : intermediate);
901 : :
902 : 1118 : if (resolved->get_kind () == TypeKind::ERROR)
903 : 0 : return SubstitutionArgumentMappings::error ();
904 : 1118 : }
905 : :
906 : 1137 : mappings.emplace_back (¶m, resolved);
907 : : }
908 : : }
909 : :
910 : 9228 : return {mappings, binding_arguments,
911 : 18456 : RegionParamList::from_subst (used_arguments.get_regions ().size (),
912 : : regions),
913 : 27684 : args.get_locus ()};
914 : 9232 : }
915 : :
916 : : BaseType *
917 : 6659 : SubstitutionRef::infer_substitions (location_t locus)
918 : : {
919 : 6659 : std::vector<SubstitutionArg> args;
920 : 6659 : std::map<std::string, BaseType *> argument_mappings;
921 : 14845 : for (auto &p : get_substs ())
922 : : {
923 : 8186 : if (p.needs_substitution ())
924 : : {
925 : 8117 : const HIR::GenericParam &generic = p.get_generic_param ();
926 : 8117 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
927 : 8117 : auto it = argument_mappings.find (symbol);
928 : 8117 : bool have_mapping = it != argument_mappings.end ();
929 : :
930 : 8117 : if (have_mapping)
931 : : {
932 : 121 : args.emplace_back (&p, it->second);
933 : : }
934 : 7996 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
935 : : {
936 : 7977 : TyVar infer_var = TyVar::get_implicit_infer_var (locus);
937 : 7977 : args.emplace_back (&p, infer_var.get_tyty ());
938 : 7977 : argument_mappings[symbol] = infer_var.get_tyty ();
939 : : }
940 : 19 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
941 : : {
942 : 19 : TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
943 : 19 : args.emplace_back (&p, infer_var.get_tyty ());
944 : 19 : argument_mappings[symbol] = infer_var.get_tyty ();
945 : : }
946 : 8117 : }
947 : : else
948 : : {
949 : 69 : args.emplace_back (&p, p.get_param_ty ()->resolve ());
950 : : }
951 : : }
952 : :
953 : : // FIXME do we need to add inference variables to all the possible bindings?
954 : : // it might just lead to inference variable hell not 100% sure if rustc does
955 : : // this i think the language might needs this to be explicitly set
956 : :
957 : 6659 : SubstitutionArgumentMappings infer_arguments (std::move (args),
958 : : {} /* binding_arguments */,
959 : : used_arguments.get_regions (),
960 : 6659 : locus);
961 : 6659 : return handle_substitions (infer_arguments);
962 : 6659 : }
963 : :
964 : : SubstitutionArgumentMappings
965 : 13964 : SubstitutionRef::adjust_mappings_for_this (
966 : : SubstitutionArgumentMappings &mappings, bool trait_mode)
967 : : {
968 : 13964 : std::vector<SubstitutionArg> resolved_mappings;
969 : 32146 : for (size_t i = 0; i < substitutions.size (); i++)
970 : : {
971 : 18182 : auto &subst = substitutions.at (i);
972 : :
973 : 18182 : SubstitutionArg arg = SubstitutionArg::error ();
974 : 18182 : if (mappings.size () == substitutions.size ())
975 : : {
976 : 15925 : mappings.get_argument_at (i, &arg);
977 : : }
978 : : else
979 : : {
980 : 2257 : if (subst.needs_substitution ())
981 : : {
982 : : // get from passed in mappings
983 : 2169 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
984 : : }
985 : : else
986 : : {
987 : : // we should already have this somewhere
988 : 88 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
989 : : &arg);
990 : : }
991 : : }
992 : :
993 : 18182 : bool ok = !arg.is_error ();
994 : 18182 : if (ok || (trait_mode && i == 0))
995 : 17693 : resolved_mappings.emplace_back (&subst, arg.get_tyty ());
996 : : }
997 : :
998 : 13964 : if (resolved_mappings.empty ())
999 : 8 : return SubstitutionArgumentMappings::error ();
1000 : :
1001 : 13956 : return SubstitutionArgumentMappings (resolved_mappings,
1002 : 13956 : mappings.get_binding_args (),
1003 : : mappings.get_regions (),
1004 : : mappings.get_locus (),
1005 : 13956 : mappings.get_subst_cb (),
1006 : 27912 : mappings.trait_item_mode ());
1007 : 13964 : }
1008 : :
1009 : : bool
1010 : 0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
1011 : : {
1012 : 0 : std::vector<SubstitutionArg> resolved_mappings;
1013 : 0 : for (size_t i = 0; i < substitutions.size (); i++)
1014 : : {
1015 : 0 : auto &subst = substitutions.at (i);
1016 : :
1017 : 0 : SubstitutionArg arg = SubstitutionArg::error ();
1018 : 0 : if (mappings.size () == substitutions.size ())
1019 : : {
1020 : 0 : mappings.get_argument_at (i, &arg);
1021 : : }
1022 : : else
1023 : : {
1024 : 0 : if (subst.needs_substitution ())
1025 : : {
1026 : : // get from passed in mappings
1027 : 0 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
1028 : : }
1029 : : else
1030 : : {
1031 : : // we should already have this somewhere
1032 : 0 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
1033 : : &arg);
1034 : : }
1035 : : }
1036 : :
1037 : 0 : bool ok = !arg.is_error ();
1038 : 0 : if (ok)
1039 : 0 : resolved_mappings.emplace_back (&subst, arg.get_tyty ());
1040 : : }
1041 : :
1042 : 0 : return !resolved_mappings.empty ();
1043 : 0 : }
1044 : :
1045 : : // this function assumes that the mappings being passed are for the same type as
1046 : : // this new substitution reference so ordering matters here
1047 : : SubstitutionArgumentMappings
1048 : 63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
1049 : : SubstitutionArgumentMappings &mappings) const
1050 : : {
1051 : 63 : std::vector<SubstitutionArg> resolved_mappings;
1052 : :
1053 : 63 : rust_assert (mappings.size () == get_num_substitutions ());
1054 : 126 : for (size_t i = 0; i < get_num_substitutions (); i++)
1055 : : {
1056 : 63 : const SubstitutionParamMapping ¶m_mapping = substitutions.at (i);
1057 : 63 : SubstitutionArg &arg = mappings.get_mappings ().at (i);
1058 : :
1059 : 63 : if (param_mapping.needs_substitution ())
1060 : 63 : resolved_mappings.emplace_back (¶m_mapping, arg.get_tyty ());
1061 : : }
1062 : :
1063 : 63 : return SubstitutionArgumentMappings (resolved_mappings,
1064 : 63 : mappings.get_binding_args (),
1065 : : mappings.get_regions (),
1066 : 126 : mappings.get_locus ());
1067 : 63 : }
1068 : :
1069 : : void
1070 : 4305 : SubstitutionRef::prepare_higher_ranked_bounds ()
1071 : : {
1072 : 7210 : for (const auto &subst : get_substs ())
1073 : : {
1074 : 2905 : const auto pty = subst.get_param_ty ();
1075 : 6289 : for (const auto &bound : pty->get_specified_bounds ())
1076 : : {
1077 : 3384 : const auto ref = bound.get ();
1078 : 3384 : ref->clear_associated_type_projections ();
1079 : : }
1080 : : }
1081 : 4305 : }
1082 : :
1083 : : bool
1084 : 15384 : SubstitutionRef::monomorphize ()
1085 : : {
1086 : 24962 : for (const auto &subst : get_substs ())
1087 : : {
1088 : 9578 : const auto pty = subst.get_param_ty ();
1089 : 9578 : if (!pty->can_resolve ())
1090 : 100 : continue;
1091 : :
1092 : 9478 : TyTy::BaseType *binding = pty->resolve ();
1093 : 9478 : if (binding->get_kind () == TyTy::TypeKind::PARAM)
1094 : 2256 : continue;
1095 : :
1096 : 15566 : for (const auto &bound : pty->get_specified_bounds ())
1097 : : {
1098 : 8344 : bool ambigious = false;
1099 : 8344 : auto associated
1100 : 8344 : = Resolver::lookup_associated_impl_block (bound, binding,
1101 : : &ambigious);
1102 : 8344 : if (associated != nullptr)
1103 : 1946 : associated->setup_associated_types (binding, bound);
1104 : : }
1105 : : }
1106 : :
1107 : 15384 : return true;
1108 : : }
1109 : :
1110 : : } // namespace TyTy
1111 : : } // namespace Rust
|