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