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 "rust-system.h"
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 : 12158284 : SubstitutionParamMapping::SubstitutionParamMapping (
32 : 12158284 : const HIR::TypeParam &generic, ParamType *param)
33 : 12158284 : : generic (generic), param (param)
34 : 12158284 : {}
35 : :
36 : 12505344 : SubstitutionParamMapping::SubstitutionParamMapping (
37 : 12505344 : const SubstitutionParamMapping &other)
38 : 12505344 : : generic (other.generic), param (other.param)
39 : 12505344 : {}
40 : :
41 : : std::string
42 : 70747 : SubstitutionParamMapping::as_string () const
43 : : {
44 : 70747 : if (param == nullptr)
45 : 0 : return "nullptr";
46 : :
47 : 70747 : return param->get_name ();
48 : : }
49 : :
50 : : SubstitutionParamMapping
51 : 12149589 : SubstitutionParamMapping::clone () const
52 : : {
53 : 12149589 : return SubstitutionParamMapping (generic,
54 : 12149589 : static_cast<ParamType *> (param->clone ()));
55 : : }
56 : :
57 : : ParamType *
58 : 66099 : SubstitutionParamMapping::get_param_ty ()
59 : : {
60 : 66099 : return param;
61 : : }
62 : :
63 : : const ParamType *
64 : 11999383 : SubstitutionParamMapping::get_param_ty () const
65 : : {
66 : 11999383 : return param;
67 : : }
68 : :
69 : : const HIR::TypeParam &
70 : 1470 : SubstitutionParamMapping::get_generic_param () const
71 : : {
72 : 1470 : return generic;
73 : : }
74 : :
75 : : bool
76 : 27043 : SubstitutionParamMapping::needs_substitution () const
77 : : {
78 : 27043 : 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 : 11101 : SubstitutionParamMapping::param_has_default_ty () const
89 : : {
90 : 11101 : 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 : 14127 : SubstitutionParamMapping::fill_param_ty (
112 : : SubstitutionArgumentMappings &subst_mappings, location_t locus)
113 : : {
114 : 14127 : SubstitutionArg arg = SubstitutionArg::error ();
115 : 14127 : bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
116 : 14127 : if (!ok)
117 : : return true;
118 : :
119 : 14127 : TyTy::BaseType &type = *arg.get_tyty ();
120 : 14127 : if (type.get_kind () == TyTy::TypeKind::INFER)
121 : : {
122 : 4991 : type.inherit_bounds (*param);
123 : : }
124 : :
125 : 14127 : 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 : 12283 : rust_debug_loc (locus,
134 : : "fill_param_ty bounds_compatible: param %s type %s",
135 : 24566 : param->get_name ().c_str (), type.get_name ().c_str ());
136 : :
137 : 12283 : if (!param->is_implicit_self_trait ())
138 : : {
139 : 7449 : if (!param->bounds_compatible (type, locus, true))
140 : : return false;
141 : : }
142 : :
143 : : // recursively pass this down to all HRTB's
144 : 27117 : for (auto &bound : param->get_specified_bounds ())
145 : 14838 : bound.handle_substitions (subst_mappings);
146 : :
147 : 12279 : param->set_ty_ref (type.get_ref ());
148 : 12279 : subst_mappings.on_param_subst (*param, arg);
149 : : }
150 : :
151 : : return true;
152 : : }
153 : :
154 : : void
155 : 3134 : SubstitutionParamMapping::override_context ()
156 : : {
157 : 3134 : if (!param->can_resolve ())
158 : : return;
159 : :
160 : 3111 : auto mappings = Analysis::Mappings::get ();
161 : 3111 : auto context = Resolver::TypeCheckContext::get ();
162 : :
163 : 3111 : context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
164 : : UNKNOWN_NODEID,
165 : 3111 : param->get_ref (),
166 : 3111 : UNKNOWN_LOCAL_DEFID),
167 : 3111 : param->resolve ());
168 : : }
169 : :
170 : 12019260 : SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
171 : 12019260 : BaseType *argument)
172 : 12019260 : : param (param), argument (argument)
173 : : {
174 : 12019260 : if (param != nullptr)
175 : 11955441 : original_param = param->get_param_ty ();
176 : 12019260 : }
177 : :
178 : 47975454 : SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
179 : 47975454 : : param (other.param), original_param (other.original_param),
180 : 47975454 : argument (other.argument)
181 : 47975454 : {}
182 : :
183 : : SubstitutionArg &
184 : 58804 : SubstitutionArg::operator= (const SubstitutionArg &other)
185 : : {
186 : 58804 : param = other.param;
187 : 58804 : argument = other.argument;
188 : 58804 : original_param = other.original_param;
189 : :
190 : 58804 : return *this;
191 : : }
192 : :
193 : : BaseType *
194 : 62644 : SubstitutionArg::get_tyty ()
195 : : {
196 : 62644 : return argument;
197 : : }
198 : :
199 : : const BaseType *
200 : 12162252 : SubstitutionArg::get_tyty () const
201 : : {
202 : 12162252 : return argument;
203 : : }
204 : :
205 : : const SubstitutionParamMapping *
206 : 3290 : SubstitutionArg::get_param_mapping () const
207 : : {
208 : 3290 : return param;
209 : : }
210 : :
211 : : const ParamType *
212 : 67731 : SubstitutionArg::get_param_ty () const
213 : : {
214 : 67731 : return original_param;
215 : : }
216 : :
217 : : SubstitutionArg
218 : 63819 : SubstitutionArg::error ()
219 : : {
220 : 63819 : return SubstitutionArg (nullptr, nullptr);
221 : : }
222 : :
223 : : bool
224 : 20896 : SubstitutionArg::is_error () const
225 : : {
226 : 20896 : 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 : 11870680 : SubstitutionArgumentMappings::get_regions () const
250 : : {
251 : 11870680 : return regions;
252 : : }
253 : :
254 : : RegionParamList &
255 : 735 : SubstitutionArgumentMappings::get_mut_regions ()
256 : : {
257 : 735 : return regions;
258 : : }
259 : :
260 : : // SubstitutionArgumentMappings
261 : :
262 : 23808041 : 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 : 23808041 : bool error_flag)
267 : 23808041 : : mappings (std::move (mappings)), binding_args (binding_args),
268 : 23808041 : regions (regions), locus (locus), param_subst_cb (param_subst_cb),
269 : 23808041 : trait_item_flag (trait_item_flag), error_flag (error_flag)
270 : 23808041 : {}
271 : :
272 : 12053444 : SubstitutionArgumentMappings::SubstitutionArgumentMappings (
273 : 12053444 : const SubstitutionArgumentMappings &other)
274 : 12053444 : : mappings (other.mappings), binding_args (other.binding_args),
275 : 12053444 : regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
276 : 12053444 : trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
277 : 12053444 : {}
278 : :
279 : : SubstitutionArgumentMappings &
280 : 13562 : SubstitutionArgumentMappings::operator= (
281 : : const SubstitutionArgumentMappings &other)
282 : : {
283 : 13562 : mappings = other.mappings;
284 : 13562 : binding_args = other.binding_args;
285 : 13562 : regions = other.regions;
286 : 13562 : locus = other.locus;
287 : 13562 : param_subst_cb = nullptr;
288 : 13562 : trait_item_flag = other.trait_item_flag;
289 : 13562 : error_flag = other.error_flag;
290 : :
291 : 13562 : return *this;
292 : : }
293 : :
294 : : SubstitutionArgumentMappings
295 : 14808 : SubstitutionArgumentMappings::error ()
296 : : {
297 : 14808 : return SubstitutionArgumentMappings ({}, {}, 0, UNDEF_LOCATION, nullptr,
298 : 14808 : false, true);
299 : : }
300 : :
301 : : SubstitutionArgumentMappings
302 : 11927469 : SubstitutionArgumentMappings::empty (size_t num_regions)
303 : : {
304 : 11927469 : return SubstitutionArgumentMappings ({}, {}, num_regions, UNDEF_LOCATION,
305 : 11927469 : nullptr, false, false);
306 : : }
307 : :
308 : : bool
309 : 9845 : SubstitutionArgumentMappings::is_error () const
310 : : {
311 : 9845 : return error_flag;
312 : : }
313 : :
314 : : bool
315 : 58667 : SubstitutionArgumentMappings::get_argument_for_symbol (
316 : : const ParamType *param_to_find, SubstitutionArg *argument) const
317 : : {
318 : 74423 : for (const auto &mapping : mappings)
319 : : {
320 : 67731 : const ParamType *p = mapping.get_param_ty ();
321 : 67731 : if (p->get_symbol () == param_to_find->get_symbol ())
322 : : {
323 : 51975 : *argument = mapping;
324 : 51975 : 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 : 5152 : SubstitutionArgumentMappings::get_argument_at (size_t index,
344 : : SubstitutionArg *argument)
345 : : {
346 : 5152 : if (index > mappings.size ())
347 : : return false;
348 : :
349 : 5152 : *argument = mappings.at (index);
350 : 5152 : 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 : 11869772 : SubstitutionArgumentMappings::get_locus () const
366 : : {
367 : 11869772 : return locus;
368 : : }
369 : :
370 : : size_t
371 : 17603 : SubstitutionArgumentMappings::size () const
372 : : {
373 : 17603 : return mappings.size ();
374 : : }
375 : :
376 : : bool
377 : 7512 : SubstitutionArgumentMappings::is_empty () const
378 : : {
379 : 7512 : return size () == 0;
380 : : }
381 : :
382 : : std::vector<SubstitutionArg> &
383 : 27579 : SubstitutionArgumentMappings::get_mappings ()
384 : : {
385 : 27579 : return mappings;
386 : : }
387 : :
388 : : const std::vector<SubstitutionArg> &
389 : 47550090 : SubstitutionArgumentMappings::get_mappings () const
390 : : {
391 : 47550090 : return mappings;
392 : : }
393 : :
394 : : std::map<std::string, BaseType *> &
395 : 22359 : SubstitutionArgumentMappings::get_binding_args ()
396 : : {
397 : 22359 : 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 : 27559 : SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
419 : : const SubstitutionArg &a) const
420 : : {
421 : 27559 : if (param_subst_cb == nullptr)
422 : : return;
423 : :
424 : 394 : param_subst_cb (p, a);
425 : : }
426 : :
427 : : ParamSubstCb
428 : 6959 : SubstitutionArgumentMappings::get_subst_cb () const
429 : : {
430 : 6959 : return param_subst_cb;
431 : : }
432 : :
433 : : bool
434 : 4843 : SubstitutionArgumentMappings::trait_item_mode () const
435 : : {
436 : 4843 : return trait_item_flag;
437 : : }
438 : :
439 : : // SubstitutionRef
440 : :
441 : 11949713 : SubstitutionRef::SubstitutionRef (
442 : : std::vector<SubstitutionParamMapping> substitutions,
443 : 11949713 : SubstitutionArgumentMappings arguments, RegionConstraints region_constraints)
444 : 11949713 : : substitutions (substitutions), used_arguments (arguments),
445 : 23899426 : region_constraints (region_constraints)
446 : 11949713 : {}
447 : :
448 : : bool
449 : 63231 : SubstitutionRef::has_substitutions () const
450 : : {
451 : 63231 : return substitutions.size () > 0;
452 : : }
453 : :
454 : : std::string
455 : 145232 : SubstitutionRef::subst_as_string () const
456 : : {
457 : 145232 : std::string buffer;
458 : 215979 : for (size_t i = 0; i < substitutions.size (); i++)
459 : : {
460 : 70747 : const SubstitutionParamMapping &sub = substitutions.at (i);
461 : 70747 : buffer += sub.as_string ();
462 : :
463 : 70747 : if ((i + 1) < substitutions.size ())
464 : 7111 : buffer += ", ";
465 : : }
466 : :
467 : 208868 : return buffer.empty () ? "" : "<" + buffer + ">";
468 : 145232 : }
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 : 21697 : SubstitutionRef::get_num_substitutions () const
490 : : {
491 : 21697 : 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 : 58765 : SubstitutionRef::get_substs ()
506 : : {
507 : 58765 : return substitutions;
508 : : }
509 : :
510 : : const std::vector<SubstitutionParamMapping> &
511 : 11862694 : SubstitutionRef::get_substs () const
512 : : {
513 : 11862694 : return substitutions;
514 : : }
515 : :
516 : : std::vector<SubstitutionParamMapping>
517 : 50407 : SubstitutionRef::clone_substs () const
518 : : {
519 : 50407 : std::vector<SubstitutionParamMapping> clone;
520 : :
521 : 81839 : for (auto &sub : substitutions)
522 : 31432 : clone.push_back (sub.clone ());
523 : :
524 : 50407 : return clone;
525 : : }
526 : :
527 : : void
528 : 2856 : SubstitutionRef::override_context ()
529 : : {
530 : 5990 : for (auto &sub : substitutions)
531 : : {
532 : 3134 : sub.override_context ();
533 : : }
534 : 2856 : }
535 : :
536 : : bool
537 : 17605 : SubstitutionRef::needs_substitution () const
538 : : {
539 : 17605 : return std::any_of (substitutions.begin (), substitutions.end (),
540 : : std::mem_fn (
541 : 17605 : &SubstitutionParamMapping::needs_substitution));
542 : : }
543 : :
544 : : bool
545 : 63 : SubstitutionRef::was_substituted () const
546 : : {
547 : 63 : return !needs_substitution ();
548 : : }
549 : :
550 : : SubstitutionArgumentMappings &
551 : 12060 : SubstitutionRef::get_substitution_arguments ()
552 : : {
553 : 12060 : return used_arguments;
554 : : }
555 : :
556 : : const SubstitutionArgumentMappings &
557 : 18233 : SubstitutionRef::get_substitution_arguments () const
558 : : {
559 : 18233 : return used_arguments;
560 : : }
561 : :
562 : : size_t
563 : 4570 : SubstitutionRef::num_required_substitutions () const
564 : : {
565 : 4570 : size_t n = 0;
566 : 10037 : for (auto &p : substitutions)
567 : : {
568 : 5467 : if (p.needs_substitution ())
569 : 5425 : n++;
570 : : }
571 : 4570 : return n;
572 : : }
573 : :
574 : : size_t
575 : 9146 : SubstitutionRef::min_required_substitutions () const
576 : : {
577 : 9146 : size_t n = 0;
578 : 20088 : for (auto &p : substitutions)
579 : : {
580 : 10942 : if (p.needs_substitution () && !p.param_has_default_ty ())
581 : 10094 : n++;
582 : : }
583 : 9146 : return n;
584 : : }
585 : :
586 : : const SubstitutionArgumentMappings &
587 : 6971 : SubstitutionRef::get_used_arguments () const
588 : : {
589 : 6971 : return used_arguments;
590 : : }
591 : :
592 : : tl::optional<SubstitutionArg>
593 : 96 : SubstitutionRef::get_arg_at (size_t i) const
594 : : {
595 : 96 : auto param_ty = get_substs ().at (i).get_param_ty ();
596 : 96 : SubstitutionArg arg = SubstitutionArg::error ();
597 : 96 : get_used_arguments ().get_argument_for_symbol (param_ty, &arg);
598 : 96 : if (arg.is_error ())
599 : 1 : return tl::nullopt;
600 : 95 : return arg;
601 : : }
602 : :
603 : : const RegionConstraints &
604 : 49279 : SubstitutionRef::get_region_constraints () const
605 : : {
606 : 49279 : return region_constraints;
607 : : }
608 : :
609 : : SubstitutionArgumentMappings
610 : 4576 : SubstitutionRef::get_mappings_from_generic_args (
611 : : HIR::GenericArgs &args, const std::vector<Region> ®ions)
612 : : {
613 : 4576 : std::map<std::string, BaseType *> binding_arguments;
614 : 4576 : if (args.get_binding_args ().size () > 0)
615 : : {
616 : 44 : if (supports_associated_bindings ())
617 : : {
618 : 43 : if (args.get_binding_args ().size () > get_num_associated_bindings ())
619 : : {
620 : 0 : rich_location r (line_table, args.get_locus ());
621 : :
622 : 0 : rust_error_at (r,
623 : : "generic item takes at most %lu type binding "
624 : : "arguments but %lu were supplied",
625 : 0 : (unsigned long) get_num_associated_bindings (),
626 : 0 : (unsigned long) args.get_binding_args ().size ());
627 : 0 : return SubstitutionArgumentMappings::error ();
628 : 0 : }
629 : :
630 : 86 : for (auto &binding : args.get_binding_args ())
631 : : {
632 : 43 : BaseType *resolved
633 : 43 : = Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
634 : 43 : if (resolved == nullptr
635 : 43 : || resolved->get_kind () == TyTy::TypeKind::ERROR)
636 : : {
637 : 0 : rust_error_at (binding.get_locus (),
638 : : "failed to resolve type arguments");
639 : 0 : return SubstitutionArgumentMappings::error ();
640 : : }
641 : :
642 : : // resolve to relevant binding
643 : 43 : auto binding_item = lookup_associated_type (
644 : 43 : binding.get_identifier ().as_string ());
645 : 43 : if (binding_item.is_error ())
646 : : {
647 : 0 : rust_error_at (
648 : : binding.get_locus (), "unknown associated type binding: %s",
649 : 0 : binding.get_identifier ().as_string ().c_str ());
650 : 0 : return SubstitutionArgumentMappings::error ();
651 : : }
652 : :
653 : 43 : binding_arguments[binding.get_identifier ().as_string ()]
654 : 43 : = resolved;
655 : : }
656 : : }
657 : : else
658 : : {
659 : 1 : rich_location r (line_table, args.get_locus ());
660 : 3 : for (auto &binding : args.get_binding_args ())
661 : 2 : r.add_range (binding.get_locus ());
662 : :
663 : 1 : rust_error_at (r, ErrorCode::E0229,
664 : : "associated type bindings are not allowed here");
665 : 1 : return SubstitutionArgumentMappings::error ();
666 : 1 : }
667 : : }
668 : :
669 : : // for inherited arguments
670 : 4575 : size_t offs = used_arguments.size ();
671 : 4575 : if (args.get_type_args ().size () + offs > substitutions.size ())
672 : : {
673 : 2 : rich_location r (line_table, args.get_locus ());
674 : 2 : if (!substitutions.empty ())
675 : 1 : r.add_range (substitutions.front ().get_param_locus ());
676 : :
677 : 2 : rust_error_at (
678 : : r,
679 : : "generic item takes at most %lu type arguments but %lu were supplied",
680 : 2 : (unsigned long) substitutions.size (),
681 : 2 : (unsigned long) args.get_type_args ().size ());
682 : 2 : return SubstitutionArgumentMappings::error ();
683 : 2 : }
684 : :
685 : 4573 : if (args.get_type_args ().size () + offs < min_required_substitutions ())
686 : : {
687 : 3 : rich_location r (line_table, args.get_locus ());
688 : 3 : r.add_range (substitutions.front ().get_param_locus ());
689 : :
690 : 6 : rust_error_at (
691 : : r, ErrorCode::E0107,
692 : : "generic item takes at least %lu type arguments but %lu were supplied",
693 : 3 : (unsigned long) (min_required_substitutions () - offs),
694 : 3 : (unsigned long) args.get_type_args ().size ());
695 : 3 : return SubstitutionArgumentMappings::error ();
696 : 3 : }
697 : :
698 : 4570 : std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
699 : 9558 : for (auto &arg : args.get_type_args ())
700 : : {
701 : 4988 : BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
702 : 4988 : if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
703 : : {
704 : 0 : rust_error_at (args.get_locus (), "failed to resolve type arguments");
705 : 0 : return SubstitutionArgumentMappings::error ();
706 : : }
707 : :
708 : 4988 : SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
709 : 4988 : offs++;
710 : 4988 : mappings.push_back (std::move (subst_arg));
711 : : }
712 : :
713 : : // we must need to fill out defaults
714 : 4570 : size_t left_over
715 : 4570 : = num_required_substitutions () - min_required_substitutions ();
716 : 4570 : if (left_over > 0)
717 : : {
718 : 625 : for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
719 : : {
720 : 243 : SubstitutionParamMapping ¶m = substitutions.at (offs);
721 : 243 : rust_assert (param.param_has_default_ty ());
722 : :
723 : 243 : BaseType *resolved = param.get_default_ty ();
724 : 243 : if (resolved->get_kind () == TypeKind::ERROR)
725 : 0 : return SubstitutionArgumentMappings::error ();
726 : :
727 : : // this resolved default might already contain default parameters
728 : 243 : if (!resolved->is_concrete ())
729 : : {
730 : 229 : SubstitutionArgumentMappings intermediate (
731 : : mappings, binding_arguments,
732 : 229 : {used_arguments.get_regions ().size ()}, args.get_locus ());
733 : 229 : resolved = Resolver::SubstMapperInternal::Resolve (resolved,
734 : : intermediate);
735 : :
736 : 229 : if (resolved->get_kind () == TypeKind::ERROR)
737 : 0 : return SubstitutionArgumentMappings::error ();
738 : 229 : }
739 : :
740 : 243 : SubstitutionArg subst_arg (¶m, resolved);
741 : 243 : mappings.push_back (std::move (subst_arg));
742 : : }
743 : : }
744 : :
745 : 4570 : return {mappings, binding_arguments,
746 : 9140 : RegionParamList::from_subst (used_arguments.get_regions ().size (),
747 : : regions),
748 : 13710 : args.get_locus ()};
749 : 4570 : }
750 : :
751 : : BaseType *
752 : 2648 : SubstitutionRef::infer_substitions (location_t locus)
753 : : {
754 : 2648 : std::vector<SubstitutionArg> args;
755 : 2648 : std::map<std::string, BaseType *> argument_mappings;
756 : 5693 : for (auto &p : get_substs ())
757 : : {
758 : 3045 : if (p.needs_substitution ())
759 : : {
760 : 2989 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
761 : 2989 : auto it = argument_mappings.find (symbol);
762 : 2989 : bool have_mapping = it != argument_mappings.end ();
763 : :
764 : 2989 : if (have_mapping)
765 : : {
766 : 7 : args.push_back (SubstitutionArg (&p, it->second));
767 : : }
768 : : else
769 : : {
770 : 2982 : TyVar infer_var = TyVar::get_implicit_infer_var (locus);
771 : 2982 : args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
772 : 2982 : argument_mappings[symbol] = infer_var.get_tyty ();
773 : : }
774 : 2989 : }
775 : : else
776 : : {
777 : 56 : args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
778 : : }
779 : : }
780 : :
781 : : // FIXME do we need to add inference variables to all the possible bindings?
782 : : // it might just lead to inference variable hell not 100% sure if rustc does
783 : : // this i think the language might needs this to be explicitly set
784 : :
785 : 2648 : SubstitutionArgumentMappings infer_arguments (std::move (args),
786 : : {} /* binding_arguments */,
787 : : used_arguments.get_regions (),
788 : 2648 : locus);
789 : 2648 : return handle_substitions (infer_arguments);
790 : 2648 : }
791 : :
792 : : SubstitutionArgumentMappings
793 : 4439 : SubstitutionRef::adjust_mappings_for_this (
794 : : SubstitutionArgumentMappings &mappings)
795 : : {
796 : 4439 : std::vector<SubstitutionArg> resolved_mappings;
797 : 9892 : for (size_t i = 0; i < substitutions.size (); i++)
798 : : {
799 : 5453 : auto &subst = substitutions.at (i);
800 : :
801 : 5453 : SubstitutionArg arg = SubstitutionArg::error ();
802 : 5453 : if (mappings.size () == substitutions.size ())
803 : : {
804 : 5152 : mappings.get_argument_at (i, &arg);
805 : : }
806 : : else
807 : : {
808 : 301 : if (subst.needs_substitution ())
809 : : {
810 : : // get from passed in mappings
811 : 231 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
812 : : }
813 : : else
814 : : {
815 : : // we should already have this somewhere
816 : 70 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
817 : : &arg);
818 : : }
819 : : }
820 : :
821 : 5453 : bool ok = !arg.is_error ();
822 : 5453 : if (ok)
823 : : {
824 : 5404 : SubstitutionArg adjusted (&subst, arg.get_tyty ());
825 : 5404 : resolved_mappings.push_back (std::move (adjusted));
826 : : }
827 : : }
828 : :
829 : 4439 : if (resolved_mappings.empty ())
830 : 0 : return SubstitutionArgumentMappings::error ();
831 : :
832 : 4439 : return SubstitutionArgumentMappings (resolved_mappings,
833 : 4439 : mappings.get_binding_args (),
834 : : mappings.get_regions (),
835 : : mappings.get_locus (),
836 : 4439 : mappings.get_subst_cb (),
837 : 8878 : mappings.trait_item_mode ());
838 : 4439 : }
839 : :
840 : : bool
841 : 0 : SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
842 : : {
843 : 0 : std::vector<SubstitutionArg> resolved_mappings;
844 : 0 : for (size_t i = 0; i < substitutions.size (); i++)
845 : : {
846 : 0 : auto &subst = substitutions.at (i);
847 : :
848 : 0 : SubstitutionArg arg = SubstitutionArg::error ();
849 : 0 : if (mappings.size () == substitutions.size ())
850 : : {
851 : 0 : mappings.get_argument_at (i, &arg);
852 : : }
853 : : else
854 : : {
855 : 0 : if (subst.needs_substitution ())
856 : : {
857 : : // get from passed in mappings
858 : 0 : mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
859 : : }
860 : : else
861 : : {
862 : : // we should already have this somewhere
863 : 0 : used_arguments.get_argument_for_symbol (subst.get_param_ty (),
864 : : &arg);
865 : : }
866 : : }
867 : :
868 : 0 : bool ok = !arg.is_error ();
869 : 0 : if (ok)
870 : : {
871 : 0 : SubstitutionArg adjusted (&subst, arg.get_tyty ());
872 : 0 : resolved_mappings.push_back (std::move (adjusted));
873 : : }
874 : : }
875 : :
876 : 0 : return !resolved_mappings.empty ();
877 : 0 : }
878 : :
879 : : // this function assumes that the mappings being passed are for the same type as
880 : : // this new substitution reference so ordering matters here
881 : : SubstitutionArgumentMappings
882 : 63 : SubstitutionRef::solve_mappings_from_receiver_for_self (
883 : : SubstitutionArgumentMappings &mappings) const
884 : : {
885 : 63 : std::vector<SubstitutionArg> resolved_mappings;
886 : :
887 : 63 : rust_assert (mappings.size () == get_num_substitutions ());
888 : 126 : for (size_t i = 0; i < get_num_substitutions (); i++)
889 : : {
890 : 63 : const SubstitutionParamMapping ¶m_mapping = substitutions.at (i);
891 : 63 : SubstitutionArg &arg = mappings.get_mappings ().at (i);
892 : :
893 : 63 : if (param_mapping.needs_substitution ())
894 : : {
895 : 63 : SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ());
896 : 63 : resolved_mappings.push_back (std::move (adjusted));
897 : : }
898 : : }
899 : :
900 : 63 : return SubstitutionArgumentMappings (resolved_mappings,
901 : 63 : mappings.get_binding_args (),
902 : : mappings.get_regions (),
903 : 126 : mappings.get_locus ());
904 : 63 : }
905 : :
906 : : void
907 : 1325 : SubstitutionRef::prepare_higher_ranked_bounds ()
908 : : {
909 : 2444 : for (const auto &subst : get_substs ())
910 : : {
911 : 1119 : const TyTy::ParamType *pty = subst.get_param_ty ();
912 : 2529 : for (const auto &bound : pty->get_specified_bounds ())
913 : : {
914 : 1410 : const auto ref = bound.get ();
915 : 1410 : ref->clear_associated_type_projections ();
916 : : }
917 : : }
918 : 1325 : }
919 : :
920 : : bool
921 : 8320 : SubstitutionRef::monomorphize ()
922 : : {
923 : 13071 : for (const auto &subst : get_substs ())
924 : : {
925 : 4751 : const TyTy::ParamType *pty = subst.get_param_ty ();
926 : :
927 : 4751 : if (!pty->can_resolve ())
928 : 64 : continue;
929 : :
930 : 4687 : const TyTy::BaseType *binding = pty->resolve ();
931 : 4687 : if (binding->get_kind () == TyTy::TypeKind::PARAM)
932 : 801 : continue;
933 : :
934 : 8321 : for (const auto &bound : pty->get_specified_bounds ())
935 : : {
936 : 4435 : bool ambigious = false;
937 : 4435 : auto associated
938 : 4435 : = Resolver::lookup_associated_impl_block (bound, binding,
939 : : &ambigious);
940 : 4435 : if (associated == nullptr && ambigious)
941 : : {
942 : : // go for the first one? or error out?
943 : 0 : auto &mappings = *Analysis::Mappings::get ();
944 : 0 : const auto &type_param = subst.get_generic_param ();
945 : 0 : const auto *trait_ref = bound.get ();
946 : :
947 : 0 : rich_location r (line_table, type_param.get_locus ());
948 : 0 : r.add_range (bound.get_locus ());
949 : 0 : r.add_range (mappings.lookup_location (binding->get_ref ()));
950 : :
951 : 0 : rust_error_at (r, "ambiguous type bound for trait %s and type %s",
952 : 0 : trait_ref->get_name ().c_str (),
953 : 0 : binding->get_name ().c_str ());
954 : 0 : return false;
955 : 0 : }
956 : :
957 : : if (associated != nullptr)
958 : : {
959 : 771 : associated->setup_associated_types (binding, bound);
960 : : }
961 : : }
962 : : }
963 : :
964 : : return true;
965 : : }
966 : :
967 : : } // namespace TyTy
968 : : } // namespace Rust
|