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 80226 : TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
30 80226 : : TypeCheckBase (), receiver (receiver)
31 80226 : {}
32 :
33 : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
34 80226 : TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
35 : {
36 80226 : TypeBoundsProbe probe (receiver);
37 80226 : probe.scan ();
38 80226 : return probe.trait_references;
39 80226 : }
40 :
41 : bool
42 82 : TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
43 : TraitReference *ref)
44 : {
45 82 : for (auto &bound : receiver->get_specified_bounds ())
46 : {
47 0 : const TraitReference *b = bound.get ();
48 0 : if (b->is_equal (*ref))
49 82 : return true;
50 : }
51 :
52 82 : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
53 82 : = Probe (receiver);
54 93 : for (auto &bound : bounds)
55 : {
56 91 : const TraitReference *b = bound.first;
57 91 : if (b->is_equal (*ref))
58 82 : return true;
59 : }
60 :
61 : return false;
62 82 : }
63 :
64 : bool
65 2521501 : 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 2521501 : if (!impl->has_trait_ref ())
72 : return true;
73 :
74 : // can be recursive trait resolution
75 2234012 : HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
76 2234012 : if (t == nullptr)
77 : return true;
78 :
79 2234012 : HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
80 2234012 : TyTy::BaseType *impl_type = nullptr;
81 2234012 : if (!query_type (impl_ty_id, &impl_type))
82 : return true;
83 :
84 2230985 : if (!types_compatable (TyTy::TyWithLocation (receiver),
85 2230985 : TyTy::TyWithLocation (impl_type), impl->get_locus (),
86 : false /*emit_errors*/, false /*check-bounds*/))
87 : return true;
88 :
89 347909 : possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
90 347909 : return true;
91 : }
92 :
93 : void
94 80226 : TypeBoundsProbe::scan ()
95 : {
96 80226 : std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
97 80226 : possible_trait_paths;
98 80226 : mappings.iterate_impl_blocks (
99 80226 : [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
100 2521501 : return process_impl_block (id, impl, possible_trait_paths);
101 : });
102 :
103 428135 : for (auto &path : possible_trait_paths)
104 : {
105 347909 : HIR::TypePath *trait_path = path.first;
106 347909 : TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
107 :
108 347909 : if (!trait_ref->is_error ())
109 347906 : trait_references.emplace_back (trait_ref, path.second);
110 : }
111 :
112 : // marker traits...
113 80226 : assemble_marker_builtins ();
114 :
115 : // add auto trait bounds
116 80244 : for (auto *auto_trait : mappings.get_auto_traits ())
117 18 : add_trait_bound (auto_trait);
118 80226 : }
119 :
120 : void
121 80226 : TypeBoundsProbe::assemble_marker_builtins ()
122 : {
123 80226 : 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 80226 : switch (raw->get_kind ())
134 : {
135 59083 : case TyTy::ARRAY:
136 59083 : case TyTy::REF:
137 59083 : case TyTy::POINTER:
138 59083 : case TyTy::PARAM:
139 59083 : case TyTy::FNDEF:
140 59083 : case TyTy::BOOL:
141 59083 : case TyTy::CHAR:
142 59083 : case TyTy::INT:
143 59083 : case TyTy::UINT:
144 59083 : case TyTy::FLOAT:
145 59083 : case TyTy::USIZE:
146 59083 : case TyTy::ISIZE:
147 59083 : case TyTy::INFER:
148 59083 : case TyTy::NEVER:
149 59083 : case TyTy::PLACEHOLDER:
150 59083 : case TyTy::PROJECTION:
151 59083 : case TyTy::OPAQUE:
152 59083 : assemble_builtin_candidate (LangItem::Kind::SIZED);
153 59083 : break;
154 :
155 279 : case TyTy::FNPTR:
156 279 : case TyTy::CLOSURE:
157 279 : assemble_builtin_candidate (LangItem::Kind::SIZED);
158 279 : assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
159 279 : assemble_builtin_candidate (LangItem::Kind::FN);
160 279 : assemble_builtin_candidate (LangItem::Kind::FN_MUT);
161 279 : break;
162 :
163 : // FIXME str and slice need to be moved and test cases updated
164 20601 : case TyTy::SLICE:
165 20601 : case TyTy::STR:
166 20601 : case TyTy::ADT:
167 20601 : case TyTy::TUPLE:
168 : // FIXME add extra checks
169 20601 : assemble_builtin_candidate (LangItem::Kind::SIZED);
170 20601 : break;
171 :
172 : case TyTy::CONST:
173 : case TyTy::DYNAMIC:
174 : case TyTy::ERROR:
175 : break;
176 : }
177 80226 : }
178 :
179 : void
180 79982 : TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
181 : {
182 79982 : auto trait_ref = TraitResolver::Resolve (*trait);
183 :
184 79982 : trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
185 79982 : }
186 :
187 : void
188 80800 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
189 : {
190 80800 : auto lang_item_defined = mappings.lookup_lang_item (lang_item);
191 80800 : if (!lang_item_defined)
192 836 : return;
193 79964 : DefId &id = lang_item_defined.value ();
194 :
195 79964 : auto defid = mappings.lookup_defid (id);
196 79964 : if (!defid)
197 : return;
198 79964 : auto item = defid.value ();
199 :
200 79964 : rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
201 79964 : HIR::Trait *trait = static_cast<HIR::Trait *> (item);
202 79964 : const TyTy::BaseType *raw = receiver->destructure ();
203 :
204 79964 : add_trait_bound (trait);
205 :
206 79964 : 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 6930 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
213 : {
214 6930 : return TraitResolver::Resolve (path);
215 : }
216 :
217 : TyTy::TypeBoundPredicate
218 43199 : 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 43199 : TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
224 43199 : bool already_resolved
225 43199 : = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
226 : &lookup);
227 43199 : if (already_resolved)
228 36269 : return lookup;
229 :
230 6930 : TraitReference *trait = resolve_trait_path (type_path);
231 6930 : if (trait->is_error ())
232 9 : return TyTy::TypeBoundPredicate::error ();
233 :
234 6921 : TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
235 6921 : HIR::GenericArgs args
236 6921 : = HIR::GenericArgs::create_empty (type_path.get_locus ());
237 :
238 6921 : auto &final_seg = type_path.get_final_segment ();
239 6921 : switch (final_seg.get_type ())
240 : {
241 879 : case HIR::TypePathSegment::SegmentType::GENERIC:
242 879 : {
243 879 : auto &final_generic_seg
244 : = static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
245 879 : if (final_generic_seg.has_generic_args ())
246 : {
247 879 : args = final_generic_seg.get_generic_args ();
248 879 : if (args.get_binding_args ().size () > 0
249 879 : && 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 6921 : if (associated_self.has_value ())
322 : {
323 6033 : std::vector<std::unique_ptr<HIR::Type>> type_args;
324 6033 : type_args.push_back (std::unique_ptr<HIR::Type> (
325 6033 : associated_self.value ().get ().clone_type ()));
326 6628 : for (auto &arg : args.get_type_args ())
327 : {
328 595 : type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
329 : }
330 :
331 18099 : args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
332 6033 : args.get_binding_args (), args.get_const_args (),
333 12066 : args.get_locus ());
334 6033 : }
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 6921 : if (!args.is_empty () || predicate.requires_generic_args ())
340 : {
341 : // this is applying generic arguments to a trait reference
342 6335 : predicate.apply_generic_arguments (&args, associated_self.has_value (),
343 : is_super_trait);
344 : }
345 :
346 6921 : context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
347 : predicate);
348 :
349 6921 : return predicate;
350 43199 : }
351 :
352 : } // namespace Resolver
353 :
354 : namespace TyTy {
355 :
356 21160 : TypeBoundPredicate::TypeBoundPredicate (
357 : const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
358 21160 : location_t locus)
359 42320 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
360 21160 : reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
361 21160 : error_flag (false), polarity (polarity),
362 63480 : super_traits (trait_reference.get_super_traits ())
363 : {
364 21160 : rust_assert (!trait_reference.get_trait_substs ().empty ());
365 :
366 21160 : substitutions.clear ();
367 45224 : for (const auto &p : trait_reference.get_trait_substs ())
368 24064 : substitutions.push_back (p.clone ());
369 :
370 : // we setup a dummy implict self argument
371 21160 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
372 21160 : used_arguments.get_mappings ().push_back (placeholder_self);
373 21160 : }
374 :
375 3942 : TypeBoundPredicate::TypeBoundPredicate (
376 : DefId reference, std::vector<SubstitutionParamMapping> subst,
377 3942 : BoundPolarity polarity, location_t locus)
378 7884 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
379 3942 : reference (reference), locus (locus), error_flag (false),
380 7884 : polarity (polarity)
381 : {
382 3942 : rust_assert (!subst.empty ());
383 :
384 3942 : substitutions.clear ();
385 8536 : for (const auto &p : subst)
386 4594 : substitutions.push_back (p.clone ());
387 :
388 : // we setup a dummy implict self argument
389 3942 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
390 3942 : used_arguments.get_mappings ().push_back (placeholder_self);
391 3942 : }
392 :
393 119238 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
394 238476 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
395 119238 : reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
396 119238 : polarity (BoundPolarity::RegularBound)
397 119238 : {}
398 :
399 82571549 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
400 165143098 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
401 82571549 : reference (other.reference), locus (other.locus),
402 82571549 : error_flag (other.error_flag), polarity (other.polarity),
403 165143098 : super_traits (other.super_traits)
404 : {
405 82571549 : substitutions.clear ();
406 174746485 : for (const auto &p : other.get_substs ())
407 92174936 : substitutions.push_back (p.clone ());
408 :
409 82571549 : std::vector<SubstitutionArg> mappings;
410 166809250 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
411 : {
412 84237701 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
413 84237701 : SubstitutionArg arg (oa);
414 84237701 : mappings.push_back (std::move (arg));
415 : }
416 :
417 : // we need to remap the argument mappings based on this copied constructor
418 82571549 : std::vector<SubstitutionArg> copied_arg_mappings;
419 82571549 : size_t i = 0;
420 166809250 : for (const auto &m : other.used_arguments.get_mappings ())
421 : {
422 84237701 : TyTy::BaseType *argument
423 84237701 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
424 84237701 : SubstitutionArg c (&substitutions.at (i++), argument);
425 84237701 : copied_arg_mappings.push_back (std::move (c));
426 : }
427 :
428 82571549 : used_arguments
429 82571549 : = SubstitutionArgumentMappings (copied_arg_mappings,
430 : other.used_arguments.get_binding_args (),
431 : other.used_arguments.get_regions (),
432 165143098 : other.used_arguments.get_locus ());
433 82571549 : }
434 :
435 : TypeBoundPredicate &
436 90715 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
437 : {
438 90715 : reference = other.reference;
439 90715 : locus = other.locus;
440 90715 : error_flag = other.error_flag;
441 90715 : polarity = other.polarity;
442 90715 : used_arguments = SubstitutionArgumentMappings::empty ();
443 :
444 90715 : substitutions.clear ();
445 221975 : for (const auto &p : other.get_substs ())
446 131260 : substitutions.push_back (p.clone ());
447 :
448 90715 : if (other.is_error ())
449 : return *this;
450 :
451 80010 : std::vector<SubstitutionArg> mappings;
452 211241 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
453 : {
454 131231 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
455 131231 : SubstitutionArg arg (oa);
456 131231 : mappings.push_back (std::move (arg));
457 : }
458 :
459 : // we need to remap the argument mappings based on this copied constructor
460 80010 : std::vector<SubstitutionArg> copied_arg_mappings;
461 80010 : size_t i = 0;
462 211241 : for (const auto &m : other.used_arguments.get_mappings ())
463 : {
464 131231 : TyTy::BaseType *argument
465 131231 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
466 :
467 131231 : copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
468 : }
469 :
470 80010 : used_arguments
471 80010 : = SubstitutionArgumentMappings (copied_arg_mappings,
472 : other.used_arguments.get_binding_args (),
473 : other.used_arguments.get_regions (),
474 160020 : other.used_arguments.get_locus ());
475 80010 : super_traits = other.super_traits;
476 :
477 80010 : return *this;
478 80010 : }
479 :
480 : TypeBoundPredicate
481 119238 : TypeBoundPredicate::error ()
482 : {
483 119238 : return TypeBoundPredicate (mark_is_error ());
484 : }
485 :
486 : std::string
487 1184 : TypeBoundPredicate::as_string () const
488 : {
489 1184 : return get ()->as_string () + subst_as_string ();
490 : }
491 :
492 : std::string
493 53514 : TypeBoundPredicate::as_name () const
494 : {
495 53514 : return get ()->get_name () + subst_as_string ();
496 : }
497 :
498 : const Resolver::TraitReference *
499 422390 : TypeBoundPredicate::get () const
500 : {
501 422390 : auto context = Resolver::TypeCheckContext::get ();
502 :
503 422390 : Resolver::TraitReference *ref = nullptr;
504 422390 : bool ok = context->lookup_trait_reference (reference, &ref);
505 422390 : rust_assert (ok);
506 :
507 422390 : return ref;
508 : }
509 :
510 : std::string
511 8252 : TypeBoundPredicate::get_name () const
512 : {
513 8252 : return get ()->get_name ();
514 : }
515 :
516 : bool
517 249 : TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
518 : {
519 249 : const Resolver::TraitReference *trait = get ();
520 249 : rust_assert (trait != nullptr);
521 249 : return trait->is_object_safe (emit_error, locus);
522 : }
523 :
524 : void
525 6400 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
526 : bool has_associated_self,
527 : bool is_super_trait)
528 : {
529 6400 : rust_assert (!substitutions.empty ());
530 6400 : if (has_associated_self)
531 : {
532 6033 : used_arguments = SubstitutionArgumentMappings::empty ();
533 : }
534 : else
535 : {
536 : // we need to get the substitutions argument mappings but also remember
537 : // that we have an implicit Self argument which we must be careful to
538 : // respect
539 367 : rust_assert (!used_arguments.is_empty ());
540 : }
541 :
542 : // now actually perform a substitution
543 6400 : auto args = get_mappings_from_generic_args (
544 : *generic_args,
545 6400 : Resolver::TypeCheckContext::get ()->regions_from_generic_args (
546 12800 : *generic_args));
547 :
548 6400 : apply_argument_mappings (args, is_super_trait);
549 6400 : }
550 :
551 : void
552 10433 : TypeBoundPredicate::apply_argument_mappings (
553 : SubstitutionArgumentMappings &arguments, bool is_super_trait)
554 : {
555 10433 : used_arguments = arguments;
556 10433 : error_flag |= used_arguments.is_error ();
557 10433 : auto &subst_mappings = used_arguments;
558 :
559 10433 : bool substs_need_bounds_check = !is_super_trait;
560 23866 : for (auto &sub : get_substs ())
561 : {
562 13433 : SubstitutionArg arg = SubstitutionArg::error ();
563 13433 : bool ok
564 13433 : = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
565 13433 : if (ok && arg.get_tyty () != nullptr)
566 12983 : sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
567 : substs_need_bounds_check);
568 : }
569 :
570 : // Associated type binding args (Iterator<Item = i32>) are consumed
571 : // by BaseType::satisfies_bound at check time
572 14458 : for (auto &super_trait : super_traits)
573 : {
574 4025 : auto adjusted
575 : = super_trait.adjust_mappings_for_this (used_arguments,
576 4025 : true /*trait mode*/);
577 4025 : super_trait.apply_argument_mappings (adjusted, is_super_trait);
578 4025 : }
579 10433 : }
580 :
581 : bool
582 0 : TypeBoundPredicate::contains_item (const std::string &search) const
583 : {
584 0 : auto trait_ref = get ();
585 0 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
586 0 : return trait_ref->lookup_trait_item (search, &trait_item_ref);
587 : }
588 :
589 : tl::optional<TypeBoundPredicateItem>
590 26406 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
591 : {
592 26406 : auto trait_ref = get ();
593 26406 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
594 26406 : if (trait_ref->lookup_trait_item (search, &trait_item_ref,
595 : false /*lookup supers*/))
596 24941 : return TypeBoundPredicateItem (*this, trait_item_ref);
597 :
598 1581 : for (auto &super_trait : super_traits)
599 : {
600 238 : auto lookup = super_trait.lookup_associated_item (search);
601 238 : if (lookup.has_value ())
602 122 : return lookup;
603 238 : }
604 :
605 1343 : return tl::nullopt;
606 : }
607 :
608 31158 : TypeBoundPredicateItem::TypeBoundPredicateItem (
609 : const TypeBoundPredicate parent,
610 31158 : const Resolver::TraitItemReference *trait_item_ref)
611 31158 : : parent (parent), trait_item_ref (trait_item_ref)
612 31158 : {}
613 :
614 33867 : TypeBoundPredicateItem::TypeBoundPredicateItem (
615 33867 : const TypeBoundPredicateItem &other)
616 33867 : : parent (other.parent), trait_item_ref (other.trait_item_ref)
617 33867 : {}
618 :
619 : TypeBoundPredicateItem &
620 6139 : TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
621 : {
622 6139 : parent = other.parent;
623 6139 : trait_item_ref = other.trait_item_ref;
624 :
625 6139 : return *this;
626 : }
627 :
628 : TypeBoundPredicateItem
629 6144 : TypeBoundPredicateItem::error ()
630 : {
631 6144 : return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
632 : }
633 :
634 : bool
635 6241 : TypeBoundPredicateItem::is_error () const
636 : {
637 6241 : return parent.is_error () || trait_item_ref == nullptr;
638 : }
639 :
640 : const TypeBoundPredicate *
641 1312 : TypeBoundPredicateItem::get_parent () const
642 : {
643 1312 : return &parent;
644 : }
645 :
646 : tl::optional<TypeBoundPredicateItem>
647 6078 : TypeBoundPredicate::lookup_associated_item (
648 : const Resolver::TraitItemReference *ref) const
649 : {
650 6078 : return lookup_associated_item (ref->get_identifier ());
651 : }
652 :
653 : BaseType *
654 8295 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
655 : {
656 8295 : auto ctx = Resolver::TypeCheckContext::get ();
657 :
658 8295 : TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
659 8295 : if (parent.get_substitution_arguments ().is_empty ())
660 : return trait_item_tyty;
661 :
662 : // set up the self mapping
663 8295 : SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
664 8295 : rust_assert (!gargs.is_empty ());
665 :
666 : // The associated-type projection we are rebasing is stored in trait
667 : // coordinates
668 : //
669 : // Self/X for trait SliceIndex<X>
670 : //
671 : // The predicate's own SubstitutionParamMappings may have already been
672 : // mutated by SubstitutionParamMapping::fill_param_ty when the bound is a
673 : // where-clause like I: SliceIndex<[T]>: substituting Self with the
674 : // ParamType I rebinds the predicate's first param from Self to I.
675 : // Building adjusted_mappings from those renamed mappings would make
676 : // name-based lookup (get_argument_for_symbol) miss the trait's Self/X
677 : // symbols inside the projection.
678 8295 : const auto &trait_substs = parent.get ()->get_trait_substs ();
679 8295 : rust_assert (gargs.get_mappings ().size () <= trait_substs.size ());
680 :
681 8295 : std::vector<SubstitutionArg> adjusted_mappings;
682 20513 : for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
683 : {
684 12218 : auto &mapping = gargs.get_mappings ().at (i);
685 :
686 12218 : bool is_implicit_self = i == 0;
687 12218 : TyTy::BaseType *argument
688 12218 : = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
689 :
690 12218 : adjusted_mappings.emplace_back (&trait_substs.at (i), argument);
691 : }
692 :
693 8295 : SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
694 : gargs.get_regions (),
695 : gargs.get_locus (),
696 8295 : gargs.get_subst_cb (),
697 8295 : true /* trait-mode-flag */);
698 8295 : TyTy::BaseType *res
699 8295 : = Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
700 :
701 8295 : if (res != trait_item_tyty)
702 : {
703 8295 : auto &mappings = Analysis::Mappings::get ();
704 8295 : HirId fresh = mappings.get_next_hir_id ();
705 8295 : res->set_ref (fresh);
706 8295 : res->set_ty_ref (fresh);
707 8295 : ctx->insert_implicit_type (fresh, res);
708 : }
709 :
710 8295 : return res;
711 8295 : }
712 : bool
713 155300 : TypeBoundPredicate::is_error () const
714 : {
715 155300 : auto context = Resolver::TypeCheckContext::get ();
716 :
717 155300 : Resolver::TraitReference *ref = nullptr;
718 155300 : bool ok = context->lookup_trait_reference (reference, &ref);
719 :
720 155300 : return !ok || error_flag;
721 : }
722 :
723 : BaseType *
724 53287 : TypeBoundPredicate::handle_substitions (
725 : SubstitutionArgumentMappings &subst_mappings)
726 : {
727 117112 : for (auto &sub : get_substs ())
728 : {
729 63825 : if (sub.get_param_ty () == nullptr)
730 0 : continue;
731 :
732 63825 : auto p = sub.get_param_ty ();
733 63825 : BaseType *r = p->resolve ();
734 63825 : BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
735 :
736 63825 : p->set_ty_ref (s->get_ty_ref ());
737 : }
738 :
739 : // FIXME more error handling at some point
740 : // used_arguments = subst_mappings;
741 : // error_flag |= used_arguments.is_error ();
742 :
743 53287 : return nullptr;
744 : }
745 :
746 : bool
747 588 : TypeBoundPredicate::requires_generic_args () const
748 : {
749 588 : if (is_error ())
750 : return false;
751 :
752 588 : return substitutions.size () > 1;
753 : }
754 :
755 : bool
756 0 : TypeBoundPredicate::contains_associated_types () const
757 : {
758 0 : return get_num_associated_bindings () > 0;
759 : }
760 :
761 : size_t
762 194 : TypeBoundPredicate::get_num_associated_bindings () const
763 : {
764 194 : size_t count = 0;
765 :
766 194 : get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
767 546 : for (const auto &trait_item : ref.get_trait_items ())
768 : {
769 352 : bool is_associated_type
770 352 : = trait_item.get_trait_item_type ()
771 352 : == Resolver::TraitItemReference::TraitItemType::TYPE;
772 352 : if (is_associated_type)
773 194 : count++;
774 : }
775 194 : });
776 :
777 194 : return count;
778 : }
779 :
780 : void
781 194 : TypeBoundPredicate::get_trait_hierachy (
782 : std::function<void (const Resolver::TraitReference &)> callback) const
783 : {
784 194 : auto trait_ref = get ();
785 194 : callback (*trait_ref);
786 :
787 194 : for (auto &super : super_traits)
788 : {
789 0 : const auto &super_trait_ref = *super.get ();
790 0 : callback (super_trait_ref);
791 0 : super.get_trait_hierachy (callback);
792 : }
793 194 : }
794 :
795 : TypeBoundPredicateItem
796 97 : TypeBoundPredicate::lookup_associated_type (const std::string &search)
797 : {
798 97 : tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search);
799 :
800 : // only need to check that it is infact an associated type because other
801 : // wise if it was not found it will just be an error node anyway
802 97 : if (item.has_value ())
803 : {
804 97 : const auto raw = item->get_raw_item ();
805 97 : if (raw->get_trait_item_type ()
806 : != Resolver::TraitItemReference::TraitItemType::TYPE)
807 0 : return TypeBoundPredicateItem::error ();
808 : }
809 97 : return item.value ();
810 97 : }
811 :
812 : std::vector<TypeBoundPredicateItem>
813 0 : TypeBoundPredicate::get_associated_type_items ()
814 : {
815 0 : std::vector<TypeBoundPredicateItem> items;
816 0 : auto trait_ref = get ();
817 0 : for (const auto &trait_item : trait_ref->get_trait_items ())
818 : {
819 0 : bool is_associated_type
820 0 : = trait_item.get_trait_item_type ()
821 0 : == Resolver::TraitItemReference::TraitItemType::TYPE;
822 0 : if (is_associated_type)
823 0 : items.emplace_back (*this, &trait_item);
824 : }
825 0 : return items;
826 : }
827 :
828 : bool
829 19269 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
830 : {
831 : // check they match the same trait reference
832 34888 : if (reference != other.reference)
833 : return false;
834 :
835 : // check that the generics match
836 3655 : if (get_num_substitutions () != other.get_num_substitutions ())
837 : return false;
838 :
839 : // then match the generics applied
840 8359 : for (size_t i = 0; i < get_num_substitutions (); i++)
841 : {
842 4709 : SubstitutionParamMapping a = substitutions.at (i);
843 4709 : SubstitutionParamMapping b = other.substitutions.at (i);
844 :
845 4709 : auto ap = a.get_param_ty ();
846 4709 : auto bp = b.get_param_ty ();
847 :
848 4709 : BaseType *apd = ap->destructure ();
849 4709 : BaseType *bpd = bp->destructure ();
850 :
851 4709 : if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
852 4709 : TyTy::TyWithLocation (bpd),
853 : UNKNOWN_LOCATION, false))
854 5 : return false;
855 : }
856 :
857 : return true;
858 : }
859 :
860 : bool
861 8381 : TypeBoundPredicate::validate_type_implements_super_traits (
862 : TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
863 : {
864 8381 : if (get_polarity () != BoundPolarity::RegularBound)
865 : return true;
866 :
867 8376 : auto &ptref = *get ();
868 12038 : for (auto &super : super_traits)
869 : {
870 3663 : if (super.get_polarity () != BoundPolarity::RegularBound)
871 0 : continue;
872 :
873 3663 : if (!super.validate_type_implements_this (self, impl_type, trait))
874 : {
875 1 : auto &sptref = *super.get ();
876 :
877 : // emit error
878 1 : std::string fixit1
879 1 : = "required by this bound in: " + ptref.get_name ();
880 2 : std::string fixit2 = "the trait " + sptref.get_name ()
881 2 : + " is not implemented for "
882 2 : + impl_type.to_string ();
883 :
884 1 : rich_location r (line_table, trait.get_locus ());
885 1 : r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
886 1 : r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
887 1 : rust_error_at (r, ErrorCode::E0277,
888 : "the trait bound %<%s: %s%> is not satisfied",
889 2 : impl_type.to_string ().c_str (),
890 1 : sptref.get_name ().c_str ());
891 :
892 1 : return false;
893 1 : }
894 :
895 3662 : if (!super.validate_type_implements_super_traits (self, impl_type, trait))
896 : return false;
897 : }
898 :
899 : return true;
900 : }
901 :
902 : bool
903 3663 : TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
904 : HIR::Type &impl_type,
905 : HIR::Type &trait) const
906 : {
907 3663 : const auto &ptref = *get ();
908 3663 : auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
909 13073 : for (auto &elem : probed_bounds)
910 : {
911 13072 : auto &tref = *(elem.first);
912 13072 : if (ptref.is_equal (tref))
913 3663 : return true;
914 : }
915 :
916 : return false;
917 3663 : }
918 :
919 : // trait item reference
920 :
921 : const Resolver::TraitItemReference *
922 39465 : TypeBoundPredicateItem::get_raw_item () const
923 : {
924 39465 : return trait_item_ref;
925 : }
926 :
927 : bool
928 0 : TypeBoundPredicateItem::needs_implementation () const
929 : {
930 0 : return !get_raw_item ()->is_optional ();
931 : }
932 :
933 : location_t
934 5 : TypeBoundPredicateItem::get_locus () const
935 : {
936 5 : return get_raw_item ()->get_locus ();
937 : }
938 :
939 : // TypeBoundsMappings
940 :
941 96787050 : TypeBoundsMappings::TypeBoundsMappings (
942 96787050 : std::vector<TypeBoundPredicate> specified_bounds)
943 96787050 : : specified_bounds (specified_bounds)
944 96787050 : {}
945 :
946 : std::vector<TypeBoundPredicate> &
947 132694 : TypeBoundsMappings::get_specified_bounds ()
948 : {
949 132694 : return specified_bounds;
950 : }
951 :
952 : const std::vector<TypeBoundPredicate> &
953 95150629 : TypeBoundsMappings::get_specified_bounds () const
954 : {
955 95150629 : return specified_bounds;
956 : }
957 :
958 : TypeBoundPredicate
959 0 : TypeBoundsMappings::lookup_predicate (DefId id)
960 : {
961 0 : for (auto &b : specified_bounds)
962 : {
963 0 : if (b.get_id () == id)
964 0 : return b;
965 : }
966 0 : return TypeBoundPredicate::error ();
967 : }
968 :
969 : size_t
970 239532 : TypeBoundsMappings::num_specified_bounds () const
971 : {
972 239532 : return specified_bounds.size ();
973 : }
974 :
975 : std::string
976 32751 : TypeBoundsMappings::raw_bounds_as_string () const
977 : {
978 32751 : std::string buf;
979 33927 : for (size_t i = 0; i < specified_bounds.size (); i++)
980 : {
981 1176 : const TypeBoundPredicate &b = specified_bounds.at (i);
982 1176 : bool has_next = (i + 1) < specified_bounds.size ();
983 4690 : buf += b.as_string () + (has_next ? " + " : "");
984 : }
985 32751 : return buf;
986 : }
987 :
988 : std::string
989 31649 : TypeBoundsMappings::bounds_as_string () const
990 : {
991 63298 : return "bounds:[" + raw_bounds_as_string () + "]";
992 : }
993 :
994 : std::string
995 53432 : TypeBoundsMappings::raw_bounds_as_name () const
996 : {
997 53432 : std::string buf;
998 106946 : for (size_t i = 0; i < specified_bounds.size (); i++)
999 : {
1000 53514 : const TypeBoundPredicate &b = specified_bounds.at (i);
1001 53514 : bool has_next = (i + 1) < specified_bounds.size ();
1002 213950 : buf += b.as_name () + (has_next ? " + " : "");
1003 : }
1004 :
1005 53432 : return buf;
1006 : }
1007 :
1008 : void
1009 68329 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
1010 : {
1011 75908 : for (auto &bound : specified_bounds)
1012 : {
1013 40311 : bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
1014 7579 : if (same_trait_ref_p)
1015 68329 : return;
1016 : }
1017 :
1018 35597 : specified_bounds.push_back (predicate);
1019 : }
1020 :
1021 : } // namespace TyTy
1022 : } // namespace Rust
|