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