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