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