]>
Commit | Line | Data |
---|---|---|
a945c346 | 1 | // Copyright (C) 2021-2024 Free Software Foundation, Inc. |
06688fe4 PH |
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-hir-type-bounds.h" | |
20 | #include "rust-hir-trait-resolve.h" | |
104cc285 | 21 | #include "rust-hir-type-check-item.h" |
06688fe4 PH |
22 | |
23 | namespace Rust { | |
24 | namespace Resolver { | |
25 | ||
4b25fc15 PH |
26 | TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver) |
27 | : TypeCheckBase (), receiver (receiver) | |
28 | {} | |
29 | ||
30 | std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> | |
31 | TypeBoundsProbe::Probe (const TyTy::BaseType *receiver) | |
32 | { | |
33 | TypeBoundsProbe probe (receiver); | |
34 | probe.scan (); | |
35 | return probe.trait_references; | |
36 | } | |
37 | ||
38 | bool | |
39 | TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver, | |
40 | TraitReference *ref) | |
41 | { | |
42 | for (auto &bound : receiver->get_specified_bounds ()) | |
43 | { | |
44 | const TraitReference *b = bound.get (); | |
45 | if (b->is_equal (*ref)) | |
46 | return true; | |
47 | } | |
48 | ||
49 | std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds | |
50 | = Probe (receiver); | |
51 | for (auto &bound : bounds) | |
52 | { | |
53 | const TraitReference *b = bound.first; | |
54 | if (b->is_equal (*ref)) | |
55 | return true; | |
56 | } | |
57 | ||
58 | return false; | |
59 | } | |
60 | ||
06688fe4 PH |
61 | void |
62 | TypeBoundsProbe::scan () | |
63 | { | |
64 | std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>> | |
65 | possible_trait_paths; | |
66 | mappings->iterate_impl_blocks ( | |
67 | [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { | |
68 | // we are filtering for trait-impl-blocks | |
69 | if (!impl->has_trait_ref ()) | |
70 | return true; | |
71 | ||
543ba359 PH |
72 | HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid (); |
73 | TyTy::BaseType *impl_type = nullptr; | |
74 | if (!query_type (impl_ty_id, &impl_type)) | |
06688fe4 PH |
75 | return true; |
76 | ||
77 | if (!receiver->can_eq (impl_type, false)) | |
78 | { | |
79 | if (!impl_type->can_eq (receiver, false)) | |
80 | return true; | |
81 | } | |
82 | ||
83 | possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl}); | |
84 | return true; | |
85 | }); | |
86 | ||
87 | for (auto &path : possible_trait_paths) | |
88 | { | |
89 | HIR::TypePath *trait_path = path.first; | |
90 | TraitReference *trait_ref = TraitResolver::Resolve (*trait_path); | |
91 | ||
92 | if (!trait_ref->is_error ()) | |
93 | trait_references.push_back ({trait_ref, path.second}); | |
94 | } | |
4b25fc15 PH |
95 | |
96 | // marker traits... | |
97 | assemble_sized_builtin (); | |
98 | } | |
99 | ||
100 | void | |
101 | TypeBoundsProbe::assemble_sized_builtin () | |
102 | { | |
103 | const TyTy::BaseType *raw = receiver->destructure (); | |
104 | ||
105 | // does this thing actually implement sized? | |
106 | switch (raw->get_kind ()) | |
107 | { | |
108 | case TyTy::ADT: | |
109 | case TyTy::STR: | |
110 | case TyTy::REF: | |
111 | case TyTy::POINTER: | |
112 | case TyTy::PARAM: | |
113 | case TyTy::ARRAY: | |
114 | case TyTy::SLICE: | |
115 | case TyTy::FNDEF: | |
116 | case TyTy::FNPTR: | |
117 | case TyTy::TUPLE: | |
118 | case TyTy::BOOL: | |
119 | case TyTy::CHAR: | |
120 | case TyTy::INT: | |
121 | case TyTy::UINT: | |
122 | case TyTy::FLOAT: | |
123 | case TyTy::USIZE: | |
124 | case TyTy::ISIZE: | |
125 | assemble_builtin_candidate (Analysis::RustLangItem::SIZED); | |
126 | break; | |
127 | ||
128 | // not-sure about this.... FIXME | |
129 | case TyTy::INFER: | |
130 | case TyTy::NEVER: | |
131 | case TyTy::PLACEHOLDER: | |
132 | case TyTy::PROJECTION: | |
133 | case TyTy::DYNAMIC: | |
134 | case TyTy::CLOSURE: | |
135 | case TyTy::ERROR: | |
136 | break; | |
137 | } | |
138 | } | |
139 | ||
140 | void | |
141 | TypeBoundsProbe::assemble_builtin_candidate ( | |
142 | Analysis::RustLangItem::ItemType lang_item) | |
143 | { | |
144 | DefId id; | |
145 | bool found_lang_item = mappings->lookup_lang_item (lang_item, &id); | |
146 | if (!found_lang_item) | |
147 | return; | |
148 | ||
149 | HIR::Item *item = mappings->lookup_defid (id); | |
150 | if (item == nullptr) | |
151 | return; | |
152 | ||
153 | rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait); | |
154 | HIR::Trait *trait = static_cast<HIR::Trait *> (item); | |
155 | const TyTy::BaseType *raw = receiver->destructure (); | |
156 | ||
157 | // assemble the reference | |
158 | TraitReference *trait_ref = TraitResolver::Resolve (*trait); | |
159 | trait_references.push_back ({trait_ref, mappings->lookup_builtin_marker ()}); | |
160 | ||
161 | rust_debug ("Added builtin lang_item: %s for %s", | |
162 | Analysis::RustLangItem::ToString (lang_item).c_str (), | |
163 | raw->get_name ().c_str ()); | |
06688fe4 PH |
164 | } |
165 | ||
166 | TraitReference * | |
167 | TypeCheckBase::resolve_trait_path (HIR::TypePath &path) | |
168 | { | |
169 | return TraitResolver::Resolve (path); | |
170 | } | |
171 | ||
172 | TyTy::TypeBoundPredicate | |
173 | TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path) | |
174 | { | |
104cc285 PH |
175 | TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error (); |
176 | bool already_resolved | |
177 | = context->lookup_predicate (type_path.get_mappings ().get_hirid (), | |
178 | &lookup); | |
179 | if (already_resolved) | |
180 | return lookup; | |
181 | ||
06688fe4 PH |
182 | TraitReference *trait = resolve_trait_path (type_path); |
183 | if (trait->is_error ()) | |
184 | return TyTy::TypeBoundPredicate::error (); | |
185 | ||
186 | TyTy::TypeBoundPredicate predicate (*trait, type_path.get_locus ()); | |
187 | HIR::GenericArgs args | |
188 | = HIR::GenericArgs::create_empty (type_path.get_locus ()); | |
189 | ||
190 | auto &final_seg = type_path.get_final_segment (); | |
51d180fc | 191 | switch (final_seg->get_type ()) |
06688fe4 | 192 | { |
51d180fc PH |
193 | case HIR::TypePathSegment::SegmentType::GENERIC: { |
194 | auto final_generic_seg | |
195 | = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ()); | |
196 | if (final_generic_seg->has_generic_args ()) | |
197 | { | |
198 | args = final_generic_seg->get_generic_args (); | |
199 | } | |
200 | } | |
201 | break; | |
202 | ||
203 | case HIR::TypePathSegment::SegmentType::FUNCTION: { | |
204 | auto final_function_seg | |
205 | = static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ()); | |
206 | auto &fn = final_function_seg->get_function_path (); | |
207 | ||
4b25fc15 PH |
208 | // we need to make implicit generic args which must be an implicit |
209 | // Tuple | |
51d180fc PH |
210 | auto crate_num = mappings->get_current_crate (); |
211 | HirId implicit_args_id = mappings->get_next_hir_id (); | |
212 | Analysis::NodeMapping mapping (crate_num, | |
213 | final_seg->get_mappings ().get_nodeid (), | |
214 | implicit_args_id, UNKNOWN_LOCAL_DEFID); | |
215 | ||
216 | std::vector<std::unique_ptr<HIR::Type>> params_copy; | |
217 | for (auto &p : fn.get_params ()) | |
218 | { | |
219 | params_copy.push_back (p->clone_type ()); | |
220 | } | |
221 | ||
222 | HIR::TupleType *implicit_tuple | |
223 | = new HIR::TupleType (mapping, std::move (params_copy), | |
224 | final_seg->get_locus ()); | |
225 | ||
226 | std::vector<std::unique_ptr<HIR::Type>> inputs; | |
227 | inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple)); | |
228 | ||
229 | args = HIR::GenericArgs ({} /* lifetimes */, | |
230 | std::move (inputs) /* type_args*/, | |
231 | {} /* binding_args*/, {} /* const_args */, | |
232 | final_seg->get_locus ()); | |
233 | ||
234 | // resolve the fn_once_output type | |
235 | TyTy::BaseType *fn_once_output_ty | |
236 | = fn.has_return_type () | |
237 | ? TypeCheckType::Resolve (fn.get_return_type ().get ()) | |
238 | : TyTy::TupleType::get_unit_type ( | |
239 | final_seg->get_mappings ().get_hirid ()); | |
240 | context->insert_implicit_type (final_seg->get_mappings ().get_hirid (), | |
241 | fn_once_output_ty); | |
242 | ||
243 | // setup the associated type.. ?? | |
244 | // fn_once_output_ty->debug (); | |
245 | } | |
246 | break; | |
247 | ||
248 | default: | |
249 | /* nothing to do */ | |
250 | break; | |
06688fe4 PH |
251 | } |
252 | ||
7eab9d18 PH |
253 | // we try to apply generic arguments when they are non empty and or when the |
254 | // predicate requires them so that we get the relevant Foo expects x number | |
255 | // arguments but got zero see test case rust/compile/traits12.rs | |
256 | if (!args.is_empty () || predicate.requires_generic_args ()) | |
06688fe4 PH |
257 | { |
258 | // this is applying generic arguments to a trait reference | |
259 | predicate.apply_generic_arguments (&args); | |
260 | } | |
261 | ||
104cc285 PH |
262 | context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (), |
263 | predicate); | |
06688fe4 PH |
264 | return predicate; |
265 | } | |
266 | ||
267 | } // namespace Resolver | |
268 | ||
269 | namespace TyTy { | |
270 | ||
271 | TypeBoundPredicate::TypeBoundPredicate ( | |
272 | const Resolver::TraitReference &trait_reference, Location locus) | |
273 | : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()), | |
274 | reference (trait_reference.get_mappings ().get_defid ()), locus (locus), | |
275 | error_flag (false) | |
276 | { | |
277 | substitutions.clear (); | |
278 | for (const auto &p : trait_reference.get_trait_substs ()) | |
279 | substitutions.push_back (p.clone ()); | |
280 | ||
281 | // we setup a dummy implict self argument | |
282 | SubstitutionArg placeholder_self (&get_substs ().front (), nullptr); | |
283 | used_arguments.get_mappings ().push_back (placeholder_self); | |
284 | } | |
285 | ||
286 | TypeBoundPredicate::TypeBoundPredicate ( | |
287 | DefId reference, std::vector<SubstitutionParamMapping> subst, Location locus) | |
288 | : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()), | |
289 | reference (reference), locus (locus), error_flag (false) | |
290 | { | |
291 | substitutions.clear (); | |
292 | for (const auto &p : subst) | |
293 | substitutions.push_back (p.clone ()); | |
294 | ||
295 | // we setup a dummy implict self argument | |
296 | SubstitutionArg placeholder_self (&get_substs ().front (), nullptr); | |
297 | used_arguments.get_mappings ().push_back (placeholder_self); | |
298 | } | |
299 | ||
300 | TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other) | |
301 | : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()), | |
302 | reference (other.reference), locus (other.locus), | |
303 | error_flag (other.error_flag) | |
304 | { | |
305 | substitutions.clear (); | |
306 | for (const auto &p : other.get_substs ()) | |
307 | substitutions.push_back (p.clone ()); | |
308 | ||
309 | std::vector<SubstitutionArg> mappings; | |
310 | for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++) | |
311 | { | |
312 | const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i); | |
313 | SubstitutionArg arg (oa); | |
314 | mappings.push_back (std::move (arg)); | |
315 | } | |
316 | ||
317 | // we need to remap the argument mappings based on this copied constructor | |
318 | std::vector<SubstitutionArg> copied_arg_mappings; | |
319 | size_t i = 0; | |
320 | for (const auto &m : other.used_arguments.get_mappings ()) | |
321 | { | |
322 | TyTy::BaseType *argument | |
323 | = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone (); | |
324 | SubstitutionArg c (&substitutions.at (i++), argument); | |
325 | copied_arg_mappings.push_back (std::move (c)); | |
326 | } | |
327 | ||
328 | used_arguments | |
7eab9d18 | 329 | = SubstitutionArgumentMappings (copied_arg_mappings, {}, |
06688fe4 PH |
330 | other.used_arguments.get_locus ()); |
331 | } | |
332 | ||
333 | TypeBoundPredicate & | |
334 | TypeBoundPredicate::operator= (const TypeBoundPredicate &other) | |
335 | { | |
336 | reference = other.reference; | |
337 | locus = other.locus; | |
338 | error_flag = other.error_flag; | |
339 | used_arguments = SubstitutionArgumentMappings::error (); | |
340 | ||
341 | substitutions.clear (); | |
342 | for (const auto &p : other.get_substs ()) | |
343 | substitutions.push_back (p.clone ()); | |
344 | ||
345 | std::vector<SubstitutionArg> mappings; | |
346 | for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++) | |
347 | { | |
348 | const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i); | |
349 | SubstitutionArg arg (oa); | |
350 | mappings.push_back (std::move (arg)); | |
351 | } | |
352 | ||
353 | // we need to remap the argument mappings based on this copied constructor | |
354 | std::vector<SubstitutionArg> copied_arg_mappings; | |
355 | size_t i = 0; | |
356 | for (const auto &m : other.used_arguments.get_mappings ()) | |
357 | { | |
358 | TyTy::BaseType *argument | |
359 | = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone (); | |
360 | SubstitutionArg c (&substitutions.at (i++), argument); | |
361 | copied_arg_mappings.push_back (std::move (c)); | |
362 | } | |
363 | ||
364 | used_arguments | |
7eab9d18 | 365 | = SubstitutionArgumentMappings (copied_arg_mappings, {}, |
06688fe4 PH |
366 | other.used_arguments.get_locus ()); |
367 | ||
368 | return *this; | |
369 | } | |
370 | ||
371 | TypeBoundPredicate | |
372 | TypeBoundPredicate::error () | |
373 | { | |
374 | auto p = TypeBoundPredicate (UNKNOWN_DEFID, {}, Location ()); | |
375 | p.error_flag = true; | |
376 | return p; | |
377 | } | |
378 | ||
379 | std::string | |
380 | TypeBoundPredicate::as_string () const | |
381 | { | |
382 | return get ()->as_string () + subst_as_string (); | |
383 | } | |
384 | ||
385 | std::string | |
386 | TypeBoundPredicate::as_name () const | |
387 | { | |
388 | return get ()->get_name () + subst_as_string (); | |
389 | } | |
390 | ||
391 | const Resolver::TraitReference * | |
392 | TypeBoundPredicate::get () const | |
393 | { | |
394 | auto context = Resolver::TypeCheckContext::get (); | |
395 | ||
396 | Resolver::TraitReference *ref = nullptr; | |
397 | bool ok = context->lookup_trait_reference (reference, &ref); | |
398 | rust_assert (ok); | |
399 | ||
400 | return ref; | |
401 | } | |
402 | ||
403 | std::string | |
404 | TypeBoundPredicate::get_name () const | |
405 | { | |
406 | return get ()->get_name (); | |
407 | } | |
408 | ||
409 | bool | |
410 | TypeBoundPredicate::is_object_safe (bool emit_error, Location locus) const | |
411 | { | |
412 | const Resolver::TraitReference *trait = get (); | |
413 | rust_assert (trait != nullptr); | |
414 | return trait->is_object_safe (emit_error, locus); | |
415 | } | |
416 | ||
417 | void | |
418 | TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args) | |
419 | { | |
420 | // we need to get the substitutions argument mappings but also remember that | |
421 | // we have an implicit Self argument which we must be careful to respect | |
422 | rust_assert (!used_arguments.is_empty ()); | |
423 | rust_assert (!substitutions.empty ()); | |
424 | ||
425 | // now actually perform a substitution | |
426 | used_arguments = get_mappings_from_generic_args (*generic_args); | |
427 | ||
428 | error_flag |= used_arguments.is_error (); | |
429 | auto &subst_mappings = used_arguments; | |
430 | for (auto &sub : get_substs ()) | |
431 | { | |
432 | SubstitutionArg arg = SubstitutionArg::error (); | |
433 | bool ok | |
434 | = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg); | |
435 | if (ok && arg.get_tyty () != nullptr) | |
436 | sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ()); | |
437 | } | |
7eab9d18 PH |
438 | |
439 | // associated argument mappings | |
440 | for (auto &it : subst_mappings.get_binding_args ()) | |
441 | { | |
442 | std::string identifier = it.first; | |
443 | TyTy::BaseType *type = it.second; | |
444 | ||
445 | TypeBoundPredicateItem item = lookup_associated_item (identifier); | |
446 | rust_assert (!item.is_error ()); | |
447 | ||
448 | const auto item_ref = item.get_raw_item (); | |
449 | item_ref->associated_type_set (type); | |
450 | } | |
06688fe4 PH |
451 | } |
452 | ||
453 | bool | |
454 | TypeBoundPredicate::contains_item (const std::string &search) const | |
455 | { | |
456 | auto trait_ref = get (); | |
457 | const Resolver::TraitItemReference *trait_item_ref = nullptr; | |
458 | return trait_ref->lookup_trait_item (search, &trait_item_ref); | |
459 | } | |
460 | ||
461 | TypeBoundPredicateItem | |
462 | TypeBoundPredicate::lookup_associated_item (const std::string &search) const | |
463 | { | |
464 | auto trait_ref = get (); | |
465 | const Resolver::TraitItemReference *trait_item_ref = nullptr; | |
466 | if (!trait_ref->lookup_trait_item (search, &trait_item_ref)) | |
467 | return TypeBoundPredicateItem::error (); | |
468 | ||
469 | return TypeBoundPredicateItem (this, trait_item_ref); | |
470 | } | |
471 | ||
c1b1bbbc PH |
472 | TypeBoundPredicateItem::TypeBoundPredicateItem ( |
473 | const TypeBoundPredicate *parent, | |
474 | const Resolver::TraitItemReference *trait_item_ref) | |
475 | : parent (parent), trait_item_ref (trait_item_ref) | |
476 | {} | |
477 | ||
478 | TypeBoundPredicateItem | |
479 | TypeBoundPredicateItem::error () | |
480 | { | |
481 | return TypeBoundPredicateItem (nullptr, nullptr); | |
482 | } | |
483 | ||
484 | bool | |
485 | TypeBoundPredicateItem::is_error () const | |
486 | { | |
487 | return parent == nullptr || trait_item_ref == nullptr; | |
488 | } | |
489 | ||
490 | const TypeBoundPredicate * | |
491 | TypeBoundPredicateItem::get_parent () const | |
492 | { | |
493 | return parent; | |
494 | } | |
495 | ||
06688fe4 PH |
496 | TypeBoundPredicateItem |
497 | TypeBoundPredicate::lookup_associated_item ( | |
498 | const Resolver::TraitItemReference *ref) const | |
499 | { | |
500 | return lookup_associated_item (ref->get_identifier ()); | |
501 | } | |
502 | ||
503 | BaseType * | |
504 | TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) | |
505 | { | |
506 | TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty (); | |
507 | if (parent->get_substitution_arguments ().is_empty ()) | |
508 | return trait_item_tyty; | |
509 | ||
510 | const Resolver::TraitItemReference *tref = get_raw_item (); | |
511 | bool is_associated_type = tref->get_trait_item_type (); | |
512 | if (is_associated_type) | |
513 | return trait_item_tyty; | |
514 | ||
515 | // set up the self mapping | |
516 | SubstitutionArgumentMappings gargs = parent->get_substitution_arguments (); | |
517 | rust_assert (!gargs.is_empty ()); | |
518 | ||
519 | // setup the adjusted mappings | |
520 | std::vector<SubstitutionArg> adjusted_mappings; | |
521 | for (size_t i = 0; i < gargs.get_mappings ().size (); i++) | |
522 | { | |
523 | auto &mapping = gargs.get_mappings ().at (i); | |
524 | ||
525 | bool is_implicit_self = i == 0; | |
526 | TyTy::BaseType *argument | |
527 | = is_implicit_self ? receiver->clone () : mapping.get_tyty (); | |
528 | ||
529 | SubstitutionArg arg (mapping.get_param_mapping (), argument); | |
530 | adjusted_mappings.push_back (std::move (arg)); | |
531 | } | |
532 | ||
7eab9d18 PH |
533 | SubstitutionArgumentMappings adjusted (adjusted_mappings, {}, |
534 | gargs.get_locus (), | |
06688fe4 PH |
535 | gargs.get_subst_cb (), |
536 | true /* trait-mode-flag */); | |
537 | return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted); | |
538 | } | |
539 | bool | |
540 | TypeBoundPredicate::is_error () const | |
541 | { | |
542 | auto context = Resolver::TypeCheckContext::get (); | |
543 | ||
544 | Resolver::TraitReference *ref = nullptr; | |
545 | bool ok = context->lookup_trait_reference (reference, &ref); | |
546 | ||
547 | return !ok || error_flag; | |
548 | } | |
549 | ||
550 | BaseType * | |
551 | TypeBoundPredicate::handle_substitions ( | |
dcb2e571 | 552 | SubstitutionArgumentMappings &subst_mappings) |
06688fe4 PH |
553 | { |
554 | for (auto &sub : get_substs ()) | |
555 | { | |
556 | if (sub.get_param_ty () == nullptr) | |
557 | continue; | |
558 | ||
559 | ParamType *p = sub.get_param_ty (); | |
560 | BaseType *r = p->resolve (); | |
561 | BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings); | |
562 | ||
563 | p->set_ty_ref (s->get_ty_ref ()); | |
564 | } | |
565 | ||
7eab9d18 PH |
566 | // associated argument mappings |
567 | for (auto &it : subst_mappings.get_binding_args ()) | |
568 | { | |
569 | std::string identifier = it.first; | |
570 | TyTy::BaseType *type = it.second; | |
571 | ||
572 | TypeBoundPredicateItem item = lookup_associated_item (identifier); | |
573 | rust_assert (!item.is_error ()); | |
574 | ||
575 | const auto item_ref = item.get_raw_item (); | |
576 | item_ref->associated_type_set (type); | |
577 | } | |
578 | ||
06688fe4 PH |
579 | // FIXME more error handling at some point |
580 | // used_arguments = subst_mappings; | |
581 | // error_flag |= used_arguments.is_error (); | |
582 | ||
583 | return nullptr; | |
584 | } | |
585 | ||
586 | bool | |
587 | TypeBoundPredicate::requires_generic_args () const | |
588 | { | |
589 | if (is_error ()) | |
590 | return false; | |
591 | ||
592 | return substitutions.size () > 1; | |
593 | } | |
594 | ||
e641158a PH |
595 | bool |
596 | TypeBoundPredicate::contains_associated_types () const | |
597 | { | |
7eab9d18 PH |
598 | return get_num_associated_bindings () > 0; |
599 | } | |
600 | ||
601 | size_t | |
602 | TypeBoundPredicate::get_num_associated_bindings () const | |
603 | { | |
604 | size_t count = 0; | |
e641158a PH |
605 | auto trait_ref = get (); |
606 | for (const auto &trait_item : trait_ref->get_trait_items ()) | |
607 | { | |
608 | bool is_associated_type | |
609 | = trait_item.get_trait_item_type () | |
610 | == Resolver::TraitItemReference::TraitItemType::TYPE; | |
611 | if (is_associated_type) | |
7eab9d18 PH |
612 | count++; |
613 | } | |
614 | return count; | |
615 | } | |
616 | ||
617 | TypeBoundPredicateItem | |
618 | TypeBoundPredicate::lookup_associated_type (const std::string &search) | |
619 | { | |
620 | TypeBoundPredicateItem item = lookup_associated_item (search); | |
621 | ||
4b25fc15 PH |
622 | // only need to check that it is infact an associated type because other |
623 | // wise if it was not found it will just be an error node anyway | |
7eab9d18 PH |
624 | if (!item.is_error ()) |
625 | { | |
626 | const auto raw = item.get_raw_item (); | |
627 | if (raw->get_trait_item_type () | |
628 | != Resolver::TraitItemReference::TraitItemType::TYPE) | |
629 | return TypeBoundPredicateItem::error (); | |
630 | } | |
631 | return item; | |
632 | } | |
633 | ||
634 | std::vector<TypeBoundPredicateItem> | |
635 | TypeBoundPredicate::get_associated_type_items () | |
636 | { | |
637 | std::vector<TypeBoundPredicateItem> items; | |
638 | auto trait_ref = get (); | |
639 | for (const auto &trait_item : trait_ref->get_trait_items ()) | |
640 | { | |
641 | bool is_associated_type | |
642 | = trait_item.get_trait_item_type () | |
643 | == Resolver::TraitItemReference::TraitItemType::TYPE; | |
644 | if (is_associated_type) | |
645 | { | |
646 | TypeBoundPredicateItem item (this, &trait_item); | |
647 | items.push_back (std::move (item)); | |
648 | } | |
e641158a | 649 | } |
7eab9d18 | 650 | return items; |
e641158a PH |
651 | } |
652 | ||
06688fe4 PH |
653 | // trait item reference |
654 | ||
655 | const Resolver::TraitItemReference * | |
656 | TypeBoundPredicateItem::get_raw_item () const | |
657 | { | |
658 | return trait_item_ref; | |
659 | } | |
660 | ||
661 | bool | |
662 | TypeBoundPredicateItem::needs_implementation () const | |
663 | { | |
664 | return !get_raw_item ()->is_optional (); | |
665 | } | |
666 | ||
667 | Location | |
668 | TypeBoundPredicateItem::get_locus () const | |
669 | { | |
670 | return get_raw_item ()->get_locus (); | |
671 | } | |
672 | ||
673 | // TypeBoundsMappings | |
674 | ||
675 | TypeBoundsMappings::TypeBoundsMappings ( | |
676 | std::vector<TypeBoundPredicate> specified_bounds) | |
677 | : specified_bounds (specified_bounds) | |
678 | {} | |
679 | ||
680 | std::vector<TypeBoundPredicate> & | |
681 | TypeBoundsMappings::get_specified_bounds () | |
682 | { | |
683 | return specified_bounds; | |
684 | } | |
685 | ||
686 | const std::vector<TypeBoundPredicate> & | |
687 | TypeBoundsMappings::get_specified_bounds () const | |
688 | { | |
689 | return specified_bounds; | |
690 | } | |
691 | ||
692 | size_t | |
693 | TypeBoundsMappings::num_specified_bounds () const | |
694 | { | |
695 | return specified_bounds.size (); | |
696 | } | |
697 | ||
698 | std::string | |
699 | TypeBoundsMappings::raw_bounds_as_string () const | |
700 | { | |
701 | std::string buf; | |
702 | for (size_t i = 0; i < specified_bounds.size (); i++) | |
703 | { | |
704 | const TypeBoundPredicate &b = specified_bounds.at (i); | |
705 | bool has_next = (i + 1) < specified_bounds.size (); | |
706 | buf += b.as_string () + (has_next ? " + " : ""); | |
707 | } | |
708 | return buf; | |
709 | } | |
710 | ||
711 | std::string | |
712 | TypeBoundsMappings::bounds_as_string () const | |
713 | { | |
714 | return "bounds:[" + raw_bounds_as_string () + "]"; | |
715 | } | |
716 | ||
717 | std::string | |
718 | TypeBoundsMappings::raw_bounds_as_name () const | |
719 | { | |
720 | std::string buf; | |
721 | for (size_t i = 0; i < specified_bounds.size (); i++) | |
722 | { | |
723 | const TypeBoundPredicate &b = specified_bounds.at (i); | |
724 | bool has_next = (i + 1) < specified_bounds.size (); | |
725 | buf += b.as_name () + (has_next ? " + " : ""); | |
726 | } | |
727 | ||
728 | return buf; | |
729 | } | |
730 | ||
731 | void | |
732 | TypeBoundsMappings::add_bound (TypeBoundPredicate predicate) | |
733 | { | |
104cc285 PH |
734 | for (auto &bound : specified_bounds) |
735 | { | |
736 | bool same_trait_ref_p = bound.get_id () == predicate.get_id (); | |
737 | if (same_trait_ref_p) | |
738 | return; | |
739 | } | |
740 | ||
06688fe4 PH |
741 | specified_bounds.push_back (predicate); |
742 | } | |
743 | ||
744 | } // namespace TyTy | |
745 | } // namespace Rust |