Line data Source code
1 : // Copyright (C) 2021-2026 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-full-decls.h"
20 : #include "rust-hir-type-bounds.h"
21 : #include "rust-hir-trait-resolve.h"
22 : #include "rust-substitution-mapper.h"
23 : #include "rust-hir-trait-resolve.h"
24 : #include "rust-type-util.h"
25 :
26 : namespace Rust {
27 : namespace Resolver {
28 :
29 66508 : TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
30 66508 : : TypeCheckBase (), receiver (receiver)
31 66508 : {}
32 :
33 : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
34 66508 : TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
35 : {
36 66508 : TypeBoundsProbe probe (receiver);
37 66508 : probe.scan ();
38 66508 : return probe.trait_references;
39 66508 : }
40 :
41 : bool
42 80 : TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
43 : TraitReference *ref)
44 : {
45 80 : for (auto &bound : receiver->get_specified_bounds ())
46 : {
47 0 : const TraitReference *b = bound.get ();
48 0 : if (b->is_equal (*ref))
49 80 : return true;
50 : }
51 :
52 80 : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
53 80 : = Probe (receiver);
54 91 : for (auto &bound : bounds)
55 : {
56 91 : const TraitReference *b = bound.first;
57 91 : if (b->is_equal (*ref))
58 80 : return true;
59 : }
60 :
61 : return false;
62 80 : }
63 :
64 : bool
65 2002015 : TypeBoundsProbe::process_impl_block (
66 : HirId id, HIR::ImplBlock *impl,
67 : std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
68 : &possible_trait_paths)
69 : {
70 : // we are filtering for trait-impl-blocks
71 2002015 : if (!impl->has_trait_ref ())
72 : return true;
73 :
74 : // can be recursive trait resolution
75 1782618 : HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
76 1782618 : if (t == nullptr)
77 : return true;
78 :
79 1782618 : HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
80 1782618 : TyTy::BaseType *impl_type = nullptr;
81 1782618 : if (!query_type (impl_ty_id, &impl_type))
82 : return true;
83 :
84 1779607 : if (!types_compatable (TyTy::TyWithLocation (receiver),
85 1779607 : TyTy::TyWithLocation (impl_type), impl->get_locus (),
86 : false /*emit_errors*/, false /*check-bounds*/))
87 : return true;
88 :
89 283662 : possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
90 283662 : return true;
91 : }
92 :
93 : void
94 66508 : TypeBoundsProbe::scan ()
95 : {
96 66508 : std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
97 66508 : possible_trait_paths;
98 66508 : mappings.iterate_impl_blocks (
99 66508 : [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
100 2002015 : return process_impl_block (id, impl, possible_trait_paths);
101 : });
102 :
103 350170 : for (auto &path : possible_trait_paths)
104 : {
105 283662 : HIR::TypePath *trait_path = path.first;
106 283662 : TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
107 :
108 283662 : if (!trait_ref->is_error ())
109 283662 : trait_references.emplace_back (trait_ref, path.second);
110 : }
111 :
112 : // marker traits...
113 66508 : assemble_marker_builtins ();
114 :
115 : // add auto trait bounds
116 66526 : for (auto *auto_trait : mappings.get_auto_traits ())
117 18 : add_trait_bound (auto_trait);
118 66508 : }
119 :
120 : void
121 66508 : TypeBoundsProbe::assemble_marker_builtins ()
122 : {
123 66508 : const TyTy::BaseType *raw = receiver->destructure ();
124 :
125 : // https://runrust.miraheze.org/wiki/Dynamically_Sized_Type
126 : // everything is sized except for:
127 : //
128 : // 1. dyn traits
129 : // 2. slices
130 : // 3. str
131 : // 4. ADT's which contain any of the above
132 : // t. tuples which contain any of the above
133 66508 : switch (raw->get_kind ())
134 : {
135 50687 : case TyTy::ARRAY:
136 50687 : case TyTy::REF:
137 50687 : case TyTy::POINTER:
138 50687 : case TyTy::PARAM:
139 50687 : case TyTy::FNDEF:
140 50687 : case TyTy::BOOL:
141 50687 : case TyTy::CHAR:
142 50687 : case TyTy::INT:
143 50687 : case TyTy::UINT:
144 50687 : case TyTy::FLOAT:
145 50687 : case TyTy::USIZE:
146 50687 : case TyTy::ISIZE:
147 50687 : case TyTy::INFER:
148 50687 : case TyTy::NEVER:
149 50687 : case TyTy::PLACEHOLDER:
150 50687 : case TyTy::PROJECTION:
151 50687 : case TyTy::OPAQUE:
152 50687 : assemble_builtin_candidate (LangItem::Kind::SIZED);
153 50687 : break;
154 :
155 175 : case TyTy::FNPTR:
156 175 : case TyTy::CLOSURE:
157 175 : assemble_builtin_candidate (LangItem::Kind::SIZED);
158 175 : assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
159 175 : assemble_builtin_candidate (LangItem::Kind::FN);
160 175 : assemble_builtin_candidate (LangItem::Kind::FN_MUT);
161 175 : break;
162 :
163 : // FIXME str and slice need to be moved and test cases updated
164 15417 : case TyTy::SLICE:
165 15417 : case TyTy::STR:
166 15417 : case TyTy::ADT:
167 15417 : case TyTy::TUPLE:
168 : // FIXME add extra checks
169 15417 : assemble_builtin_candidate (LangItem::Kind::SIZED);
170 15417 : break;
171 :
172 : case TyTy::CONST:
173 : case TyTy::DYNAMIC:
174 : case TyTy::ERROR:
175 : break;
176 : }
177 66508 : }
178 :
179 : void
180 66215 : TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
181 : {
182 66215 : auto trait_ref = TraitResolver::Resolve (*trait);
183 :
184 66215 : trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
185 66215 : }
186 :
187 : void
188 66804 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
189 : {
190 66804 : auto lang_item_defined = mappings.lookup_lang_item (lang_item);
191 66804 : if (!lang_item_defined)
192 607 : return;
193 66197 : DefId &id = lang_item_defined.value ();
194 :
195 66197 : auto defid = mappings.lookup_defid (id);
196 66197 : if (!defid)
197 : return;
198 66197 : auto item = defid.value ();
199 :
200 66197 : rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
201 66197 : HIR::Trait *trait = static_cast<HIR::Trait *> (item);
202 66197 : const TyTy::BaseType *raw = receiver->destructure ();
203 :
204 66197 : add_trait_bound (trait);
205 :
206 66197 : rust_debug ("Added builtin lang_item: %s for %s",
207 : LangItem::ToString (lang_item).c_str (),
208 : raw->get_name ().c_str ());
209 : }
210 :
211 : TraitReference *
212 6757 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
213 : {
214 6757 : return TraitResolver::Resolve (path);
215 : }
216 :
217 : TyTy::TypeBoundPredicate
218 38136 : TypeCheckBase::get_predicate_from_bound (
219 : HIR::TypePath &type_path,
220 : tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
221 : BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait)
222 : {
223 38136 : TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
224 38136 : bool already_resolved
225 38136 : = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
226 : &lookup);
227 38136 : if (already_resolved)
228 31379 : return lookup;
229 :
230 6757 : TraitReference *trait = resolve_trait_path (type_path);
231 6757 : if (trait->is_error ())
232 9 : return TyTy::TypeBoundPredicate::error ();
233 :
234 6748 : TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
235 6748 : HIR::GenericArgs args
236 6748 : = HIR::GenericArgs::create_empty (type_path.get_locus ());
237 :
238 6748 : auto &final_seg = type_path.get_final_segment ();
239 6748 : switch (final_seg.get_type ())
240 : {
241 847 : case HIR::TypePathSegment::SegmentType::GENERIC:
242 847 : {
243 847 : auto &final_generic_seg
244 : = static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
245 847 : if (final_generic_seg.has_generic_args ())
246 : {
247 847 : args = final_generic_seg.get_generic_args ();
248 847 : if (args.get_binding_args ().size () > 0
249 847 : && associated_self.has_value () && is_qualified_type_path)
250 : {
251 1 : auto &binding_args = args.get_binding_args ();
252 :
253 1 : rich_location r (line_table, args.get_locus ());
254 2 : for (auto it = binding_args.begin (); it != binding_args.end ();
255 1 : it++)
256 : {
257 1 : auto &arg = *it;
258 1 : r.add_fixit_remove (arg.get_locus ());
259 : }
260 1 : rust_error_at (r, ErrorCode::E0229,
261 : "associated type bindings are not allowed here");
262 1 : }
263 : }
264 : }
265 : break;
266 :
267 27 : case HIR::TypePathSegment::SegmentType::FUNCTION:
268 27 : {
269 27 : auto &final_function_seg
270 : = static_cast<HIR::TypePathSegmentFunction &> (final_seg);
271 27 : auto &fn = final_function_seg.get_function_path ();
272 :
273 : // we need to make implicit generic args which must be an implicit
274 : // Tuple
275 27 : auto crate_num = mappings.get_current_crate ();
276 27 : HirId implicit_args_id = mappings.get_next_hir_id ();
277 27 : Analysis::NodeMapping mapping (crate_num,
278 27 : final_seg.get_mappings ().get_nodeid (),
279 27 : implicit_args_id, UNKNOWN_LOCAL_DEFID);
280 :
281 27 : std::vector<std::unique_ptr<HIR::Type>> params_copy;
282 56 : for (auto &p : fn.get_params ())
283 : {
284 29 : params_copy.push_back (p->clone_type ());
285 : }
286 :
287 27 : std::vector<std::unique_ptr<HIR::Type>> inputs;
288 27 : inputs.push_back (
289 27 : std::make_unique<HIR::TupleType> (mapping, std::move (params_copy),
290 27 : final_seg.get_locus ()));
291 :
292 : // resolve the fn_once_output type which assumes there must be an output
293 : // set
294 27 : rust_assert (fn.has_return_type ());
295 27 : TypeCheckType::Resolve (fn.get_return_type ());
296 :
297 27 : HIR::TraitItem *trait_item
298 27 : = mappings
299 27 : .lookup_trait_item_lang_item (LangItem::Kind::FN_ONCE_OUTPUT,
300 : final_seg.get_locus ())
301 27 : .value ();
302 :
303 27 : std::vector<HIR::GenericArgsBinding> bindings;
304 27 : location_t output_locus = fn.get_return_type ().get_locus ();
305 81 : bindings.emplace_back (Identifier (trait_item->trait_identifier ()),
306 54 : fn.get_return_type ().clone_type (),
307 : output_locus);
308 :
309 54 : args = HIR::GenericArgs ({} /* lifetimes */,
310 : std::move (inputs) /* type_args*/,
311 : std::move (bindings) /* binding_args*/,
312 54 : {} /* const_args */, final_seg.get_locus ());
313 27 : }
314 27 : break;
315 :
316 : default:
317 : /* nothing to do */
318 : break;
319 : }
320 :
321 6748 : if (associated_self.has_value ())
322 : {
323 5950 : std::vector<std::unique_ptr<HIR::Type>> type_args;
324 5950 : type_args.push_back (std::unique_ptr<HIR::Type> (
325 5950 : associated_self.value ().get ().clone_type ()));
326 6539 : for (auto &arg : args.get_type_args ())
327 : {
328 589 : type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
329 : }
330 :
331 17850 : args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
332 5950 : args.get_binding_args (), args.get_const_args (),
333 11900 : args.get_locus ());
334 5950 : }
335 :
336 : // we try to apply generic arguments when they are non empty and or when the
337 : // predicate requires them so that we get the relevant Foo expects x number
338 : // arguments but got zero see test case rust/compile/traits12.rs
339 6748 : if (!args.is_empty () || predicate.requires_generic_args ())
340 : {
341 : // this is applying generic arguments to a trait reference
342 6224 : predicate.apply_generic_arguments (&args, associated_self.has_value (),
343 : is_super_trait);
344 : }
345 :
346 6748 : context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
347 : predicate);
348 :
349 6748 : return predicate;
350 38136 : }
351 :
352 : } // namespace Resolver
353 :
354 : namespace TyTy {
355 :
356 20224 : TypeBoundPredicate::TypeBoundPredicate (
357 : const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
358 20224 : location_t locus)
359 40448 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
360 20224 : reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
361 20224 : error_flag (false), polarity (polarity),
362 60672 : super_traits (trait_reference.get_super_traits ())
363 : {
364 20224 : rust_assert (!trait_reference.get_trait_substs ().empty ());
365 :
366 20224 : substitutions.clear ();
367 43340 : for (const auto &p : trait_reference.get_trait_substs ())
368 23116 : substitutions.push_back (p.clone ());
369 :
370 : // we setup a dummy implict self argument
371 20224 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
372 20224 : used_arguments.get_mappings ().push_back (placeholder_self);
373 20224 : }
374 :
375 3696 : TypeBoundPredicate::TypeBoundPredicate (
376 : DefId reference, std::vector<SubstitutionParamMapping> subst,
377 3696 : BoundPolarity polarity, location_t locus)
378 7392 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
379 3696 : reference (reference), locus (locus), error_flag (false),
380 7392 : polarity (polarity)
381 : {
382 3696 : rust_assert (!subst.empty ());
383 :
384 3696 : substitutions.clear ();
385 8041 : for (const auto &p : subst)
386 4345 : substitutions.push_back (p.clone ());
387 :
388 : // we setup a dummy implict self argument
389 3696 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
390 3696 : used_arguments.get_mappings ().push_back (placeholder_self);
391 3696 : }
392 :
393 108790 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
394 217580 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
395 108790 : reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
396 108790 : polarity (BoundPolarity::RegularBound)
397 108790 : {}
398 :
399 73867070 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
400 147734140 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
401 73867070 : reference (other.reference), locus (other.locus),
402 73867070 : error_flag (other.error_flag), polarity (other.polarity),
403 147734140 : super_traits (other.super_traits)
404 : {
405 73867070 : substitutions.clear ();
406 157197190 : for (const auto &p : other.get_substs ())
407 83330120 : substitutions.push_back (p.clone ());
408 :
409 73867070 : std::vector<SubstitutionArg> mappings;
410 149375468 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
411 : {
412 75508398 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
413 75508398 : SubstitutionArg arg (oa);
414 75508398 : mappings.push_back (std::move (arg));
415 : }
416 :
417 : // we need to remap the argument mappings based on this copied constructor
418 73867070 : std::vector<SubstitutionArg> copied_arg_mappings;
419 73867070 : size_t i = 0;
420 149375468 : for (const auto &m : other.used_arguments.get_mappings ())
421 : {
422 75508398 : TyTy::BaseType *argument
423 75508398 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
424 75508398 : SubstitutionArg c (&substitutions.at (i++), argument);
425 75508398 : copied_arg_mappings.push_back (std::move (c));
426 : }
427 :
428 73867070 : used_arguments
429 73867070 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
430 : other.used_arguments.get_regions (),
431 147734140 : other.used_arguments.get_locus ());
432 73867070 : }
433 :
434 : TypeBoundPredicate &
435 81128 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
436 : {
437 81128 : reference = other.reference;
438 81128 : locus = other.locus;
439 81128 : error_flag = other.error_flag;
440 81128 : polarity = other.polarity;
441 81128 : used_arguments = SubstitutionArgumentMappings::empty ();
442 :
443 81128 : substitutions.clear ();
444 199880 : for (const auto &p : other.get_substs ())
445 118752 : substitutions.push_back (p.clone ());
446 :
447 81128 : if (other.is_error ())
448 : return *this;
449 :
450 71971 : std::vector<SubstitutionArg> mappings;
451 190712 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
452 : {
453 118741 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
454 118741 : SubstitutionArg arg (oa);
455 118741 : mappings.push_back (std::move (arg));
456 : }
457 :
458 : // we need to remap the argument mappings based on this copied constructor
459 71971 : std::vector<SubstitutionArg> copied_arg_mappings;
460 71971 : size_t i = 0;
461 190712 : for (const auto &m : other.used_arguments.get_mappings ())
462 : {
463 118741 : TyTy::BaseType *argument
464 118741 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
465 :
466 118741 : copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
467 : }
468 :
469 71971 : used_arguments
470 71971 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
471 : other.used_arguments.get_regions (),
472 143942 : other.used_arguments.get_locus ());
473 71971 : super_traits = other.super_traits;
474 :
475 71971 : return *this;
476 71971 : }
477 :
478 : TypeBoundPredicate
479 108790 : TypeBoundPredicate::error ()
480 : {
481 108790 : return TypeBoundPredicate (mark_is_error ());
482 : }
483 :
484 : std::string
485 3271 : TypeBoundPredicate::as_string () const
486 : {
487 3271 : return get ()->as_string () + subst_as_string ();
488 : }
489 :
490 : std::string
491 49615 : TypeBoundPredicate::as_name () const
492 : {
493 49615 : return get ()->get_name () + subst_as_string ();
494 : }
495 :
496 : const Resolver::TraitReference *
497 362883 : TypeBoundPredicate::get () const
498 : {
499 362883 : auto context = Resolver::TypeCheckContext::get ();
500 :
501 362883 : Resolver::TraitReference *ref = nullptr;
502 362883 : bool ok = context->lookup_trait_reference (reference, &ref);
503 362883 : rust_assert (ok);
504 :
505 362883 : return ref;
506 : }
507 :
508 : std::string
509 8536 : TypeBoundPredicate::get_name () const
510 : {
511 8536 : return get ()->get_name ();
512 : }
513 :
514 : bool
515 200 : TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
516 : {
517 200 : const Resolver::TraitReference *trait = get ();
518 200 : rust_assert (trait != nullptr);
519 200 : return trait->is_object_safe (emit_error, locus);
520 : }
521 :
522 : void
523 6289 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
524 : bool has_associated_self,
525 : bool is_super_trait)
526 : {
527 6289 : rust_assert (!substitutions.empty ());
528 6289 : if (has_associated_self)
529 : {
530 5950 : used_arguments = SubstitutionArgumentMappings::empty ();
531 : }
532 : else
533 : {
534 : // we need to get the substitutions argument mappings but also remember
535 : // that we have an implicit Self argument which we must be careful to
536 : // respect
537 339 : rust_assert (!used_arguments.is_empty ());
538 : }
539 :
540 : // now actually perform a substitution
541 6289 : auto args = get_mappings_from_generic_args (
542 : *generic_args,
543 6289 : Resolver::TypeCheckContext::get ()->regions_from_generic_args (
544 12578 : *generic_args));
545 :
546 6289 : apply_argument_mappings (args, is_super_trait);
547 6289 : }
548 :
549 : void
550 10316 : TypeBoundPredicate::apply_argument_mappings (
551 : SubstitutionArgumentMappings &arguments, bool is_super_trait)
552 : {
553 10316 : used_arguments = arguments;
554 10316 : error_flag |= used_arguments.is_error ();
555 10316 : auto &subst_mappings = used_arguments;
556 :
557 10316 : bool substs_need_bounds_check = !is_super_trait;
558 23623 : for (auto &sub : get_substs ())
559 : {
560 13307 : SubstitutionArg arg = SubstitutionArg::error ();
561 13307 : bool ok
562 13307 : = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
563 13307 : if (ok && arg.get_tyty () != nullptr)
564 12887 : sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
565 : substs_need_bounds_check);
566 : }
567 :
568 : // associated argument mappings
569 10396 : for (auto &it : subst_mappings.get_binding_args ())
570 : {
571 80 : std::string identifier = it.first;
572 80 : TyTy::BaseType *type = it.second;
573 :
574 80 : tl::optional<TypeBoundPredicateItem> item
575 80 : = lookup_associated_item (identifier);
576 :
577 80 : if (!item.has_value ())
578 0 : continue;
579 :
580 80 : const auto item_ref = item->get_raw_item ();
581 80 : item_ref->associated_type_set (type);
582 80 : }
583 :
584 14335 : for (auto &super_trait : super_traits)
585 : {
586 4019 : auto adjusted
587 : = super_trait.adjust_mappings_for_this (used_arguments,
588 4019 : true /*trait mode*/);
589 4019 : super_trait.apply_argument_mappings (adjusted, is_super_trait);
590 4019 : }
591 10316 : }
592 :
593 : bool
594 0 : TypeBoundPredicate::contains_item (const std::string &search) const
595 : {
596 0 : auto trait_ref = get ();
597 0 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
598 0 : return trait_ref->lookup_trait_item (search, &trait_item_ref);
599 : }
600 :
601 : tl::optional<TypeBoundPredicateItem>
602 24751 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
603 : {
604 24751 : auto trait_ref = get ();
605 24751 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
606 24751 : if (trait_ref->lookup_trait_item (search, &trait_item_ref,
607 : false /*lookup supers*/))
608 23270 : return TypeBoundPredicateItem (*this, trait_item_ref);
609 :
610 1597 : for (auto &super_trait : super_traits)
611 : {
612 236 : auto lookup = super_trait.lookup_associated_item (search);
613 236 : if (lookup.has_value ())
614 120 : return lookup;
615 236 : }
616 :
617 1361 : return tl::nullopt;
618 : }
619 :
620 28755 : TypeBoundPredicateItem::TypeBoundPredicateItem (
621 : const TypeBoundPredicate parent,
622 28755 : const Resolver::TraitItemReference *trait_item_ref)
623 28755 : : parent (parent), trait_item_ref (trait_item_ref)
624 28755 : {}
625 :
626 31337 : TypeBoundPredicateItem::TypeBoundPredicateItem (
627 31337 : const TypeBoundPredicateItem &other)
628 31337 : : parent (other.parent), trait_item_ref (other.trait_item_ref)
629 31337 : {}
630 :
631 : TypeBoundPredicateItem &
632 5408 : TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
633 : {
634 5408 : parent = other.parent;
635 5408 : trait_item_ref = other.trait_item_ref;
636 :
637 5408 : return *this;
638 : }
639 :
640 : TypeBoundPredicateItem
641 5412 : TypeBoundPredicateItem::error ()
642 : {
643 5412 : return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
644 : }
645 :
646 : bool
647 5484 : TypeBoundPredicateItem::is_error () const
648 : {
649 5484 : return parent.is_error () || trait_item_ref == nullptr;
650 : }
651 :
652 : const TypeBoundPredicate *
653 1262 : TypeBoundPredicateItem::get_parent () const
654 : {
655 1262 : return &parent;
656 : }
657 :
658 : tl::optional<TypeBoundPredicateItem>
659 5347 : TypeBoundPredicate::lookup_associated_item (
660 : const Resolver::TraitItemReference *ref) const
661 : {
662 5347 : return lookup_associated_item (ref->get_identifier ());
663 : }
664 :
665 : BaseType *
666 7381 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
667 : {
668 7381 : TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
669 7381 : if (parent.get_substitution_arguments ().is_empty ())
670 : return trait_item_tyty;
671 :
672 7381 : const Resolver::TraitItemReference *tref = get_raw_item ();
673 7381 : bool is_associated_type = tref->get_trait_item_type ();
674 7381 : if (is_associated_type)
675 : return trait_item_tyty;
676 :
677 : // set up the self mapping
678 5880 : SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
679 5880 : rust_assert (!gargs.is_empty ());
680 :
681 : // setup the adjusted mappings
682 5880 : std::vector<SubstitutionArg> adjusted_mappings;
683 14225 : for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
684 : {
685 8345 : auto &mapping = gargs.get_mappings ().at (i);
686 :
687 8345 : bool is_implicit_self = i == 0;
688 8345 : TyTy::BaseType *argument
689 8345 : = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
690 :
691 8345 : adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument);
692 : }
693 :
694 5880 : SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
695 : gargs.get_regions (),
696 : gargs.get_locus (),
697 5880 : gargs.get_subst_cb (),
698 5880 : true /* trait-mode-flag */);
699 5880 : return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
700 5880 : }
701 : bool
702 152902 : TypeBoundPredicate::is_error () const
703 : {
704 152902 : auto context = Resolver::TypeCheckContext::get ();
705 :
706 152902 : Resolver::TraitReference *ref = nullptr;
707 152902 : bool ok = context->lookup_trait_reference (reference, &ref);
708 :
709 152902 : return !ok || error_flag;
710 : }
711 :
712 : BaseType *
713 36957 : TypeBoundPredicate::handle_substitions (
714 : SubstitutionArgumentMappings &subst_mappings)
715 : {
716 82076 : for (auto &sub : get_substs ())
717 : {
718 45119 : if (sub.get_param_ty () == nullptr)
719 0 : continue;
720 :
721 45119 : auto p = sub.get_param_ty ();
722 45119 : BaseType *r = p->resolve ();
723 45119 : BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
724 :
725 45119 : p->set_ty_ref (s->get_ty_ref ());
726 : }
727 :
728 : // associated argument mappings
729 37000 : for (auto &it : subst_mappings.get_binding_args ())
730 : {
731 43 : std::string identifier = it.first;
732 43 : TyTy::BaseType *type = it.second;
733 :
734 43 : tl::optional<TypeBoundPredicateItem> item
735 43 : = lookup_associated_item (identifier);
736 43 : if (item.has_value ())
737 : {
738 8 : const auto item_ref = item->get_raw_item ();
739 8 : item_ref->associated_type_set (type);
740 : }
741 43 : }
742 :
743 : // FIXME more error handling at some point
744 : // used_arguments = subst_mappings;
745 : // error_flag |= used_arguments.is_error ();
746 :
747 36957 : return nullptr;
748 : }
749 :
750 : bool
751 524 : TypeBoundPredicate::requires_generic_args () const
752 : {
753 524 : if (is_error ())
754 : return false;
755 :
756 524 : return substitutions.size () > 1;
757 : }
758 :
759 : bool
760 0 : TypeBoundPredicate::contains_associated_types () const
761 : {
762 0 : return get_num_associated_bindings () > 0;
763 : }
764 :
765 : size_t
766 144 : TypeBoundPredicate::get_num_associated_bindings () const
767 : {
768 144 : size_t count = 0;
769 :
770 144 : get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
771 396 : for (const auto &trait_item : ref.get_trait_items ())
772 : {
773 252 : bool is_associated_type
774 252 : = trait_item.get_trait_item_type ()
775 252 : == Resolver::TraitItemReference::TraitItemType::TYPE;
776 252 : if (is_associated_type)
777 144 : count++;
778 : }
779 144 : });
780 :
781 144 : return count;
782 : }
783 :
784 : void
785 144 : TypeBoundPredicate::get_trait_hierachy (
786 : std::function<void (const Resolver::TraitReference &)> callback) const
787 : {
788 144 : auto trait_ref = get ();
789 144 : callback (*trait_ref);
790 :
791 144 : for (auto &super : super_traits)
792 : {
793 0 : const auto &super_trait_ref = *super.get ();
794 0 : callback (super_trait_ref);
795 0 : super.get_trait_hierachy (callback);
796 : }
797 144 : }
798 :
799 : TypeBoundPredicateItem
800 72 : TypeBoundPredicate::lookup_associated_type (const std::string &search)
801 : {
802 72 : tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search);
803 :
804 : // only need to check that it is infact an associated type because other
805 : // wise if it was not found it will just be an error node anyway
806 72 : if (item.has_value ())
807 : {
808 72 : const auto raw = item->get_raw_item ();
809 72 : if (raw->get_trait_item_type ()
810 : != Resolver::TraitItemReference::TraitItemType::TYPE)
811 0 : return TypeBoundPredicateItem::error ();
812 : }
813 72 : return item.value ();
814 72 : }
815 :
816 : std::vector<TypeBoundPredicateItem>
817 0 : TypeBoundPredicate::get_associated_type_items ()
818 : {
819 0 : std::vector<TypeBoundPredicateItem> items;
820 0 : auto trait_ref = get ();
821 0 : for (const auto &trait_item : trait_ref->get_trait_items ())
822 : {
823 0 : bool is_associated_type
824 0 : = trait_item.get_trait_item_type ()
825 0 : == Resolver::TraitItemReference::TraitItemType::TYPE;
826 0 : if (is_associated_type)
827 0 : items.emplace_back (*this, &trait_item);
828 : }
829 0 : return items;
830 : }
831 :
832 : bool
833 21704 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
834 : {
835 : // check they match the same trait reference
836 40122 : if (reference != other.reference)
837 : return false;
838 :
839 : // check that the generics match
840 3301 : if (get_num_substitutions () != other.get_num_substitutions ())
841 : return false;
842 :
843 : // then match the generics applied
844 7713 : for (size_t i = 0; i < get_num_substitutions (); i++)
845 : {
846 4427 : SubstitutionParamMapping a = substitutions.at (i);
847 4427 : SubstitutionParamMapping b = other.substitutions.at (i);
848 :
849 4427 : auto ap = a.get_param_ty ();
850 4427 : auto bp = b.get_param_ty ();
851 :
852 4427 : BaseType *apd = ap->destructure ();
853 4427 : BaseType *bpd = bp->destructure ();
854 :
855 4427 : if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
856 4427 : TyTy::TyWithLocation (bpd),
857 : UNKNOWN_LOCATION, false))
858 15 : return false;
859 : }
860 :
861 : return true;
862 : }
863 :
864 : bool
865 8310 : TypeBoundPredicate::validate_type_implements_super_traits (
866 : TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
867 : {
868 8310 : if (get_polarity () != BoundPolarity::RegularBound)
869 : return true;
870 :
871 8305 : auto &ptref = *get ();
872 11964 : for (auto &super : super_traits)
873 : {
874 3660 : if (super.get_polarity () != BoundPolarity::RegularBound)
875 0 : continue;
876 :
877 3660 : if (!super.validate_type_implements_this (self, impl_type, trait))
878 : {
879 1 : auto &sptref = *super.get ();
880 :
881 : // emit error
882 1 : std::string fixit1
883 1 : = "required by this bound in: " + ptref.get_name ();
884 2 : std::string fixit2 = "the trait " + sptref.get_name ()
885 2 : + " is not implemented for "
886 2 : + impl_type.to_string ();
887 :
888 1 : rich_location r (line_table, trait.get_locus ());
889 1 : r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
890 1 : r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
891 1 : rust_error_at (r, ErrorCode::E0277,
892 : "the trait bound %<%s: %s%> is not satisfied",
893 2 : impl_type.to_string ().c_str (),
894 1 : sptref.get_name ().c_str ());
895 :
896 1 : return false;
897 1 : }
898 :
899 3659 : if (!super.validate_type_implements_super_traits (self, impl_type, trait))
900 : return false;
901 : }
902 :
903 : return true;
904 : }
905 :
906 : bool
907 3660 : TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
908 : HIR::Type &impl_type,
909 : HIR::Type &trait) const
910 : {
911 3660 : const auto &ptref = *get ();
912 3660 : auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
913 13065 : for (auto &elem : probed_bounds)
914 : {
915 13064 : auto &tref = *(elem.first);
916 13064 : if (ptref.is_equal (tref))
917 3660 : return true;
918 : }
919 :
920 : return false;
921 3660 : }
922 :
923 : // trait item reference
924 :
925 : const Resolver::TraitItemReference *
926 43549 : TypeBoundPredicateItem::get_raw_item () const
927 : {
928 43549 : return trait_item_ref;
929 : }
930 :
931 : bool
932 0 : TypeBoundPredicateItem::needs_implementation () const
933 : {
934 0 : return !get_raw_item ()->is_optional ();
935 : }
936 :
937 : location_t
938 5 : TypeBoundPredicateItem::get_locus () const
939 : {
940 5 : return get_raw_item ()->get_locus ();
941 : }
942 :
943 : // TypeBoundsMappings
944 :
945 87349062 : TypeBoundsMappings::TypeBoundsMappings (
946 87349062 : std::vector<TypeBoundPredicate> specified_bounds)
947 87349062 : : specified_bounds (specified_bounds)
948 87349062 : {}
949 :
950 : std::vector<TypeBoundPredicate> &
951 105576 : TypeBoundsMappings::get_specified_bounds ()
952 : {
953 105576 : return specified_bounds;
954 : }
955 :
956 : const std::vector<TypeBoundPredicate> &
957 85857838 : TypeBoundsMappings::get_specified_bounds () const
958 : {
959 85857838 : return specified_bounds;
960 : }
961 :
962 : TypeBoundPredicate
963 2407 : TypeBoundsMappings::lookup_predicate (DefId id)
964 : {
965 2589 : for (auto &b : specified_bounds)
966 : {
967 2756 : if (b.get_id () == id)
968 2392 : return b;
969 : }
970 15 : return TypeBoundPredicate::error ();
971 : }
972 :
973 : size_t
974 232621 : TypeBoundsMappings::num_specified_bounds () const
975 : {
976 232621 : return specified_bounds.size ();
977 : }
978 :
979 : std::string
980 30637 : TypeBoundsMappings::raw_bounds_as_string () const
981 : {
982 30637 : std::string buf;
983 31658 : for (size_t i = 0; i < specified_bounds.size (); i++)
984 : {
985 1021 : const TypeBoundPredicate &b = specified_bounds.at (i);
986 1021 : bool has_next = (i + 1) < specified_bounds.size ();
987 4070 : buf += b.as_string () + (has_next ? " + " : "");
988 : }
989 30637 : return buf;
990 : }
991 :
992 : std::string
993 29690 : TypeBoundsMappings::bounds_as_string () const
994 : {
995 59380 : return "bounds:[" + raw_bounds_as_string () + "]";
996 : }
997 :
998 : std::string
999 49533 : TypeBoundsMappings::raw_bounds_as_name () const
1000 : {
1001 49533 : std::string buf;
1002 99148 : for (size_t i = 0; i < specified_bounds.size (); i++)
1003 : {
1004 49615 : const TypeBoundPredicate &b = specified_bounds.at (i);
1005 49615 : bool has_next = (i + 1) < specified_bounds.size ();
1006 198354 : buf += b.as_name () + (has_next ? " + " : "");
1007 : }
1008 :
1009 49533 : return buf;
1010 : }
1011 :
1012 : void
1013 59978 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
1014 : {
1015 65771 : for (auto &bound : specified_bounds)
1016 : {
1017 35515 : bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
1018 5793 : if (same_trait_ref_p)
1019 59978 : return;
1020 : }
1021 :
1022 30256 : specified_bounds.push_back (predicate);
1023 : }
1024 :
1025 : } // namespace TyTy
1026 : } // namespace Rust
|