Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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 <utility>
22 : : #include "rust-tyty.h"
23 : : #include "rust-hir-type-check.h"
24 : : #include "rust-substitution-mapper.h"
25 : : #include "rust-hir-type-check-type.h"
26 : : #include "rust-type-util.h"
27 : :
28 : : namespace Rust {
29 : : namespace TyTy {
30 : :
31 : 12157837 : SubstitutionParamMapping::SubstitutionParamMapping (
32 : 12157837 : const HIR::TypeParam &generic, ParamType *param)
33 : 12157837 : : generic (generic), param (param)
34 : 12157837 : {}
35 : :
36 : 12504873 : SubstitutionParamMapping::SubstitutionParamMapping (
37 : 12504873 : const SubstitutionParamMapping &other)
38 : 12504873 : : generic (other.generic), param (other.param)
39 : 12504873 : {}
40 : :
41 : : std::string
42 : 69807 : SubstitutionParamMapping::as_string () const
43 : : {
44 : 69807 : if (param == nullptr)
45 : 0 : return "nullptr";
46 : :
47 : 69807 : return param->get_name ();
48 : : }
49 : :
50 : : SubstitutionParamMapping
51 : 12149145 : SubstitutionParamMapping::clone () const
52 : : {
53 : 12149145 : return SubstitutionParamMapping (generic,
54 : 12149145 : static_cast<ParamType *> (param->clone ()));
55 : : }
56 : :
57 : : ParamType *
58 : 66081 : SubstitutionParamMapping::get_param_ty ()
59 : : {
60 : 66081 : return param;
61 : : }
62 : :
63 : : const ParamType *
64 : 11998841 : SubstitutionParamMapping::get_param_ty () const
65 : : {
66 : 11998841 : return param;
67 : : }
68 : :
69 : : const HIR::TypeParam &
70 : 0 : SubstitutionParamMapping::get_generic_param () const
71 : : {
72 : 0 : return generic;
73 : : }
74 : :
75 : : bool
76 : 27034 : SubstitutionParamMapping::needs_substitution () const
77 : : {
78 : 27034 : return !(get_param_ty ()->is_concrete ());
79 : : }
80 : :
81 : : location_t
82 : 707 : SubstitutionParamMapping::get_param_locus () const
83 : : {
84 : 707 : return generic.get_locus ();
85 : : }
86 : :
87 : : bool
88 : 11099 : SubstitutionParamMapping::param_has_default_ty () const
89 : : {
90 : 11099 : return generic.has_type ();
91 : : }
92 : :
93 : : BaseType *
94 : 243 : SubstitutionParamMapping::get_default_ty () const
95 : : {
96 : 243 : TyVar var (generic.get_type_mappings ().get_hirid ());
97 : 243 : return var.get_tyty ();
98 : : }
99 : :
100 : : bool
101 : 0 : SubstitutionParamMapping::need_substitution () const
102 : : {
103 : 0 : if (!param->can_resolve ())
104 : : return true;
105 : :
106 : 0 : auto resolved = param->resolve ();
107 : 0 : return !resolved->is_concrete ();
108 : : }
109 : :
110 : : bool
111 : 14123 : SubstitutionParamMapping::fill_param_ty (
112 : : SubstitutionArgumentMappings &subst_mappings, location_t locus)
113 : : {
114 : 14123 : SubstitutionArg arg = SubstitutionArg::error ();
115 : 14123 : bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
116 : 14123 : if (!ok)
117 : : return true;
118 : :
119 : 14123 : TyTy::BaseType &type = *arg.get_tyty ();
120 : 14123 : if (type.get_kind () == TyTy::TypeKind::INFER)
121 : : {
122 : 4989 : type.inherit_bounds (*param);
123 : : }
124 : :
125 : 14123 : if (type.get_kind () == TypeKind::PARAM)
126 : : {
127 : : // delete param;
128 : 1844 : param = static_cast<ParamType *> (type.clone ());
129 : : }
130 : : else
131 : : {
132 : : // check the substitution is compatible with bounds
133 : 12279 : rust_debug_loc (locus,
134 : : "fill_param_ty bounds_compatible: param %s type %s",
135 : 24558 : param->get_name ().c_str (), type.get_name ().c_str ());
136 : :
137 : 12279 : if (!param->is_implicit_self_trait ())
138 : : {
139 : 7448 : if (!param->bounds_compatible (type, locus, true))
140 : : return false;
141 : : }
142 : :
143 : : // recursively pass this down to all HRTB's
144 : 27109 : for (auto &bound : param->get_specified_bounds ())
145 : 14834 : bound.handle_substitions (subst_mappings);
146 : :
147 : 12275 : param->set_ty_ref (type.get_ref ());
148 : 12275 : subst_mappings.on_param_subst (*param, arg);
149 : : }
150 : :
151 : : return true;
152 : : }
153 : :
154 : : void
155 : 3133 : SubstitutionParamMapping::override_context ()
156 : : {
157 : 3133 : if (!param->can_resolve ())
158 : : return;
159 : :
160 : 3110 : auto mappings = Analysis::Mappings::get ();
161 : 3110 : auto context = Resolver::TypeCheckContext::get ();
162 : :
163 : 3110 : context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
164 : : UNKNOWN_NODEID,
165 : 3110 : param->get_ref (),
166 : : UNKNOWN_LOCAL_DEFID),
167 : 3110 : param->resolve ());
168 : : }
169 : :
170 : 12018713 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
171 : 12018713 : BaseType *argument)
172 : 12018713 : : param (param), argument (argument)
173 : : {
174 : 12018713 : if (param != nullptr)
175 : 11955006 : original_param = param->get_param_ty ();
176 : 12018713 : }
177 : :
178 : 47973644 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
179 : 47973644 : : param (other.param), original_param (other.original_param),
180 : 47973644 : argument (other.argument)
181 : 47973644 : {}
182 : :
183 : : SubstitutionArg &
184 : 58694 : SubstitutionArg::operator= (const SubstitutionArg &other)
185 : : {
186 : 58694 : param = other.param;
187 : 58694 : argument = other.argument;
188 : 58694 : original_param = other.original_param;
189 : :
190 : 58694 : return *this;
191 : : }
192 : :
193 : : BaseType *
194 : 62531 : SubstitutionArg::get_tyty ()
195 : : {
196 : 62531 : return argument;
197 : : }
198 : :
199 : : const BaseType *
200 : 12161813 : SubstitutionArg::get_tyty () const
201 : : {
202 : 12161813 : return argument;
203 : : }
204 : :
205 : : const SubstitutionParamMapping *
206 : 3289 : SubstitutionArg::get_param_mapping () const
207 : : {
208 : 3289 : return param;
209 : : }
210 : :
211 : : const ParamType *
212 : 67620 : SubstitutionArg::get_param_ty () const
213 : : {
214 : 67620 : return original_param;
215 : : }
216 : :
217 : : SubstitutionArg
218 : 63707 : SubstitutionArg::error ()
219 : : {
220 : 63707 : return SubstitutionArg (nullptr, nullptr);
221 : : }
222 : :
223 : : bool
224 : 20793 : SubstitutionArg::is_error () const
225 : : {
226 : 20793 : return param == nullptr || argument == nullptr;
227 : : }
228 : :
229 : : bool
230 : 0 : SubstitutionArg::is_conrete () const
231 : : {
232 : 0 : if (argument == nullptr)
233 : : return false;
234 : :
235 : 0 : if (argument->get_kind () == TyTy::TypeKind::PARAM)
236 : : return false;
237 : :
238 : 0 : return argument->is_concrete ();
239 : : }
240 : :
241 : : std::string
242 : 0 : SubstitutionArg::as_string () const
243 : : {
244 : 0 : return original_param->as_string ()
245 : 0 : + (argument != nullptr ? ":" + argument->as_string () : "");
246 : : }
247 : :
248 : : const RegionParamList &
249 : 11864184 : SubstitutionArgumentMappings::get_regions () const
250 : : {
251 : 11864184 : return regions;
252 : : }
253 : :
254 : : RegionParamList &
255 : 734 : SubstitutionArgumentMappings::get_mut_regions ()
256 : : {
257 : 734 : return regions;
258 : : }
259 : :
260 : : // SubstitutionArgumentMappings
261 : :
262 : 23807086 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
263 : : std::vector<SubstitutionArg> mappings,
264 : : std::map<std::string, BaseType *> binding_args, RegionParamList regions,
265 : : location_t locus, ParamSubstCb param_subst_cb, bool trait_item_flag,
266 : 23807086 : bool error_flag)
267 : 23807086 : : mappings (std::move (mappings)), binding_args (binding_args),
268 : 23807086 : regions (regions), locus (locus), param_subst_cb (param_subst_cb),
269 : 23807086 : trait_item_flag (trait_item_flag), error_flag (error_flag)
270 : 23807086 : {}
271 : :
272 : 12052773 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
273 : 12052773 : const SubstitutionArgumentMappings &other)
274 : 12052773 : : mappings (other.mappings), binding_args (other.binding_args),
275 : 12052773 : regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
276 : 12052773 : trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
277 : 12052773 : {}
278 : :
279 : : SubstitutionArgumentMappings &
280 : 13548 : SubstitutionArgumentMappings::operator= (
281 : : const SubstitutionArgumentMappings &other)
282 : : {
283 : 13548 : mappings = other.mappings;
284 : 13548 : binding_args = other.binding_args;
285 : 13548 : regions = other.regions;
286 : 13548 : locus = other.locus;
287 : 13548 : param_subst_cb = nullptr;
288 : 13548 : trait_item_flag = other.trait_item_flag;
289 : 13548 : error_flag = other.error_flag;
290 : :
291 : 13548 : return *this;
292 : : }
293 : :
294 : : SubstitutionArgumentMappings
295 : 14794 : SubstitutionArgumentMappings::error ()
296 : : {
297 : 14794 : return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
298 : 14794 : false, true);
299 : : }
300 : :
301 : : SubstitutionArgumentMappings
302 : 11926960 : SubstitutionArgumentMappings::empty (size_t num_regions)
303 : : {
304 : 11926960 : return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
305 : 11926960 : nullptr, false, false);
306 : : }
307 : :
308 : : bool
309 : 9836 : SubstitutionArgumentMappings::is_error () const
310 : : {
311 : 9836 : return error_flag;
312 : : }
313 : :
314 : : bool
315 : 58556 : SubstitutionArgumentMappings::get_argument_for_symbol (
316 : : const ParamType *param_to_find, SubstitutionArg *argument) const
317 : : {
318 : 74310 : for (const auto &mapping : mappings)
319 : : {
320 : 67620 : const ParamType *p = mapping.get_param_ty ();
321 : 67620 : if (p->get_symbol () == param_to_find->get_symbol ())
322 : : {
323 : 51866 : *argument = mapping;
324 : 51866 : return true;
325 : : }
326 : : }
327 : : return false;
328 : : }
329 : : tl::optional<size_t>
330 : 0 : SubstitutionArgumentMappings::find_symbol (const ParamType ¶m_to_find) const
331 : : {
332 : 0 : auto it = std::find_if (mappings.begin (), mappings.end (),
333 : 0 : [param_to_find] (const SubstitutionArg &arg) {
334 : 0 : return arg.get_param_ty ()->get_symbol ()
335 : 0 : == param_to_find.get_symbol ();
336 : : });
337 : 0 : if (it == mappings.end ())
338 : 0 : return tl::nullopt;
339 : 0 : return std::distance (mappings.begin (), it);
340 : : }
341 : :
342 : : bool
343 : 5151 : SubstitutionArgumentMappings::get_argument_at (size_t index,
344 : : SubstitutionArg *argument)
345 : : {
346 : 5151 : if (index > mappings.size ())
347 : : return false;
348 : :
349 : 5151 : *argument = mappings.at (index);
350 : 5151 : return true;
351 : : }
352 : :
353 : : bool
354 : 0 : SubstitutionArgumentMappings::is_concrete () const
355 : : {
356 : 0 : for (auto &mapping : mappings)
357 : : {
358 : 0 : if (!mapping.is_conrete ())
359 : 0 : return false;
360 : : }
361 : : return true;
362 : : }
363 : :
364 : : location_t
365 : 11869343 : SubstitutionArgumentMappings::get_locus () const
366 : : {
367 : 11869343 : return locus;
368 : : }
369 : :
370 : : size_t
371 : 17595 : SubstitutionArgumentMappings::size () const
372 : : {
373 : 17595 : return mappings.size ();
374 : : }
375 : :
376 : : bool
377 : 7510 : SubstitutionArgumentMappings::is_empty () const
378 : : {
379 : 7510 : return size () == 0;
380 : : }
381 : :
382 : : std::vector<SubstitutionArg> &
383 : 27564 : SubstitutionArgumentMappings::get_mappings ()
384 : : {
385 : 27564 : return mappings;
386 : : }
387 : :
388 : : const std::vector<SubstitutionArg> &
389 : 47548388 : SubstitutionArgumentMappings::get_mappings () const
390 : : {
391 : 47548388 : return mappings;
392 : : }
393 : :
394 : : std::map<std::string, BaseType *> &
395 : 22353 : SubstitutionArgumentMappings::get_binding_args ()
396 : : {
397 : 22353 : return binding_args;
398 : : }
399 : :
400 : : const std::map<std::string, BaseType *> &
401 : 0 : SubstitutionArgumentMappings::get_binding_args () const
402 : : {
403 : 0 : return binding_args;
404 : : }
405 : :
406 : : std::string
407 : 0 : SubstitutionArgumentMappings::as_string () const
408 : : {
409 : 0 : std::string buffer;
410 : 0 : for (auto &mapping : mappings)
411 : : {
412 : 0 : buffer += mapping.as_string () + ", ";
413 : : }
414 : 0 : return "<" + buffer + ">";
415 : 0 : }
416 : :
417 : : void
418 : 27549 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
419 : : const SubstitutionArg &a) const
420 : : {
421 : 27549 : if (param_subst_cb == nullptr)
422 : : return;
423 : :
424 : 394 : param_subst_cb (p, a);
425 : : }
426 : :
427 : : ParamSubstCb
428 : 6957 : SubstitutionArgumentMappings::get_subst_cb () const
429 : : {
430 : 6957 : return param_subst_cb;
431 : : }
432 : :
433 : : bool
434 : 4842 : SubstitutionArgumentMappings::trait_item_mode () const
435 : : {
436 : 4842 : return trait_item_flag;
437 : : }
438 : :
439 : : // SubstitutionRef
440 : :
441 : 11949154 : SubstitutionRef::SubstitutionRef (
442 : : std::vector<SubstitutionParamMapping> substitutions,
443 : 11949154 : SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
444 : 11949154 : : substitutions (substitutions), used_arguments (arguments),
445 : 23898308 : region_constraints (region_constraints)
446 : 11949154 : {}
447 : :
448 : : bool
449 : 63064 : SubstitutionRef::has_substitutions () const
450 : : {
451 : 63064 : return substitutions.size () > 0;
452 : : }
453 : :
454 : : std::string
455 : 142530 : SubstitutionRef::subst_as_string () const
456 : : {
457 : 142530 : std::string buffer;
458 : 212337 : for (size_t i = 0; i < substitutions.size (); i++)
459 : : {
460 : 69807 : const SubstitutionParamMapping &sub = substitutions.at (i);
461 : 69807 : buffer += sub.as_string ();
462 : :
463 : 69807 : if ((i + 1) < substitutions.size ())
464 : 7029 : buffer += ", ";
465 : : }
466 : :
467 : 205308 : return buffer.empty () ? "" : "<" + buffer + ">";
468 : 142530 : }
469 : :
470 : : bool
471 : 44 : SubstitutionRef::supports_associated_bindings () const
472 : : {
473 : 44 : return get_num_associated_bindings () > 0;
474 : : }
475 : :
476 : : size_t
477 : 1 : SubstitutionRef::get_num_associated_bindings () const
478 : : {
479 : 1 : return 0;
480 : : }
481 : :
482 : : TypeBoundPredicateItem
483 : 0 : SubstitutionRef::lookup_associated_type (const std::string &search)
484 : : {
485 : 0 : return TypeBoundPredicateItem::error ();
486 : : }
487 : :
488 : : size_t
489 : 19655 : SubstitutionRef::get_num_substitutions () const
490 : : {
491 : 19655 : return substitutions.size ();
492 : : }
493 : : size_t
494 : 0 : SubstitutionRef::get_num_lifetime_params () const
495 : : {
496 : 0 : return used_arguments.get_regions ().size ();
497 : : }
498 : : size_t
499 : 0 : SubstitutionRef::get_num_type_params () const
500 : : {
501 : 0 : return get_num_substitutions ();
502 : : }
503 : :
504 : : std::vector<SubstitutionParamMapping> &
505 : 54664 : SubstitutionRef::get_substs ()
506 : : {
507 : 54664 : return substitutions;
508 : : }
509 : :
510 : : const std::vector<SubstitutionParamMapping> &
511 : 11862166 : SubstitutionRef::get_substs () const
512 : : {
513 : 11862166 : return substitutions;
514 : : }
515 : :
516 : : std::vector<SubstitutionParamMapping>
517 : 50347 : SubstitutionRef::clone_substs () const
518 : : {
519 : 50347 : std::vector<SubstitutionParamMapping> clone;
520 : :
521 : 81775 : for (auto &sub : substitutions)
522 : 31428 : clone.push_back (sub.clone ());
523 : :
524 : 50347 : return clone;
525 : : }
526 : :
527 : : void
528 : 2855 : SubstitutionRef::override_context ()
529 : : {
530 : 5988 : for (auto &sub : substitutions)
531 : : {
532 : 3133 : sub.override_context ();
533 : : }
534 : 2855 : }
535 : :
536 : : bool
537 : 17502 : SubstitutionRef::needs_substitution () const
538 : : {
539 : 17502 : return std::any_of (substitutions.begin (), substitutions.end (),
540 : : std::mem_fn (
541 : 17502 : &SubstitutionParamMapping::needs_substitution));
542 : : }
543 : :
544 : : bool
545 : 63 : SubstitutionRef::was_substituted () const
546 : : {
547 : 63 : return !needs_substitution ();
548 : : }
549 : :
550 : : SubstitutionArgumentMappings &
551 : 12051 : SubstitutionRef::get_substitution_arguments ()
552 : : {
553 : 12051 : return used_arguments;
554 : : }
555 : :
556 : : const SubstitutionArgumentMappings &
557 : 18220 : SubstitutionRef::get_substitution_arguments () const
558 : : {
559 : 18220 : return used_arguments;
560 : : }
561 : :
562 : : size_t
563 : 4565 : SubstitutionRef::num_required_substitutions () const
564 : : {
565 : 4565 : size_t n = 0;
566 : 10031 : for (auto &p : substitutions)
567 : : {
568 : 5466 : if (p.needs_substitution ())
569 : 5424 : n++;
570 : : }
571 : 4565 : return n;
572 : : }
573 : :
574 : : size_t
575 : 9136 : SubstitutionRef::min_required_substitutions () const
576 : : {
577 : 9136 : size_t n = 0;
578 : 20076 : for (auto &p : substitutions)
579 : : {
580 : 10940 : if (p.needs_substitution () && !p.param_has_default_ty ())
581 : 10092 : n++;
582 : : }
583 : 9136 : return n;
584 : : }
585 : :
586 : : const SubstitutionArgumentMappings &
587 : 811 : SubstitutionRef::get_used_arguments () const
588 : : {
589 : 811 : return used_arguments;
590 : : }
591 : :
592 : : const RegionConstraints &
593 : 49219 : SubstitutionRef::get_region_constraints () const
594 : : {
595 : 49219 : return region_constraints;
596 : : }
597 : :
598 : : SubstitutionArgumentMappings
599 : 4571 : SubstitutionRef::get_mappings_from_generic_args (
600 : : HIR::GenericArgs &args, const std::vector<Region> ®ions)
601 : : {
602 : 4571 : std::map<std::string, BaseType *> binding_arguments;
603 : 4571 : if (args.get_binding_args ().size () > 0)
604 : : {
605 : 44 : if (supports_associated_bindings ())
606 : : {
607 : 43 : if (args.get_binding_args ().size () > get_num_associated_bindings ())
608 : : {
609 : 0 : rich_location r (line_table, args.get_locus ());
610 : :
611 : 0 : rust_error_at (r,
612 : : "generic item takes at most %lu type binding "
613 : : "arguments but %lu were supplied",
614 : 0 : (unsigned long) get_num_associated_bindings (),
615 : 0 : (unsigned long) args.get_binding_args ().size ());
616 : 0 : return SubstitutionArgumentMappings::error ();
617 : 0 : }
618 : :
619 : 86 : for (auto &binding : args.get_binding_args ())
620 : : {
621 : 43 : BaseType *resolved
622 : 43 : = Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
623 : 43 : if (resolved == nullptr
624 : 43 : || resolved->get_kind () == TyTy::TypeKind::ERROR)
625 : : {
626 : 0 : rust_error_at (binding.get_locus (),
627 : : "failed to resolve type arguments");
628 : 0 : return SubstitutionArgumentMappings::error ();
629 : : }
630 : :
631 : : // resolve to relevant binding
632 : 43 : auto binding_item = lookup_associated_type (
633 : 43 : binding.get_identifier ().as_string ());
634 : 43 : if (binding_item.is_error ())
635 : : {
636 : 0 : rust_error_at (
637 : : binding.get_locus (), "unknown associated type binding: %s",
638 : 0 : binding.get_identifier ().as_string ().c_str ());
639 : 0 : return SubstitutionArgumentMappings::error ();
640 : : }
641 : :
642 : 43 : binding_arguments[binding.get_identifier ().as_string ()]
643 : 43 : = resolved;
644 : : }
645 : : }
646 : : else
647 : : {
648 : 1 : rich_location r (line_table, args.get_locus ());
649 : 3 : for (auto &binding : args.get_binding_args ())
650 : 2 : r.add_range (binding.get_locus ());
651 : :
652 : 1 : rust_error_at (r, ErrorCode::E0229,
653 : : "associated type bindings are not allowed here");
654 : 1 : return SubstitutionArgumentMappings::error ();
655 : 1 : }
656 : : }
657 : :
658 : : // for inherited arguments
659 : 4570 : size_t offs = used_arguments.size ();
660 : 4570 : if (args.get_type_args ().size () + offs > substitutions.size ())
661 : : {
662 : 2 : rich_location r (line_table, args.get_locus ());
663 : 2 : if (!substitutions.empty ())
664 : 1 : r.add_range (substitutions.front ().get_param_locus ());
665 : :
666 : 2 : rust_error_at (
667 : : r,
668 : : "generic item takes at most %lu type arguments but %lu were supplied",
669 : 2 : (unsigned long) substitutions.size (),
670 : 2 : (unsigned long) args.get_type_args ().size ());
671 : 2 : return SubstitutionArgumentMappings::error ();
672 : 2 : }
673 : :
674 : 4568 : if (args.get_type_args ().size () + offs < min_required_substitutions ())
675 : : {
676 : 3 : rich_location r (line_table, args.get_locus ());
677 : 3 : r.add_range (substitutions.front ().get_param_locus ());
678 : :
679 : 3 : rust_error_at (
680 : : r, ErrorCode::E0107,
681 : : "generic item takes at least %lu type arguments but %lu were supplied",
682 : 3 : (unsigned long) (min_required_substitutions () - offs),
683 : 3 : (unsigned long) args.get_type_args ().size ());
684 : 3 : return SubstitutionArgumentMappings::error ();
685 : 3 : }
686 : :
687 : 4565 : std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
688 : 9552 : for (auto &arg : args.get_type_args ())
689 : : {
690 : 4987 : BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
691 : 4987 : if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
692 : : {
693 : 0 : rust_error_at (args.get_locus (), "failed to resolve type arguments");
694 : 0 : return SubstitutionArgumentMappings::error ();
695 : : }
696 : :
697 : 4987 : SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
698 : 4987 : offs++;
699 : 4987 : mappings.push_back (std::move (subst_arg));
700 : : }
701 : :
702 : : // we must need to fill out defaults
703 : 4565 : size_t left_over
704 : 4565 : = num_required_substitutions () - min_required_substitutions ();
705 : 4565 : if (left_over > 0)
706 : : {
707 : 625 : for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
708 : : {
709 : 243 : SubstitutionParamMapping ¶m = substitutions.at (offs);
710 : 243 : rust_assert (param.param_has_default_ty ());
711 : :
712 : 243 : BaseType *resolved = param.get_default_ty ();
713 : 243 : if (resolved->get_kind () == TypeKind::ERROR)
714 : 0 : return SubstitutionArgumentMappings::error ();
715 : :
716 : : // this resolved default might already contain default parameters
717 : 243 : if (!resolved->is_concrete ())
718 : : {
719 : 229 : SubstitutionArgumentMappings intermediate (
720 : : mappings, binding_arguments,
721 : 229 : {used_arguments.get_regions ().size ()}, args.get_locus ());
722 : 229 : resolved = Resolver::SubstMapperInternal::Resolve (resolved,
723 : : intermediate);
724 : :
725 : 229 : if (resolved->get_kind () == TypeKind::ERROR)
726 : 0 : return SubstitutionArgumentMappings::error ();
727 : 229 : }
728 : :
729 : 243 : SubstitutionArg subst_arg (¶m, resolved);
730 : 243 : mappings.push_back (std::move (subst_arg));
731 : : }
732 : : }
733 : :
734 : 4565 : return {mappings, binding_arguments,
735 : 9130 : RegionParamList::from_subst (used_arguments.get_regions ().size (),
736 : : regions),
737 : 13695 : args.get_locus ()};
738 : 4565 : }
739 : :
740 : : BaseType *
741 : 2646 : SubstitutionRef::infer_substitions (location_t locus)
742 : : {
743 : 2646 : std::vector<SubstitutionArg> args;
744 : 2646 : std::map<std::string, BaseType *> argument_mappings;
745 : 5689 : for (auto &p : get_substs ())
746 : : {
747 : 3043 : if (p.needs_substitution ())
748 : : {
749 : 2987 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
750 : 2987 : auto it = argument_mappings.find (symbol);
751 : 2987 : bool have_mapping = it != argument_mappings.end ();
752 : :
753 : 2987 : if (have_mapping)
754 : : {
755 : 7 : args.push_back (SubstitutionArg (&p, it->second));
756 : : }
757 : : else
758 : : {
759 : 2980 : TyVar infer_var = TyVar::get_implicit_infer_var (locus);
760 : 2980 : args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
761 : 2980 : argument_mappings[symbol] = infer_var.get_tyty ();
762 : : }
763 : 2987 : }
764 : : else
765 : : {
766 : 56 : args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
767 : : }
768 : : }
769 : :
770 : : // FIXME do we need to add inference variables to all the possible bindings?
771 : : // it might just lead to inference variable hell not 100% sure if rustc does
772 : : // this i think the language might needs this to be explicitly set
773 : :
774 : 2646 : SubstitutionArgumentMappings infer_arguments (std::move (args),
775 : : {} /* binding_arguments */,
776 : : used_arguments.get_regions (),
777 : 2646 : locus);
778 : 2646 : return handle_substitions (infer_arguments);
779 : 2646 : }
780 : :
781 : : SubstitutionArgumentMappings
782 : 4438 : SubstitutionRef::adjust_mappings_for_this (
783 : : SubstitutionArgumentMappings &mappings)
784 : : {
785 : 4438 : std::vector<SubstitutionArg> resolved_mappings;
786 : 9890 : for (size_t i = 0; i < substitutions.size (); i++)
787 : : {
788 : 5452 : auto &subst = substitutions.at (i);
789 : :
790 : 5452 : SubstitutionArg arg = SubstitutionArg::error ();
791 : 5452 : if (mappings.size () == substitutions.size ())
792 : : {
793 : 5151 : mappings.get_argument_at (i, &arg);
794 : : }
795 : : else
796 : : {
797 : 301 : if (subst.needs_substitution ())
798 : : {
799 : : // get from passed in mappings
800 : 231 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
801 : : }
802 : : else
803 : : {
804 : : // we should already have this somewhere
805 : 70 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
806 : : &arg);
807 : : }
808 : : }
809 : :
810 : 5452 : bool ok = !arg.is_error ();
811 : 5452 : if (ok)
812 : : {
813 : 5403 : SubstitutionArg adjusted (&subst, arg.get_tyty ());
814 : 5403 : resolved_mappings.push_back (std::move (adjusted));
815 : : }
816 : : }
817 : :
818 : 4438 : if (resolved_mappings.empty ())
819 : 0 : return SubstitutionArgumentMappings::error ();
820 : :
821 : 4438 : return SubstitutionArgumentMappings (resolved_mappings,
822 : 4438 : mappings.get_binding_args (),
823 : : mappings.get_regions (),
824 : : mappings.get_locus (),
825 : 4438 : mappings.get_subst_cb (),
826 : 8876 : mappings.trait_item_mode ());
827 : 4438 : }
828 : :
829 : : bool
830 : 0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
831 : : {
832 : 0 : std::vector<SubstitutionArg> resolved_mappings;
833 : 0 : for (size_t i = 0; i < substitutions.size (); i++)
834 : : {
835 : 0 : auto &subst = substitutions.at (i);
836 : :
837 : 0 : SubstitutionArg arg = SubstitutionArg::error ();
838 : 0 : if (mappings.size () == substitutions.size ())
839 : : {
840 : 0 : mappings.get_argument_at (i, &arg);
841 : : }
842 : : else
843 : : {
844 : 0 : if (subst.needs_substitution ())
845 : : {
846 : : // get from passed in mappings
847 : 0 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
848 : : }
849 : : else
850 : : {
851 : : // we should already have this somewhere
852 : 0 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
853 : : &arg);
854 : : }
855 : : }
856 : :
857 : 0 : bool ok = !arg.is_error ();
858 : 0 : if (ok)
859 : : {
860 : 0 : SubstitutionArg adjusted (&subst, arg.get_tyty ());
861 : 0 : resolved_mappings.push_back (std::move (adjusted));
862 : : }
863 : : }
864 : :
865 : 0 : return !resolved_mappings.empty ();
866 : 0 : }
867 : :
868 : : // this function assumes that the mappings being passed are for the same type as
869 : : // this new substitution reference so ordering matters here
870 : : SubstitutionArgumentMappings
871 : 63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
872 : : SubstitutionArgumentMappings &mappings) const
873 : : {
874 : 63 : std::vector<SubstitutionArg> resolved_mappings;
875 : :
876 : 63 : rust_assert (mappings.size () == get_num_substitutions ());
877 : 126 : for (size_t i = 0; i < get_num_substitutions (); i++)
878 : : {
879 : 63 : const SubstitutionParamMapping ¶m_mapping = substitutions.at (i);
880 : 63 : SubstitutionArg &arg = mappings.get_mappings ().at (i);
881 : :
882 : 63 : if (param_mapping.needs_substitution ())
883 : : {
884 : 63 : SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ());
885 : 63 : resolved_mappings.push_back (std::move (adjusted));
886 : : }
887 : : }
888 : :
889 : 63 : return SubstitutionArgumentMappings (resolved_mappings,
890 : 63 : mappings.get_binding_args (),
891 : : mappings.get_regions (),
892 : 126 : mappings.get_locus ());
893 : 63 : }
894 : :
895 : : void
896 : 1325 : SubstitutionRef::prepare_higher_ranked_bounds ()
897 : : {
898 : 2444 : for (const auto &subst : get_substs ())
899 : : {
900 : 1119 : const TyTy::ParamType *pty = subst.get_param_ty ();
901 : 2529 : for (const auto &bound : pty->get_specified_bounds ())
902 : : {
903 : 1410 : const auto ref = bound.get ();
904 : 1410 : ref->clear_associated_type_projections ();
905 : : }
906 : : }
907 : 1325 : }
908 : :
909 : : bool
910 : 8310 : SubstitutionRef::monomorphize ()
911 : : {
912 : 13059 : for (const auto &subst : get_substs ())
913 : : {
914 : 4749 : const TyTy::ParamType *pty = subst.get_param_ty ();
915 : :
916 : 4749 : if (!pty->can_resolve ())
917 : 64 : continue;
918 : :
919 : 4685 : const TyTy::BaseType *binding = pty->resolve ();
920 : 4685 : if (binding->get_kind () == TyTy::TypeKind::PARAM)
921 : 801 : continue;
922 : :
923 : 8317 : for (const auto &bound : pty->get_specified_bounds ())
924 : : {
925 : 4433 : bool ambigious = false;
926 : 4433 : auto associated
927 : 4433 : = Resolver::lookup_associated_impl_block (bound, binding,
928 : : &ambigious);
929 : 4433 : if (associated == nullptr && ambigious)
930 : : {
931 : : // go for the first one? or error out?
932 : 0 : auto &mappings = *Analysis::Mappings::get ();
933 : 0 : const auto &type_param = subst.get_generic_param ();
934 : 0 : const auto *trait_ref = bound.get ();
935 : :
936 : 0 : rich_location r (line_table, type_param.get_locus ());
937 : 0 : r.add_range (bound.get_locus ());
938 : 0 : r.add_range (mappings.lookup_location (binding->get_ref ()));
939 : :
940 : 0 : rust_error_at (r, "ambiguous type bound for trait %s and type %s",
941 : 0 : trait_ref->get_name ().c_str (),
942 : 0 : binding->get_name ().c_str ());
943 : 0 : return false;
944 : 0 : }
945 : :
946 : : if (associated != nullptr)
947 : : {
948 : 771 : associated->setup_associated_types (binding, bound);
949 : : }
950 : : }
951 : : }
952 : :
953 : : return true;
954 : : }
955 : :
956 : : } // namespace TyTy
957 : : } // namespace Rust
|