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 : #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 2761360 : SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
36 : BaseGeneric *param)
37 2761360 : : generic (generic), param (param)
38 2761360 : {}
39 :
40 3478760 : SubstitutionParamMapping::SubstitutionParamMapping (
41 : const SubstitutionParamMapping &other)
42 3478760 : : generic (other.generic), param (other.param)
43 3478760 : {}
44 :
45 : std::string
46 31497 : SubstitutionParamMapping::as_string () const
47 : {
48 31497 : if (param == nullptr)
49 0 : return "nullptr";
50 :
51 31497 : return param->get_name ();
52 : }
53 :
54 : SubstitutionParamMapping
55 2747377 : SubstitutionParamMapping::clone () const
56 : {
57 2747377 : return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
58 2747377 : param->clone ()));
59 : }
60 :
61 : BaseGeneric *
62 249871 : SubstitutionParamMapping::get_param_ty ()
63 : {
64 249871 : return param;
65 : }
66 :
67 : const BaseGeneric *
68 2505975 : SubstitutionParamMapping::get_param_ty () const
69 : {
70 2505975 : return param;
71 : }
72 :
73 : HIR::GenericParam &
74 18864 : SubstitutionParamMapping::get_generic_param ()
75 : {
76 18864 : return generic;
77 : }
78 :
79 : const HIR::GenericParam &
80 11884 : SubstitutionParamMapping::get_generic_param () const
81 : {
82 11884 : return generic;
83 : }
84 :
85 : bool
86 78878 : SubstitutionParamMapping::needs_substitution () const
87 : {
88 78878 : return !(get_param_ty ()->is_concrete ());
89 : }
90 :
91 : Identifier
92 2552 : SubstitutionParamMapping::get_type_representation () const
93 : {
94 5104 : return param->get_symbol ();
95 : }
96 :
97 : location_t
98 1137 : SubstitutionParamMapping::get_param_locus () const
99 : {
100 1137 : return generic.get_locus ();
101 : }
102 :
103 : bool
104 28492 : SubstitutionParamMapping::param_has_default_ty () const
105 : {
106 28492 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
107 : {
108 28241 : const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
109 28241 : return type_param.has_type ();
110 : }
111 :
112 251 : rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
113 251 : const auto &const_param
114 : = static_cast<const HIR::ConstGenericParam &> (generic);
115 251 : return const_param.has_default_expression ();
116 : }
117 :
118 : BaseType *
119 1424 : SubstitutionParamMapping::get_default_ty () const
120 : {
121 1424 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
122 : {
123 1419 : const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
124 1419 : TyVar var (type_param.get_type_mappings ().get_hirid ());
125 1419 : 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 48717 : SubstitutionParamMapping::fill_param_ty (
150 : SubstitutionArgumentMappings &subst_mappings, location_t locus,
151 : bool needs_bounds_check)
152 : {
153 48717 : SubstitutionArg arg = SubstitutionArg::error ();
154 48717 : bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
155 48717 : if (!ok)
156 : return true;
157 :
158 48717 : TyTy::BaseType &type = *arg.get_tyty ();
159 48717 : std::pair<HirId, HirId> subst_key (param->get_ref (), type.get_ref ());
160 50613 : static std::vector<std::pair<HirId, HirId>> active_substs;
161 48717 : bool is_recursive_subst
162 48717 : = Resolver::ScopedPush<std::pair<HirId, HirId>>::contains (active_substs,
163 : subst_key);
164 48717 : bool skip_recursive_bounds
165 48717 : = is_recursive_subst && type.get_kind () == TyTy::TypeKind::INFER;
166 42 : if (skip_recursive_bounds)
167 : {
168 42 : type.append_reference (param->get_ref ());
169 42 : type.append_reference (param->get_ty_ref ());
170 42 : for (auto ref : param->get_combined_refs ())
171 0 : type.append_reference (ref);
172 42 : if (param->can_resolve ())
173 : {
174 42 : TyTy::BaseType *resolved = param->resolve ();
175 42 : type.append_reference (resolved->get_ref ());
176 42 : type.append_reference (resolved->get_ty_ref ());
177 42 : for (auto ref : resolved->get_combined_refs ())
178 0 : type.append_reference (ref);
179 42 : if (resolved->get_kind () != TyTy::TypeKind::PARAM
180 42 : && resolved->get_kind () != TyTy::TypeKind::INFER)
181 : return true;
182 : }
183 : }
184 :
185 48675 : Resolver::ScopedPush<std::pair<HirId, HirId>> guard (active_substs, subst_key,
186 48675 : !is_recursive_subst);
187 :
188 48675 : if (type.get_kind () == TyTy::TypeKind::INFER)
189 : {
190 12504 : type.inherit_bounds (*param);
191 : }
192 :
193 48675 : if (type.get_kind () == TypeKind::PARAM)
194 : {
195 11689 : param = static_cast<BaseGeneric *> (type.clone ());
196 : }
197 36986 : else if (type.get_kind () == TyTy::TypeKind::CONST)
198 : {
199 195 : rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
200 195 : auto *const_type = type.as_const_type ();
201 195 : if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
202 22 : param = static_cast<BaseGeneric *> (type.clone ());
203 : else
204 173 : param->set_ty_ref (type.get_ref ());
205 : }
206 36791 : else if (param->get_kind () == TypeKind::PARAM)
207 : {
208 36791 : auto &p = *static_cast<TyTy::ParamType *> (param);
209 :
210 : // check the substitution is compatible with bounds
211 36791 : rust_debug_loc (locus,
212 : "fill_param_ty bounds_compatible: param %s type %s",
213 : param->get_name ().c_str (), type.get_name ().c_str ());
214 36791 : if (!skip_recursive_bounds && needs_bounds_check
215 36791 : && !p.is_implicit_self_trait ())
216 : {
217 16001 : if (!param->bounds_compatible (type, locus, true))
218 : return false;
219 : }
220 :
221 : // recursively pass this down to all HRTB's
222 36781 : if (!skip_recursive_bounds)
223 80889 : for (auto &bound : param->get_specified_bounds ())
224 44108 : bound.handle_substitions (subst_mappings);
225 :
226 36781 : param->set_ty_ref (type.get_ref ());
227 : }
228 :
229 : return true;
230 48717 : }
231 :
232 : void
233 5869 : SubstitutionParamMapping::override_context ()
234 : {
235 5869 : if (!param->can_resolve ())
236 : return;
237 :
238 5855 : auto &mappings = Analysis::Mappings::get ();
239 5855 : auto context = Resolver::TypeCheckContext::get ();
240 :
241 5855 : context->insert_type (
242 5855 : Analysis::NodeMapping (mappings.crate.get_current_crate (), UNKNOWN_NODEID,
243 5855 : param->get_ref (), UNKNOWN_LOCAL_DEFID),
244 5855 : param->resolve ());
245 : }
246 :
247 2605420 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
248 : BaseType *argument)
249 2605420 : : param (param), argument (argument)
250 : {
251 2605420 : if (param != nullptr)
252 2390389 : original_param = param->get_param_ty ();
253 2605420 : }
254 :
255 5065315 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
256 5065315 : : param (other.param), original_param (other.original_param),
257 5065315 : argument (other.argument)
258 5065315 : {}
259 :
260 : SubstitutionArg &
261 207151 : SubstitutionArg::operator= (const SubstitutionArg &other)
262 : {
263 207151 : param = other.param;
264 207151 : argument = other.argument;
265 207151 : original_param = other.original_param;
266 :
267 207151 : return *this;
268 : }
269 :
270 : BaseType *
271 3323255 : SubstitutionArg::get_tyty () const
272 : {
273 3323255 : return argument;
274 : }
275 :
276 : const SubstitutionParamMapping *
277 0 : SubstitutionArg::get_param_mapping () const
278 : {
279 0 : return param;
280 : }
281 :
282 : const BaseGeneric *
283 237269 : SubstitutionArg::get_param_ty () const
284 : {
285 237269 : return original_param;
286 : }
287 :
288 : SubstitutionArg
289 215031 : SubstitutionArg::error ()
290 : {
291 215031 : return SubstitutionArg (nullptr, nullptr);
292 : }
293 :
294 : bool
295 78956 : SubstitutionArg::is_error () const
296 : {
297 78956 : return param == nullptr || argument == nullptr;
298 : }
299 :
300 : bool
301 0 : SubstitutionArg::is_conrete () const
302 : {
303 0 : if (argument == nullptr)
304 : return false;
305 :
306 0 : if (argument->get_kind () == TyTy::TypeKind::PARAM)
307 : return false;
308 :
309 0 : return argument->is_concrete ();
310 : }
311 :
312 : std::string
313 0 : SubstitutionArg::as_string () const
314 : {
315 0 : return original_param->as_string ()
316 0 : + (argument != nullptr ? ":" + argument->as_string () : "");
317 : }
318 :
319 : const RegionParamList &
320 2058090 : SubstitutionArgumentMappings::get_regions () const
321 : {
322 2058090 : return regions;
323 : }
324 :
325 : RegionParamList &
326 2170 : SubstitutionArgumentMappings::get_mut_regions ()
327 : {
328 2170 : return regions;
329 : }
330 :
331 : // SubstitutionArgumentMappings
332 :
333 4292294 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
334 : std::vector<SubstitutionArg> mappings,
335 : std::map<std::string, BaseType *> binding_args, RegionParamList regions,
336 : location_t locus, bool trait_item_flag, bool error_flag,
337 : std::map<std::string, BaseType *> constraint_args)
338 4292294 : : mappings (std::move (mappings)), binding_args (binding_args),
339 4292294 : constraint_args (constraint_args), regions (regions), locus (locus),
340 4292294 : trait_item_flag (trait_item_flag), error_flag (error_flag)
341 4292294 : {}
342 :
343 2488183 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
344 : const SubstitutionArgumentMappings &other)
345 2488183 : : mappings (other.mappings), binding_args (other.binding_args),
346 2488183 : constraint_args (other.constraint_args), regions (other.regions),
347 2488183 : locus (other.locus), trait_item_flag (other.trait_item_flag),
348 2488183 : error_flag (other.error_flag)
349 2488183 : {}
350 :
351 : SubstitutionArgumentMappings &
352 48045 : SubstitutionArgumentMappings::operator= (
353 : const SubstitutionArgumentMappings &other)
354 : {
355 48045 : mappings = other.mappings;
356 48045 : binding_args = other.binding_args;
357 48045 : constraint_args = other.constraint_args;
358 48045 : regions = other.regions;
359 48045 : locus = other.locus;
360 48045 : trait_item_flag = other.trait_item_flag;
361 48045 : error_flag = other.error_flag;
362 :
363 48045 : return *this;
364 : }
365 :
366 : SubstitutionArgumentMappings
367 44267 : SubstitutionArgumentMappings::error ()
368 : {
369 44267 : return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, false, true);
370 : }
371 :
372 : SubstitutionArgumentMappings
373 2192108 : SubstitutionArgumentMappings::empty (size_t num_regions)
374 : {
375 2192108 : return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
376 2192108 : false, false);
377 : }
378 :
379 : bool
380 41588 : SubstitutionArgumentMappings::is_error () const
381 : {
382 41588 : return error_flag;
383 : }
384 :
385 : bool
386 197012 : SubstitutionArgumentMappings::get_argument_for_symbol (
387 : const BaseGeneric *param_to_find, SubstitutionArg *argument) const
388 : {
389 253402 : for (const auto &mapping : mappings)
390 : {
391 236342 : const auto *p = mapping.get_param_ty ();
392 236342 : if (p->get_symbol () == param_to_find->get_symbol ())
393 : {
394 179952 : *argument = mapping;
395 179952 : return true;
396 : }
397 : }
398 : return false;
399 : }
400 : tl::optional<size_t>
401 0 : SubstitutionArgumentMappings::find_symbol (const ParamType ¶m_to_find) const
402 : {
403 0 : auto it = std::find_if (mappings.begin (), mappings.end (),
404 0 : [param_to_find] (const SubstitutionArg &arg) {
405 0 : return arg.get_param_ty ()->get_symbol ()
406 0 : == param_to_find.get_symbol ();
407 : });
408 0 : if (it == mappings.end ())
409 0 : return tl::nullopt;
410 0 : return std::distance (mappings.begin (), it);
411 : }
412 :
413 : bool
414 18019 : SubstitutionArgumentMappings::get_argument_at (size_t index,
415 : SubstitutionArg *argument)
416 : {
417 18019 : if (index > mappings.size ())
418 : return false;
419 :
420 18019 : *argument = mappings.at (index);
421 18019 : return true;
422 : }
423 :
424 : bool
425 0 : SubstitutionArgumentMappings::is_concrete () const
426 : {
427 0 : for (auto &mapping : mappings)
428 : {
429 0 : if (!mapping.is_conrete ())
430 0 : return false;
431 : }
432 : return true;
433 : }
434 :
435 : location_t
436 2072008 : SubstitutionArgumentMappings::get_locus () const
437 : {
438 2072008 : return locus;
439 : }
440 :
441 : size_t
442 57546 : SubstitutionArgumentMappings::size () const
443 : {
444 57546 : return mappings.size ();
445 : }
446 :
447 : bool
448 21211 : SubstitutionArgumentMappings::is_empty () const
449 : {
450 21211 : return size () == 0;
451 : }
452 :
453 : std::vector<SubstitutionArg> &
454 102512 : SubstitutionArgumentMappings::get_mappings ()
455 : {
456 102512 : return mappings;
457 : }
458 :
459 : const std::vector<SubstitutionArg> &
460 2340118 : SubstitutionArgumentMappings::get_mappings () const
461 : {
462 2340118 : return mappings;
463 : }
464 :
465 : std::map<std::string, BaseType *> &
466 15812 : SubstitutionArgumentMappings::get_binding_args ()
467 : {
468 15812 : return binding_args;
469 : }
470 :
471 : const std::map<std::string, BaseType *> &
472 2014373 : SubstitutionArgumentMappings::get_binding_args () const
473 : {
474 2014373 : return binding_args;
475 : }
476 :
477 : const std::map<std::string, BaseType *> &
478 2024906 : SubstitutionArgumentMappings::get_constraint_args () const
479 : {
480 2024906 : return constraint_args;
481 : }
482 :
483 : std::string
484 0 : SubstitutionArgumentMappings::as_string () const
485 : {
486 0 : std::string buffer;
487 0 : for (auto &mapping : mappings)
488 : {
489 0 : buffer += mapping.as_string () + ", ";
490 : }
491 0 : return "<" + buffer + ">";
492 0 : }
493 :
494 : bool
495 15753 : SubstitutionArgumentMappings::trait_item_mode () const
496 : {
497 15753 : return trait_item_flag;
498 : }
499 :
500 : // SubstitutionRef
501 :
502 2240832 : SubstitutionRef::SubstitutionRef (
503 : std::vector<SubstitutionParamMapping> substitutions,
504 : SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
505 2240832 : : substitutions (substitutions), used_arguments (arguments),
506 4481664 : region_constraints (region_constraints)
507 2240832 : {}
508 :
509 : bool
510 313243 : SubstitutionRef::has_substitutions () const
511 : {
512 313243 : return substitutions.size () > 0;
513 : }
514 :
515 : std::string
516 99088 : SubstitutionRef::subst_as_string () const
517 : {
518 99088 : std::string buffer;
519 130585 : for (size_t i = 0; i < substitutions.size (); i++)
520 : {
521 31497 : const SubstitutionParamMapping &sub = substitutions.at (i);
522 62994 : buffer += sub.as_string ();
523 :
524 31497 : if ((i + 1) < substitutions.size ())
525 2803 : buffer += ", ";
526 : }
527 :
528 127782 : return buffer.empty () ? "" : "<" + buffer + ">";
529 99088 : }
530 :
531 : bool
532 131 : SubstitutionRef::supports_associated_bindings () const
533 : {
534 131 : return get_num_associated_bindings () > 0;
535 : }
536 :
537 : size_t
538 1 : SubstitutionRef::get_num_associated_bindings () const
539 : {
540 1 : return 0;
541 : }
542 :
543 : TypeBoundPredicateItem
544 0 : SubstitutionRef::lookup_associated_type (const std::string &search)
545 : {
546 0 : return TypeBoundPredicateItem::error ();
547 : }
548 :
549 : size_t
550 55986 : SubstitutionRef::get_num_substitutions () const
551 : {
552 55986 : return substitutions.size ();
553 : }
554 : size_t
555 241 : SubstitutionRef::get_num_lifetime_params () const
556 : {
557 241 : return used_arguments.get_regions ().size ();
558 : }
559 : size_t
560 506 : SubstitutionRef::get_num_type_params () const
561 : {
562 506 : return get_num_substitutions ();
563 : }
564 :
565 : std::vector<SubstitutionParamMapping> &
566 182265 : SubstitutionRef::get_substs ()
567 : {
568 182265 : return substitutions;
569 : }
570 :
571 : const std::vector<SubstitutionParamMapping> &
572 2029840 : SubstitutionRef::get_substs () const
573 : {
574 2029840 : return substitutions;
575 : }
576 :
577 : std::vector<SubstitutionParamMapping>
578 127435 : SubstitutionRef::clone_substs () const
579 : {
580 127435 : std::vector<SubstitutionParamMapping> clone;
581 127435 : clone.reserve (substitutions.size ());
582 :
583 201432 : for (auto &sub : substitutions)
584 73997 : clone.push_back (sub.clone ());
585 :
586 127435 : return clone;
587 : }
588 :
589 : void
590 5287 : SubstitutionRef::override_context ()
591 : {
592 11156 : for (auto &sub : substitutions)
593 : {
594 5869 : sub.override_context ();
595 : }
596 5287 : }
597 :
598 : bool
599 51214 : SubstitutionRef::needs_substitution () const
600 : {
601 51214 : return std::any_of (substitutions.begin (), substitutions.end (),
602 : std::mem_fn (
603 51214 : &SubstitutionParamMapping::needs_substitution));
604 : }
605 :
606 : bool
607 63 : SubstitutionRef::was_substituted () const
608 : {
609 63 : return !needs_substitution ();
610 : }
611 :
612 : SubstitutionArgumentMappings &
613 55005 : SubstitutionRef::get_substitution_arguments ()
614 : {
615 55005 : return used_arguments;
616 : }
617 :
618 : const SubstitutionArgumentMappings &
619 200210 : SubstitutionRef::get_substitution_arguments () const
620 : {
621 200210 : return used_arguments;
622 : }
623 :
624 : size_t
625 11090 : SubstitutionRef::num_required_substitutions () const
626 : {
627 11090 : size_t n = 0;
628 25023 : for (auto &p : substitutions)
629 : {
630 13933 : if (p.needs_substitution ())
631 13522 : n++;
632 : }
633 11090 : return n;
634 : }
635 :
636 : size_t
637 22196 : SubstitutionRef::min_required_substitutions () const
638 : {
639 22196 : size_t n = 0;
640 50086 : for (auto &p : substitutions)
641 : {
642 27890 : if (p.needs_substitution () && !p.param_has_default_ty ())
643 23275 : n++;
644 : }
645 22196 : return n;
646 : }
647 :
648 : const SubstitutionArgumentMappings &
649 13319 : SubstitutionRef::get_used_arguments () const
650 : {
651 13319 : return used_arguments;
652 : }
653 :
654 : tl::optional<SubstitutionArg>
655 204 : SubstitutionRef::get_arg_at (size_t i) const
656 : {
657 204 : auto param_ty = get_substs ().at (i).get_param_ty ();
658 204 : SubstitutionArg arg = SubstitutionArg::error ();
659 204 : get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
660 204 : if (arg.is_error ())
661 16 : return tl::nullopt;
662 188 : return arg;
663 : }
664 :
665 : const RegionConstraints &
666 115675 : SubstitutionRef::get_region_constraints () const
667 : {
668 115675 : return region_constraints;
669 : }
670 :
671 : SubstitutionArgumentMappings
672 11106 : SubstitutionRef::get_mappings_from_generic_args (
673 : HIR::GenericArgs &args, const std::vector<Region> ®ions)
674 : {
675 11106 : std::map<std::string, BaseType *> binding_arguments;
676 11106 : std::map<std::string, BaseType *> constraint_arguments;
677 11106 : if (args.get_binding_args ().size () > 0)
678 : {
679 131 : if (supports_associated_bindings ())
680 : {
681 130 : if (args.get_binding_args ().size () > get_num_associated_bindings ())
682 : {
683 0 : rich_location r (line_table, args.get_locus ());
684 0 : rust_error_at (r,
685 : "generic item takes at most %lu type binding "
686 : "arguments but %lu were supplied",
687 0 : (unsigned long) get_num_associated_bindings (),
688 0 : (unsigned long) args.get_binding_args ().size ());
689 0 : return SubstitutionArgumentMappings::error ();
690 0 : }
691 :
692 262 : for (auto &binding : args.get_binding_args ())
693 : {
694 132 : BaseType *resolved
695 132 : = Resolver::TypeCheckType::Resolve (binding.get_type ());
696 132 : if (resolved == nullptr
697 132 : || resolved->get_kind () == TyTy::TypeKind::ERROR)
698 : {
699 0 : return SubstitutionArgumentMappings::error ();
700 : }
701 :
702 : // resolve to relevant binding
703 132 : auto binding_item = lookup_associated_type (
704 132 : binding.get_identifier ().as_string ());
705 132 : if (binding_item.is_error ())
706 : {
707 0 : rust_error_at (
708 : binding.get_locus (), "unknown associated type binding: %s",
709 0 : binding.get_identifier ().as_string ().c_str ());
710 0 : return SubstitutionArgumentMappings::error ();
711 : }
712 :
713 132 : if (binding.get_kind ()
714 : == HIR::GenericArgsBinding::Kind::Constraint)
715 10 : constraint_arguments[binding.get_identifier ().as_string ()]
716 10 : = resolved;
717 : else
718 122 : binding_arguments[binding.get_identifier ().as_string ()]
719 122 : = resolved;
720 132 : }
721 : }
722 : else
723 : {
724 1 : rich_location r (line_table, args.get_locus ());
725 3 : for (auto &binding : args.get_binding_args ())
726 2 : r.add_range (binding.get_locus ());
727 :
728 1 : rust_error_at (r, ErrorCode::E0229,
729 : "associated type bindings are not allowed here");
730 1 : return SubstitutionArgumentMappings::error ();
731 1 : }
732 : }
733 :
734 : // check if we need to use inherited arguments or nothing
735 11105 : size_t offs = 0;
736 11105 : size_t total_arguments
737 11105 : = args.get_type_args ().size () + args.get_const_args ().size ();
738 11105 : if (total_arguments < substitutions.size ())
739 : {
740 2038 : offs = used_arguments.get_mappings ().empty () ? get_outer_param_count ()
741 611 : : used_arguments.size ();
742 2038 : total_arguments += offs;
743 : }
744 :
745 11105 : if (total_arguments > substitutions.size ())
746 : {
747 4 : rich_location r (line_table, args.get_locus ());
748 4 : if (!substitutions.empty ())
749 : {
750 3 : const auto &subst = substitutions.front ();
751 3 : const auto &generic = subst.get_generic_param ();
752 3 : r.add_range (generic.get_locus ());
753 : }
754 :
755 8 : rust_error_at (
756 : r,
757 : "generic item takes at most %lu type arguments but %lu were supplied",
758 4 : (unsigned long) substitutions.size (),
759 4 : (unsigned long) args.get_type_args ().size ());
760 4 : return SubstitutionArgumentMappings::error ();
761 4 : }
762 :
763 11101 : if (total_arguments < min_required_substitutions ())
764 : {
765 5 : rich_location r (line_table, args.get_locus ());
766 5 : if (!substitutions.empty ())
767 : {
768 5 : const auto &subst = substitutions.front ();
769 5 : const auto &generic = subst.get_generic_param ();
770 5 : r.add_range (generic.get_locus ());
771 : }
772 :
773 10 : rust_error_at (
774 : r, ErrorCode::E0107,
775 : "generic item takes at least %lu type arguments but %lu were supplied",
776 5 : (unsigned long) (min_required_substitutions () - offs),
777 5 : (unsigned long) args.get_type_args ().size ());
778 5 : return SubstitutionArgumentMappings::error ();
779 5 : }
780 :
781 11096 : std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
782 22851 : for (auto &arg : args.get_type_args ())
783 : {
784 11760 : BaseType *resolved = Resolver::TypeCheckType::Resolve (*arg);
785 11759 : if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
786 : {
787 4 : return SubstitutionArgumentMappings::error ();
788 : }
789 :
790 11759 : const auto ¶m_mapping = substitutions.at (offs);
791 11759 : const auto &generic = param_mapping.get_generic_param ();
792 11759 : if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
793 : {
794 11756 : const auto &type_param
795 : = static_cast<const HIR::TypeParam &> (generic);
796 11756 : if (type_param.from_impl_trait ())
797 : {
798 1 : rich_location r (line_table, arg->get_locus ());
799 1 : r.add_fixit_remove (arg->get_locus ());
800 1 : rust_error_at (r, ErrorCode::E0632,
801 : "cannot provide explicit generic arguments when "
802 : "%<impl Trait%> is used in argument position");
803 1 : return SubstitutionArgumentMappings::error ();
804 1 : }
805 : }
806 3 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
807 : {
808 3 : if (resolved->get_kind () != TyTy::TypeKind::CONST)
809 : {
810 3 : rich_location r (line_table, arg->get_locus ());
811 3 : r.add_fixit_remove (arg->get_locus ());
812 3 : rust_error_at (r, ErrorCode::E0747,
813 : "type provided when a constant was expected");
814 3 : return SubstitutionArgumentMappings::error ();
815 3 : }
816 : }
817 :
818 11755 : mappings.emplace_back (¶m_mapping, resolved);
819 11755 : offs++;
820 : }
821 :
822 11207 : for (auto &arg : args.get_const_args ())
823 : {
824 117 : auto &expr = *arg.get_expression ().get ();
825 117 : const auto ¶m_mapping = substitutions.at (offs);
826 117 : const auto &generic = param_mapping.get_generic_param ();
827 117 : if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
828 : {
829 0 : rich_location r (line_table, arg.get_locus ());
830 0 : r.add_fixit_remove (expr.get_locus ());
831 0 : rust_error_at (r, "invalid position for a const generic argument");
832 0 : return SubstitutionArgumentMappings::error ();
833 0 : }
834 :
835 117 : auto specified_type = param_mapping.get_param_ty ()
836 117 : ->as_const_type ()
837 117 : ->get_specified_type ();
838 117 : auto const_value_ty = resolve_const_argument (expr, specified_type);
839 117 : if (const_value_ty->is<ErrorType> ())
840 1 : return SubstitutionArgumentMappings::error ();
841 :
842 116 : mappings.emplace_back (¶m_mapping, const_value_ty);
843 116 : offs++;
844 : }
845 :
846 : // we must need to fill out defaults
847 11090 : size_t left_over
848 11090 : = num_required_substitutions () - min_required_substitutions ();
849 11090 : if (left_over > 0)
850 : {
851 3320 : for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
852 : {
853 1424 : SubstitutionParamMapping ¶m = substitutions.at (offs);
854 1424 : rust_assert (param.param_has_default_ty ());
855 :
856 1424 : BaseType *resolved = param.get_default_ty ();
857 1424 : if (resolved->get_kind () == TypeKind::ERROR)
858 0 : return SubstitutionArgumentMappings::error ();
859 :
860 : // this resolved default might already contain default parameters
861 1424 : if (!resolved->is_concrete ())
862 : {
863 1402 : SubstitutionArgumentMappings intermediate (
864 : mappings, binding_arguments,
865 1402 : {used_arguments.get_regions ().size ()}, args.get_locus ());
866 1402 : resolved = Resolver::SubstMapperInternal::Resolve (resolved,
867 : intermediate);
868 :
869 1402 : if (resolved->get_kind () == TypeKind::ERROR)
870 0 : return SubstitutionArgumentMappings::error ();
871 1402 : }
872 :
873 1424 : mappings.emplace_back (¶m, resolved);
874 : }
875 : }
876 :
877 11090 : return {mappings,
878 : binding_arguments,
879 22180 : RegionParamList::from_subst (used_arguments.get_regions ().size (),
880 : regions),
881 : args.get_locus (),
882 : false,
883 : false,
884 33270 : constraint_arguments};
885 22200 : }
886 :
887 : BaseType *
888 118 : SubstitutionRef::resolve_const_argument (HIR::Expr &expr,
889 : BaseType *specified_type)
890 : {
891 118 : BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
892 236 : if (expr_type == nullptr || expr_type->is<ErrorType> ())
893 0 : return new ErrorType (expr.get_mappings ().get_hirid ());
894 :
895 118 : TyTy::BaseType *coerced_type = nullptr;
896 118 : if (expr_type->get_kind () == TyTy::TypeKind::CONST)
897 : {
898 22 : auto const_expr_type = expr_type->as_const_type ();
899 22 : auto const_value_type = const_expr_type->get_specified_type ();
900 22 : coerced_type
901 22 : = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
902 22 : TyTy::TyWithLocation (specified_type),
903 : TyTy::TyWithLocation (const_value_type,
904 22 : expr.get_locus ()),
905 22 : expr.get_locus ());
906 : }
907 : else
908 : {
909 96 : coerced_type
910 96 : = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
911 96 : TyTy::TyWithLocation (specified_type),
912 : TyTy::TyWithLocation (expr_type,
913 96 : expr.get_locus ()),
914 96 : expr.get_locus ());
915 : }
916 :
917 236 : if (coerced_type == nullptr || coerced_type->is<ErrorType> ())
918 0 : return new ErrorType (expr.get_mappings ().get_hirid ());
919 :
920 118 : TyTy::BaseType *const_value_ty = nullptr;
921 118 : if (expr_type->get_kind () == TyTy::TypeKind::CONST)
922 : const_value_ty = expr_type;
923 : else
924 : {
925 96 : auto ctx = Compile::Context::get ();
926 96 : tree folded
927 96 : = Compile::HIRCompileBase::query_compile_const_expr (ctx, coerced_type,
928 : expr);
929 :
930 96 : if (folded == error_mark_node)
931 : {
932 1 : rich_location r (line_table, expr.get_locus ());
933 1 : r.add_range (expr.get_locus ());
934 1 : rust_error_at (r, "failed to resolve const expression");
935 1 : return new ErrorType (expr.get_mappings ().get_hirid ());
936 1 : }
937 :
938 : // Use a fresh HirId to avoid conflicts with the expr's type
939 95 : auto &global_mappings = Analysis::Mappings::get ();
940 95 : HirId const_value_id = global_mappings.get_next_hir_id ();
941 95 : const_value_ty
942 95 : = new TyTy::ConstValueType (folded, coerced_type, const_value_id,
943 95 : const_value_id, {});
944 :
945 : // Insert the ConstValueType into the context so it can be looked up
946 95 : auto context = Resolver::TypeCheckContext::get ();
947 95 : context->insert_type (Analysis::NodeMapping (0, 0,
948 : const_value_ty->get_ref (),
949 95 : 0),
950 : const_value_ty);
951 : }
952 :
953 : return const_value_ty;
954 : }
955 :
956 : BaseType *
957 8183 : SubstitutionRef::infer_substitions (location_t locus)
958 : {
959 8183 : std::vector<SubstitutionArg> args;
960 8183 : std::map<std::string, BaseType *> argument_mappings;
961 17987 : for (auto &p : get_substs ())
962 : {
963 9804 : if (p.needs_substitution ())
964 : {
965 9760 : const HIR::GenericParam &generic = p.get_generic_param ();
966 9760 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
967 9760 : auto it = argument_mappings.find (symbol);
968 9760 : bool have_mapping = it != argument_mappings.end ();
969 :
970 9760 : if (have_mapping)
971 : {
972 121 : args.emplace_back (&p, it->second);
973 : }
974 9639 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
975 : {
976 9619 : TyVar infer_var = TyVar::get_implicit_infer_var (locus);
977 9619 : args.emplace_back (&p, infer_var.get_tyty ());
978 9619 : argument_mappings[symbol] = infer_var.get_tyty ();
979 : }
980 20 : else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
981 : {
982 20 : TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
983 20 : args.emplace_back (&p, infer_var.get_tyty ());
984 20 : argument_mappings[symbol] = infer_var.get_tyty ();
985 : }
986 9760 : }
987 : else
988 : {
989 44 : args.emplace_back (&p, p.get_param_ty ()->resolve ());
990 : }
991 : }
992 :
993 : // FIXME do we need to add inference variables to all the possible bindings?
994 : // it might just lead to inference variable hell not 100% sure if rustc does
995 : // this i think the language might needs this to be explicitly set
996 :
997 8183 : SubstitutionArgumentMappings infer_arguments (std::move (args),
998 : {} /* binding_arguments */,
999 : used_arguments.get_regions (),
1000 8183 : locus);
1001 8183 : return handle_substitions (infer_arguments);
1002 8183 : }
1003 :
1004 : SubstitutionArgumentMappings
1005 15751 : SubstitutionRef::adjust_mappings_for_this (
1006 : SubstitutionArgumentMappings &mappings, bool trait_mode)
1007 : {
1008 15751 : std::vector<SubstitutionArg> resolved_mappings;
1009 36144 : for (size_t i = 0; i < substitutions.size (); i++)
1010 : {
1011 20393 : auto &subst = substitutions.at (i);
1012 :
1013 20393 : SubstitutionArg arg = SubstitutionArg::error ();
1014 20393 : if (mappings.size () == substitutions.size ())
1015 : {
1016 18019 : mappings.get_argument_at (i, &arg);
1017 : }
1018 : else
1019 : {
1020 2374 : if (subst.needs_substitution ())
1021 : {
1022 : // get from passed in mappings
1023 2284 : bool found
1024 2284 : = mappings.get_argument_for_symbol (subst.get_param_ty (),
1025 : &arg);
1026 2284 : if (!found)
1027 : {
1028 : // This type can already be partially instantiated from an
1029 : // outer scope
1030 505 : SubstitutionArg bound_arg = SubstitutionArg::error ();
1031 505 : bool have_binding = used_arguments.get_argument_for_symbol (
1032 505 : subst.get_param_ty (), &bound_arg);
1033 :
1034 505 : if (have_binding && !bound_arg.is_error ())
1035 : {
1036 25 : BaseType *resolved
1037 25 : = Resolver::SubstMapperInternal::Resolve (
1038 : bound_arg.get_tyty (), mappings);
1039 25 : if (resolved->get_kind () != TypeKind::ERROR)
1040 25 : arg = SubstitutionArg (&subst, resolved);
1041 : }
1042 : }
1043 : }
1044 : else
1045 : {
1046 : // we should already have this somewhere
1047 90 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
1048 : &arg);
1049 : }
1050 : }
1051 :
1052 20393 : bool ok = !arg.is_error ();
1053 20393 : if (ok || (trait_mode && i == 0))
1054 19913 : resolved_mappings.emplace_back (&subst, arg.get_tyty ());
1055 : }
1056 :
1057 15751 : if (resolved_mappings.empty ())
1058 2 : return SubstitutionArgumentMappings::error ();
1059 :
1060 15749 : return SubstitutionArgumentMappings (resolved_mappings,
1061 15749 : mappings.get_binding_args (),
1062 : mappings.get_regions (),
1063 : mappings.get_locus (),
1064 : mappings.trait_item_mode (), false,
1065 31498 : mappings.get_constraint_args ());
1066 15751 : }
1067 :
1068 : bool
1069 0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
1070 : {
1071 0 : std::vector<SubstitutionArg> resolved_mappings;
1072 0 : for (size_t i = 0; i < substitutions.size (); i++)
1073 : {
1074 0 : auto &subst = substitutions.at (i);
1075 :
1076 0 : SubstitutionArg arg = SubstitutionArg::error ();
1077 0 : if (mappings.size () == substitutions.size ())
1078 : {
1079 0 : mappings.get_argument_at (i, &arg);
1080 : }
1081 : else
1082 : {
1083 0 : if (subst.needs_substitution ())
1084 : {
1085 : // get from passed in mappings
1086 0 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
1087 : }
1088 : else
1089 : {
1090 : // we should already have this somewhere
1091 0 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
1092 : &arg);
1093 : }
1094 : }
1095 :
1096 0 : bool ok = !arg.is_error ();
1097 0 : if (ok)
1098 0 : resolved_mappings.emplace_back (&subst, arg.get_tyty ());
1099 : }
1100 :
1101 0 : return !resolved_mappings.empty ();
1102 0 : }
1103 :
1104 : // this function assumes that the mappings being passed are for the same type as
1105 : // this new substitution reference so ordering matters here
1106 : SubstitutionArgumentMappings
1107 63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
1108 : SubstitutionArgumentMappings &mappings) const
1109 : {
1110 63 : std::vector<SubstitutionArg> resolved_mappings;
1111 :
1112 63 : rust_assert (mappings.size () == get_num_substitutions ());
1113 126 : for (size_t i = 0; i < get_num_substitutions (); i++)
1114 : {
1115 63 : const SubstitutionParamMapping ¶m_mapping = substitutions.at (i);
1116 63 : SubstitutionArg &arg = mappings.get_mappings ().at (i);
1117 :
1118 63 : if (param_mapping.needs_substitution ())
1119 63 : resolved_mappings.emplace_back (¶m_mapping, arg.get_tyty ());
1120 : }
1121 :
1122 63 : return SubstitutionArgumentMappings (resolved_mappings,
1123 63 : mappings.get_binding_args (),
1124 : mappings.get_regions (),
1125 : mappings.get_locus (), false, false,
1126 126 : mappings.get_constraint_args ());
1127 63 : }
1128 :
1129 : bool
1130 18536 : SubstitutionRef::monomorphize ()
1131 : {
1132 29988 : for (const auto &subst : get_substs ())
1133 : {
1134 11452 : const auto pty = subst.get_param_ty ();
1135 11452 : if (!pty->can_resolve ())
1136 109 : continue;
1137 :
1138 11343 : TyTy::BaseType *binding = pty->resolve ();
1139 11343 : if (binding->get_kind () == TyTy::TypeKind::PARAM)
1140 2428 : continue;
1141 :
1142 : // For each where-clause bound on this fn-substitution param, find the
1143 : // impl block that satisfies the bound for binding and unify
1144 : // its signature against binding + bound. This pins inference
1145 : // variables that should be constrained
1146 : //
1147 : // fn into_iter<I: Iterator> with binding = Range<{integer}>
1148 : //
1149 : // the only matching
1150 : //
1151 : // <A: Step> Iterator for Range<A>
1152 : //
1153 : // Step for usize impl together force {integer} = usize instead of
1154 : // letting it default.
1155 18945 : for (const auto &bound : pty->get_specified_bounds ())
1156 : {
1157 10030 : bool ambigious = false;
1158 10030 : auto associated
1159 10030 : = Resolver::lookup_associated_impl_block (bound, binding,
1160 : &ambigious);
1161 10030 : if (associated != nullptr)
1162 2323 : associated->bind_impl_for_bound (binding, bound, UNKNOWN_LOCATION);
1163 : }
1164 : }
1165 :
1166 18536 : return true;
1167 : }
1168 :
1169 : } // namespace TyTy
1170 : } // namespace Rust
|