Branch data Line data Source code
1 : : // Copyright (C) 2021-2025 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-hir-type-bounds.h"
20 : : #include "rust-hir-trait-resolve.h"
21 : : #include "rust-substitution-mapper.h"
22 : : #include "rust-type-util.h"
23 : :
24 : : namespace Rust {
25 : : namespace Resolver {
26 : :
27 : 12390 : TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver)
28 : 12390 : : TypeCheckBase (), receiver (receiver)
29 : 12390 : {}
30 : :
31 : : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
32 : 12390 : TypeBoundsProbe::Probe (const TyTy::BaseType *receiver)
33 : : {
34 : 12390 : TypeBoundsProbe probe (receiver);
35 : 12390 : probe.scan ();
36 : 12390 : return probe.trait_references;
37 : 12390 : }
38 : :
39 : : bool
40 : 222 : TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
41 : : TraitReference *ref)
42 : : {
43 : 236 : for (auto &bound : receiver->get_specified_bounds ())
44 : : {
45 : 49 : const TraitReference *b = bound.get ();
46 : 49 : if (b->is_equal (*ref))
47 : 222 : return true;
48 : : }
49 : :
50 : 187 : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
51 : 187 : = Probe (receiver);
52 : 199 : for (auto &bound : bounds)
53 : : {
54 : 199 : const TraitReference *b = bound.first;
55 : 199 : if (b->is_equal (*ref))
56 : 187 : return true;
57 : : }
58 : :
59 : : return false;
60 : 187 : }
61 : :
62 : : void
63 : 12390 : TypeBoundsProbe::scan ()
64 : : {
65 : 12390 : std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
66 : 12390 : possible_trait_paths;
67 : 12390 : mappings->iterate_impl_blocks (
68 : 12390 : [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
69 : : // we are filtering for trait-impl-blocks
70 : 181161 : if (!impl->has_trait_ref ())
71 : : return true;
72 : :
73 : 155340 : HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
74 : 155340 : TyTy::BaseType *impl_type = nullptr;
75 : 155340 : if (!query_type (impl_ty_id, &impl_type))
76 : : return true;
77 : :
78 : 154380 : if (!receiver->can_eq (impl_type, false))
79 : : {
80 : 135809 : if (!impl_type->can_eq (receiver, false))
81 : : return true;
82 : : }
83 : :
84 : 25945 : possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
85 : 25945 : return true;
86 : : });
87 : :
88 : 38335 : for (auto &path : possible_trait_paths)
89 : : {
90 : 25945 : HIR::TypePath *trait_path = path.first;
91 : 25945 : TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
92 : :
93 : 25945 : if (!trait_ref->is_error ())
94 : 25945 : trait_references.push_back ({trait_ref, path.second});
95 : : }
96 : :
97 : : // marker traits...
98 : 12390 : assemble_sized_builtin ();
99 : 12390 : }
100 : :
101 : : void
102 : 12390 : TypeBoundsProbe::assemble_sized_builtin ()
103 : : {
104 : 12390 : const TyTy::BaseType *raw = receiver->destructure ();
105 : :
106 : : // https://runrust.miraheze.org/wiki/Dynamically_Sized_Type
107 : : // everything is sized except for:
108 : : //
109 : : // 1. dyn traits
110 : : // 2. slices
111 : : // 3. str
112 : : // 4. ADT's which contain any of the above
113 : : // t. tuples which contain any of the above
114 : 12390 : switch (raw->get_kind ())
115 : : {
116 : 8863 : case TyTy::ARRAY:
117 : 8863 : case TyTy::REF:
118 : 8863 : case TyTy::POINTER:
119 : 8863 : case TyTy::PARAM:
120 : 8863 : case TyTy::FNDEF:
121 : 8863 : case TyTy::FNPTR:
122 : 8863 : case TyTy::BOOL:
123 : 8863 : case TyTy::CHAR:
124 : 8863 : case TyTy::INT:
125 : 8863 : case TyTy::UINT:
126 : 8863 : case TyTy::FLOAT:
127 : 8863 : case TyTy::USIZE:
128 : 8863 : case TyTy::ISIZE:
129 : 8863 : case TyTy::CLOSURE:
130 : 8863 : case TyTy::INFER:
131 : 8863 : case TyTy::NEVER:
132 : 8863 : case TyTy::PLACEHOLDER:
133 : 8863 : case TyTy::PROJECTION:
134 : 8863 : assemble_builtin_candidate (LangItem::Kind::SIZED);
135 : 8863 : break;
136 : :
137 : : // FIXME str and slice need to be moved and test cases updated
138 : 3448 : case TyTy::SLICE:
139 : 3448 : case TyTy::STR:
140 : 3448 : case TyTy::ADT:
141 : 3448 : case TyTy::TUPLE:
142 : : // FIXME add extra checks
143 : 3448 : assemble_builtin_candidate (LangItem::Kind::SIZED);
144 : 3448 : break;
145 : :
146 : : case TyTy::DYNAMIC:
147 : : case TyTy::ERROR:
148 : : break;
149 : : }
150 : 12390 : }
151 : :
152 : : void
153 : 12311 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
154 : : {
155 : 12311 : DefId id;
156 : 12311 : bool found_lang_item = mappings->lookup_lang_item (lang_item, &id);
157 : 12311 : if (!found_lang_item)
158 : 0 : return;
159 : :
160 : 12311 : HIR::Item *item = mappings->lookup_defid (id);
161 : 12311 : if (item == nullptr)
162 : : return;
163 : :
164 : 12311 : rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
165 : 12311 : HIR::Trait *trait = static_cast<HIR::Trait *> (item);
166 : 12311 : const TyTy::BaseType *raw = receiver->destructure ();
167 : :
168 : : // assemble the reference
169 : 12311 : TraitReference *trait_ref = TraitResolver::Resolve (*trait);
170 : 12311 : trait_references.push_back ({trait_ref, mappings->lookup_builtin_marker ()});
171 : :
172 : 12311 : rust_debug ("Added builtin lang_item: %s for %s",
173 : : LangItem::ToString (lang_item).c_str (),
174 : : raw->get_name ().c_str ());
175 : : }
176 : :
177 : : TraitReference *
178 : 3123 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
179 : : {
180 : 3123 : return TraitResolver::Resolve (path);
181 : : }
182 : :
183 : : TyTy::TypeBoundPredicate
184 : 12035 : TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path,
185 : : HIR::Type *associated_self,
186 : : BoundPolarity polarity)
187 : : {
188 : 12035 : TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
189 : 12035 : bool already_resolved
190 : 12035 : = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
191 : : &lookup);
192 : 12035 : if (already_resolved)
193 : 8912 : return lookup;
194 : :
195 : 3123 : TraitReference *trait = resolve_trait_path (type_path);
196 : 3123 : if (trait->is_error ())
197 : 8 : return TyTy::TypeBoundPredicate::error ();
198 : :
199 : 3115 : TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
200 : 3115 : HIR::GenericArgs args
201 : 3115 : = HIR::GenericArgs::create_empty (type_path.get_locus ());
202 : :
203 : 3115 : auto &final_seg = type_path.get_final_segment ();
204 : 3115 : switch (final_seg->get_type ())
205 : : {
206 : 426 : case HIR::TypePathSegment::SegmentType::GENERIC: {
207 : 426 : auto final_generic_seg
208 : 426 : = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ());
209 : 426 : if (final_generic_seg->has_generic_args ())
210 : : {
211 : 426 : args = final_generic_seg->get_generic_args ();
212 : : }
213 : : }
214 : : break;
215 : :
216 : 17 : case HIR::TypePathSegment::SegmentType::FUNCTION: {
217 : 17 : auto final_function_seg
218 : 17 : = static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ());
219 : 17 : auto &fn = final_function_seg->get_function_path ();
220 : :
221 : : // we need to make implicit generic args which must be an implicit
222 : : // Tuple
223 : 17 : auto crate_num = mappings->get_current_crate ();
224 : 17 : HirId implicit_args_id = mappings->get_next_hir_id ();
225 : 17 : Analysis::NodeMapping mapping (crate_num,
226 : 17 : final_seg->get_mappings ().get_nodeid (),
227 : 17 : implicit_args_id, UNKNOWN_LOCAL_DEFID);
228 : :
229 : 17 : std::vector<std::unique_ptr<HIR::Type>> params_copy;
230 : 34 : for (auto &p : fn.get_params ())
231 : : {
232 : 17 : params_copy.push_back (p->clone_type ());
233 : : }
234 : :
235 : 17 : HIR::TupleType *implicit_tuple
236 : : = new HIR::TupleType (mapping, std::move (params_copy),
237 : 17 : final_seg->get_locus ());
238 : :
239 : 17 : std::vector<std::unique_ptr<HIR::Type>> inputs;
240 : 17 : inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
241 : :
242 : : // resolve the fn_once_output type which assumes there must be an output
243 : : // set
244 : 17 : rust_assert (fn.has_return_type ());
245 : 17 : TypeCheckType::Resolve (fn.get_return_type ().get ());
246 : :
247 : 17 : HIR::TraitItem *trait_item = mappings->lookup_trait_item_lang_item (
248 : : LangItem::Kind::FN_ONCE_OUTPUT, final_seg->get_locus ());
249 : :
250 : 17 : std::vector<HIR::GenericArgsBinding> bindings;
251 : 17 : location_t output_locus = fn.get_return_type ()->get_locus ();
252 : 34 : HIR::GenericArgsBinding binding (Identifier (
253 : 17 : trait_item->trait_identifier ()),
254 : 34 : fn.get_return_type ()->clone_type (),
255 : 17 : output_locus);
256 : 17 : bindings.push_back (std::move (binding));
257 : :
258 : 34 : args = HIR::GenericArgs ({} /* lifetimes */,
259 : : std::move (inputs) /* type_args*/,
260 : : std::move (bindings) /* binding_args*/,
261 : 34 : {} /* const_args */, final_seg->get_locus ());
262 : 17 : }
263 : 17 : break;
264 : :
265 : : default:
266 : : /* nothing to do */
267 : : break;
268 : : }
269 : :
270 : 3115 : if (associated_self != nullptr)
271 : : {
272 : 2862 : std::vector<std::unique_ptr<HIR::Type>> type_args;
273 : 2862 : type_args.push_back (
274 : 2862 : std::unique_ptr<HIR::Type> (associated_self->clone_type ()));
275 : 3306 : for (auto &arg : args.get_type_args ())
276 : : {
277 : 444 : type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
278 : : }
279 : :
280 : 8586 : args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
281 : 2862 : args.get_binding_args (), args.get_const_args (),
282 : 5724 : args.get_locus ());
283 : 2862 : }
284 : :
285 : : // we try to apply generic arguments when they are non empty and or when the
286 : : // predicate requires them so that we get the relevant Foo expects x number
287 : : // arguments but got zero see test case rust/compile/traits12.rs
288 : 3360 : if (!args.is_empty () || predicate.requires_generic_args ())
289 : : {
290 : : // this is applying generic arguments to a trait reference
291 : 2870 : predicate.apply_generic_arguments (&args, associated_self != nullptr);
292 : : }
293 : :
294 : 3115 : context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
295 : : predicate);
296 : :
297 : 3115 : return predicate;
298 : 3115 : }
299 : :
300 : : } // namespace Resolver
301 : :
302 : : namespace TyTy {
303 : :
304 : 11758 : TypeBoundPredicate::TypeBoundPredicate (
305 : : const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
306 : 11758 : location_t locus)
307 : 23516 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
308 : 11758 : reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
309 : 23516 : error_flag (false), polarity (polarity)
310 : : {
311 : 11758 : rust_assert (!trait_reference.get_trait_substs ().empty ());
312 : :
313 : 11758 : substitutions.clear ();
314 : 24598 : for (const auto &p : trait_reference.get_trait_substs ())
315 : 12840 : substitutions.push_back (p.clone ());
316 : :
317 : : // we setup a dummy implict self argument
318 : 11758 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
319 : 11758 : used_arguments.get_mappings ().push_back (placeholder_self);
320 : 11758 : }
321 : :
322 : 2082 : TypeBoundPredicate::TypeBoundPredicate (
323 : : DefId reference, std::vector<SubstitutionParamMapping> subst,
324 : 2082 : BoundPolarity polarity, location_t locus)
325 : 4164 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
326 : 2082 : reference (reference), locus (locus), error_flag (false),
327 : 2082 : polarity (polarity)
328 : : {
329 : 2082 : rust_assert (!subst.empty ());
330 : :
331 : 2082 : substitutions.clear ();
332 : 4463 : for (const auto &p : subst)
333 : 2381 : substitutions.push_back (p.clone ());
334 : :
335 : : // we setup a dummy implict self argument
336 : 2082 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
337 : 2082 : used_arguments.get_mappings ().push_back (placeholder_self);
338 : 2082 : }
339 : :
340 : 38671 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
341 : 77342 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
342 : 38671 : reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
343 : 38671 : polarity (BoundPolarity::RegularBound)
344 : 38671 : {}
345 : :
346 : 11828879 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
347 : 23657758 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
348 : 11828879 : reference (other.reference), locus (other.locus),
349 : 11828879 : error_flag (other.error_flag), polarity (other.polarity)
350 : : {
351 : 11828879 : substitutions.clear ();
352 : 23885775 : for (const auto &p : other.get_substs ())
353 : 12056896 : substitutions.push_back (p.clone ());
354 : :
355 : 11828879 : std::vector<SubstitutionArg> mappings;
356 : 23724728 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
357 : : {
358 : 11895849 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
359 : 11895849 : SubstitutionArg arg (oa);
360 : 11895849 : mappings.push_back (std::move (arg));
361 : : }
362 : :
363 : : // we need to remap the argument mappings based on this copied constructor
364 : 11828879 : std::vector<SubstitutionArg> copied_arg_mappings;
365 : 11828879 : size_t i = 0;
366 : 23724728 : for (const auto &m : other.used_arguments.get_mappings ())
367 : : {
368 : 11895849 : TyTy::BaseType *argument
369 : 11895849 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
370 : 11895849 : SubstitutionArg c (&substitutions.at (i++), argument);
371 : 11895849 : copied_arg_mappings.push_back (std::move (c));
372 : : }
373 : :
374 : 11828879 : used_arguments
375 : 11828879 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
376 : : other.used_arguments.get_regions (),
377 : 23657758 : other.used_arguments.get_locus ());
378 : 11828879 : }
379 : :
380 : : TypeBoundPredicate &
381 : 25533 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
382 : : {
383 : 25533 : reference = other.reference;
384 : 25533 : locus = other.locus;
385 : 25533 : error_flag = other.error_flag;
386 : 25533 : polarity = other.polarity;
387 : 25533 : used_arguments = SubstitutionArgumentMappings::empty ();
388 : :
389 : 25533 : substitutions.clear ();
390 : 53056 : for (const auto &p : other.get_substs ())
391 : 27523 : substitutions.push_back (p.clone ());
392 : :
393 : 25533 : if (other.is_error ())
394 : : return *this;
395 : :
396 : 19744 : std::vector<SubstitutionArg> mappings;
397 : 47261 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
398 : : {
399 : 27517 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
400 : 27517 : SubstitutionArg arg (oa);
401 : 27517 : mappings.push_back (std::move (arg));
402 : : }
403 : :
404 : : // we need to remap the argument mappings based on this copied constructor
405 : 19744 : std::vector<SubstitutionArg> copied_arg_mappings;
406 : 19744 : size_t i = 0;
407 : 47261 : for (const auto &m : other.used_arguments.get_mappings ())
408 : : {
409 : 27517 : TyTy::BaseType *argument
410 : 27517 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
411 : 27517 : SubstitutionArg c (&substitutions.at (i++), argument);
412 : 27517 : copied_arg_mappings.push_back (std::move (c));
413 : : }
414 : :
415 : 19744 : used_arguments
416 : 19744 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
417 : : other.used_arguments.get_regions (),
418 : 39488 : other.used_arguments.get_locus ());
419 : :
420 : 19744 : return *this;
421 : 19744 : }
422 : :
423 : : TypeBoundPredicate
424 : 38671 : TypeBoundPredicate::error ()
425 : : {
426 : 38671 : return TypeBoundPredicate (mark_is_error ());
427 : : }
428 : :
429 : : std::string
430 : 1558 : TypeBoundPredicate::as_string () const
431 : : {
432 : 1558 : return get ()->as_string () + subst_as_string ();
433 : : }
434 : :
435 : : std::string
436 : 4267 : TypeBoundPredicate::as_name () const
437 : : {
438 : 4267 : return get ()->get_name () + subst_as_string ();
439 : : }
440 : :
441 : : const Resolver::TraitReference *
442 : 46248 : TypeBoundPredicate::get () const
443 : : {
444 : 46248 : auto context = Resolver::TypeCheckContext::get ();
445 : :
446 : 46248 : Resolver::TraitReference *ref = nullptr;
447 : 46248 : bool ok = context->lookup_trait_reference (reference, &ref);
448 : 46248 : rust_assert (ok);
449 : :
450 : 46248 : return ref;
451 : : }
452 : :
453 : : std::string
454 : 660 : TypeBoundPredicate::get_name () const
455 : : {
456 : 660 : return get ()->get_name ();
457 : : }
458 : :
459 : : bool
460 : 110 : TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
461 : : {
462 : 110 : const Resolver::TraitReference *trait = get ();
463 : 110 : rust_assert (trait != nullptr);
464 : 110 : return trait->is_object_safe (emit_error, locus);
465 : : }
466 : :
467 : : void
468 : 2923 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
469 : : bool has_associated_self)
470 : : {
471 : 2923 : rust_assert (!substitutions.empty ());
472 : 2923 : if (has_associated_self)
473 : : {
474 : 2862 : used_arguments = SubstitutionArgumentMappings::empty ();
475 : : }
476 : : else
477 : : {
478 : : // we need to get the substitutions argument mappings but also remember
479 : : // that we have an implicit Self argument which we must be careful to
480 : : // respect
481 : 61 : rust_assert (!used_arguments.is_empty ());
482 : : }
483 : :
484 : : // now actually perform a substitution
485 : 5846 : used_arguments = get_mappings_from_generic_args (
486 : : *generic_args,
487 : 2923 : Resolver::TypeCheckContext::get ()->regions_from_generic_args (
488 : 2923 : *generic_args));
489 : :
490 : 2923 : error_flag |= used_arguments.is_error ();
491 : 2923 : auto &subst_mappings = used_arguments;
492 : 6574 : for (auto &sub : get_substs ())
493 : : {
494 : 3651 : SubstitutionArg arg = SubstitutionArg::error ();
495 : 3651 : bool ok
496 : 3651 : = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
497 : 3651 : if (ok && arg.get_tyty () != nullptr)
498 : 3588 : sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
499 : : }
500 : :
501 : : // associated argument mappings
502 : 2966 : for (auto &it : subst_mappings.get_binding_args ())
503 : : {
504 : 43 : std::string identifier = it.first;
505 : 43 : TyTy::BaseType *type = it.second;
506 : :
507 : 43 : TypeBoundPredicateItem item = lookup_associated_item (identifier);
508 : 43 : rust_assert (!item.is_error ());
509 : :
510 : 43 : const auto item_ref = item.get_raw_item ();
511 : 43 : item_ref->associated_type_set (type);
512 : 43 : }
513 : 2923 : }
514 : :
515 : : bool
516 : 0 : TypeBoundPredicate::contains_item (const std::string &search) const
517 : : {
518 : 0 : auto trait_ref = get ();
519 : 0 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
520 : 0 : return trait_ref->lookup_trait_item (search, &trait_item_ref);
521 : : }
522 : :
523 : : TypeBoundPredicateItem
524 : 5973 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
525 : : {
526 : 5973 : auto trait_ref = get ();
527 : 5973 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
528 : 5973 : if (!trait_ref->lookup_trait_item (search, &trait_item_ref))
529 : 498 : return TypeBoundPredicateItem::error ();
530 : :
531 : 5475 : return TypeBoundPredicateItem (this, trait_item_ref);
532 : : }
533 : :
534 : 8560 : TypeBoundPredicateItem::TypeBoundPredicateItem (
535 : : const TypeBoundPredicate *parent,
536 : 8560 : const Resolver::TraitItemReference *trait_item_ref)
537 : 8560 : : parent (parent), trait_item_ref (trait_item_ref)
538 : 8560 : {}
539 : :
540 : : TypeBoundPredicateItem
541 : 3015 : TypeBoundPredicateItem::error ()
542 : : {
543 : 3015 : return TypeBoundPredicateItem (nullptr, nullptr);
544 : : }
545 : :
546 : : bool
547 : 8481 : TypeBoundPredicateItem::is_error () const
548 : : {
549 : 8481 : return parent == nullptr || trait_item_ref == nullptr;
550 : : }
551 : :
552 : : const TypeBoundPredicate *
553 : 506 : TypeBoundPredicateItem::get_parent () const
554 : : {
555 : 506 : return parent;
556 : : }
557 : :
558 : : TypeBoundPredicateItem
559 : 2462 : TypeBoundPredicate::lookup_associated_item (
560 : : const Resolver::TraitItemReference *ref) const
561 : : {
562 : 2462 : return lookup_associated_item (ref->get_identifier ());
563 : : }
564 : :
565 : : BaseType *
566 : 3997 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
567 : : {
568 : 3997 : TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
569 : 3997 : if (parent->get_substitution_arguments ().is_empty ())
570 : : return trait_item_tyty;
571 : :
572 : 3997 : const Resolver::TraitItemReference *tref = get_raw_item ();
573 : 3997 : bool is_associated_type = tref->get_trait_item_type ();
574 : 3997 : if (is_associated_type)
575 : : return trait_item_tyty;
576 : :
577 : : // set up the self mapping
578 : 2520 : SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
579 : 2520 : rust_assert (!gargs.is_empty ());
580 : :
581 : : // setup the adjusted mappings
582 : 2520 : std::vector<SubstitutionArg> adjusted_mappings;
583 : 5810 : for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
584 : : {
585 : 3290 : auto &mapping = gargs.get_mappings ().at (i);
586 : :
587 : 3290 : bool is_implicit_self = i == 0;
588 : 3290 : TyTy::BaseType *argument
589 : 3290 : = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
590 : :
591 : 3290 : SubstitutionArg arg (mapping.get_param_mapping (), argument);
592 : 3290 : adjusted_mappings.push_back (std::move (arg));
593 : : }
594 : :
595 : 2520 : SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
596 : : gargs.get_regions (),
597 : : gargs.get_locus (),
598 : 2520 : gargs.get_subst_cb (),
599 : 2520 : true /* trait-mode-flag */);
600 : 2520 : return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
601 : 2520 : }
602 : : bool
603 : 49795 : TypeBoundPredicate::is_error () const
604 : : {
605 : 49795 : auto context = Resolver::TypeCheckContext::get ();
606 : :
607 : 49795 : Resolver::TraitReference *ref = nullptr;
608 : 49795 : bool ok = context->lookup_trait_reference (reference, &ref);
609 : :
610 : 49795 : return !ok || error_flag;
611 : : }
612 : :
613 : : BaseType *
614 : 14934 : TypeBoundPredicate::handle_substitions (
615 : : SubstitutionArgumentMappings &subst_mappings)
616 : : {
617 : 31343 : for (auto &sub : get_substs ())
618 : : {
619 : 16409 : if (sub.get_param_ty () == nullptr)
620 : 0 : continue;
621 : :
622 : 16409 : ParamType *p = sub.get_param_ty ();
623 : 16409 : BaseType *r = p->resolve ();
624 : 16409 : BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
625 : :
626 : 16409 : p->set_ty_ref (s->get_ty_ref ());
627 : : }
628 : :
629 : : // associated argument mappings
630 : 14951 : for (auto &it : subst_mappings.get_binding_args ())
631 : : {
632 : 17 : std::string identifier = it.first;
633 : 17 : TyTy::BaseType *type = it.second;
634 : :
635 : 17 : TypeBoundPredicateItem item = lookup_associated_item (identifier);
636 : 17 : if (!item.is_error ())
637 : : {
638 : 0 : const auto item_ref = item.get_raw_item ();
639 : 0 : item_ref->associated_type_set (type);
640 : : }
641 : 17 : }
642 : :
643 : : // FIXME more error handling at some point
644 : : // used_arguments = subst_mappings;
645 : : // error_flag |= used_arguments.is_error ();
646 : :
647 : 14934 : return nullptr;
648 : : }
649 : :
650 : : bool
651 : 245 : TypeBoundPredicate::requires_generic_args () const
652 : : {
653 : 245 : if (is_error ())
654 : : return false;
655 : :
656 : 245 : return substitutions.size () > 1;
657 : : }
658 : :
659 : : bool
660 : 0 : TypeBoundPredicate::contains_associated_types () const
661 : : {
662 : 0 : return get_num_associated_bindings () > 0;
663 : : }
664 : :
665 : : size_t
666 : 86 : TypeBoundPredicate::get_num_associated_bindings () const
667 : : {
668 : 86 : size_t count = 0;
669 : 86 : auto trait_ref = get ();
670 : 258 : for (const auto &trait_item : trait_ref->get_trait_items ())
671 : : {
672 : 172 : bool is_associated_type
673 : 172 : = trait_item.get_trait_item_type ()
674 : 172 : == Resolver::TraitItemReference::TraitItemType::TYPE;
675 : 172 : if (is_associated_type)
676 : 86 : count++;
677 : : }
678 : 86 : return count;
679 : : }
680 : :
681 : : TypeBoundPredicateItem
682 : 43 : TypeBoundPredicate::lookup_associated_type (const std::string &search)
683 : : {
684 : 43 : TypeBoundPredicateItem item = lookup_associated_item (search);
685 : :
686 : : // only need to check that it is infact an associated type because other
687 : : // wise if it was not found it will just be an error node anyway
688 : 43 : if (!item.is_error ())
689 : : {
690 : 43 : const auto raw = item.get_raw_item ();
691 : 43 : if (raw->get_trait_item_type ()
692 : : != Resolver::TraitItemReference::TraitItemType::TYPE)
693 : 0 : return TypeBoundPredicateItem::error ();
694 : : }
695 : 43 : return item;
696 : : }
697 : :
698 : : std::vector<TypeBoundPredicateItem>
699 : 0 : TypeBoundPredicate::get_associated_type_items ()
700 : : {
701 : 0 : std::vector<TypeBoundPredicateItem> items;
702 : 0 : auto trait_ref = get ();
703 : 0 : for (const auto &trait_item : trait_ref->get_trait_items ())
704 : : {
705 : 0 : bool is_associated_type
706 : 0 : = trait_item.get_trait_item_type ()
707 : 0 : == Resolver::TraitItemReference::TraitItemType::TYPE;
708 : 0 : if (is_associated_type)
709 : : {
710 : 0 : TypeBoundPredicateItem item (this, &trait_item);
711 : 0 : items.push_back (std::move (item));
712 : : }
713 : : }
714 : 0 : return items;
715 : : }
716 : :
717 : : bool
718 : 6983 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
719 : : {
720 : : // check they match the same trait reference
721 : 13056 : if (reference != other.reference)
722 : : return false;
723 : :
724 : : // check that the generics match
725 : 923 : if (get_num_substitutions () != other.get_num_substitutions ())
726 : : return false;
727 : :
728 : : // then match the generics applied
729 : 2180 : for (size_t i = 0; i < get_num_substitutions (); i++)
730 : : {
731 : 1270 : const SubstitutionParamMapping &a = substitutions.at (i);
732 : 1270 : const SubstitutionParamMapping &b = other.substitutions.at (i);
733 : :
734 : 1270 : const ParamType *ap = a.get_param_ty ();
735 : 1270 : const ParamType *bp = b.get_param_ty ();
736 : :
737 : 1270 : const BaseType *apd = ap->destructure ();
738 : 1270 : const BaseType *bpd = bp->destructure ();
739 : :
740 : : // FIXME use the unify_and infer inteface or try coerce
741 : 1270 : if (!apd->can_eq (bpd, false /*emit_errors*/))
742 : : {
743 : 316 : if (!bpd->can_eq (apd, false /*emit_errors*/))
744 : : return false;
745 : : }
746 : : }
747 : :
748 : : return true;
749 : : }
750 : :
751 : : // trait item reference
752 : :
753 : : const Resolver::TraitItemReference *
754 : 16500 : TypeBoundPredicateItem::get_raw_item () const
755 : : {
756 : 16500 : return trait_item_ref;
757 : : }
758 : :
759 : : bool
760 : 0 : TypeBoundPredicateItem::needs_implementation () const
761 : : {
762 : 0 : return !get_raw_item ()->is_optional ();
763 : : }
764 : :
765 : : location_t
766 : 3 : TypeBoundPredicateItem::get_locus () const
767 : : {
768 : 3 : return get_raw_item ()->get_locus ();
769 : : }
770 : :
771 : : // TypeBoundsMappings
772 : :
773 : 13106672 : TypeBoundsMappings::TypeBoundsMappings (
774 : 13106672 : std::vector<TypeBoundPredicate> specified_bounds)
775 : 13106672 : : specified_bounds (specified_bounds)
776 : 13106672 : {}
777 : :
778 : : std::vector<TypeBoundPredicate> &
779 : 20843 : TypeBoundsMappings::get_specified_bounds ()
780 : : {
781 : 20843 : return specified_bounds;
782 : : }
783 : :
784 : : const std::vector<TypeBoundPredicate> &
785 : 12389460 : TypeBoundsMappings::get_specified_bounds () const
786 : : {
787 : 12389460 : return specified_bounds;
788 : : }
789 : :
790 : : TypeBoundPredicate
791 : 1157 : TypeBoundsMappings::lookup_predicate (DefId id)
792 : : {
793 : 1211 : for (auto &b : specified_bounds)
794 : : {
795 : 1250 : if (b.get_id () == id)
796 : 1142 : return b;
797 : : }
798 : 15 : return TypeBoundPredicate::error ();
799 : : }
800 : :
801 : : size_t
802 : 117160 : TypeBoundsMappings::num_specified_bounds () const
803 : : {
804 : 117160 : return specified_bounds.size ();
805 : : }
806 : :
807 : : std::string
808 : 17563 : TypeBoundsMappings::raw_bounds_as_string () const
809 : : {
810 : 17563 : std::string buf;
811 : 18095 : for (size_t i = 0; i < specified_bounds.size (); i++)
812 : : {
813 : 532 : const TypeBoundPredicate &b = specified_bounds.at (i);
814 : 532 : bool has_next = (i + 1) < specified_bounds.size ();
815 : 1596 : buf += b.as_string () + (has_next ? " + " : "");
816 : : }
817 : 17563 : return buf;
818 : : }
819 : :
820 : : std::string
821 : 17082 : TypeBoundsMappings::bounds_as_string () const
822 : : {
823 : 34164 : return "bounds:[" + raw_bounds_as_string () + "]";
824 : : }
825 : :
826 : : std::string
827 : 4287 : TypeBoundsMappings::raw_bounds_as_name () const
828 : : {
829 : 4287 : std::string buf;
830 : 8554 : for (size_t i = 0; i < specified_bounds.size (); i++)
831 : : {
832 : 4267 : const TypeBoundPredicate &b = specified_bounds.at (i);
833 : 4267 : bool has_next = (i + 1) < specified_bounds.size ();
834 : 12801 : buf += b.as_name () + (has_next ? " + " : "");
835 : : }
836 : :
837 : 4287 : return buf;
838 : : }
839 : :
840 : : void
841 : 17765 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
842 : : {
843 : 19658 : for (auto &bound : specified_bounds)
844 : : {
845 : 9625 : bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
846 : 1893 : if (same_trait_ref_p)
847 : 17765 : return;
848 : : }
849 : :
850 : 10033 : specified_bounds.push_back (predicate);
851 : : }
852 : :
853 : : } // namespace TyTy
854 : : } // namespace Rust
|