Branch data Line data Source code
1 : : // Copyright (C) 2021-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-hir-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 : 66494 : TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
30 : 66494 : : TypeCheckBase (), receiver (receiver)
31 : 66494 : {}
32 : :
33 : : std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
34 : 66494 : TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
35 : : {
36 : 66494 : TypeBoundsProbe probe (receiver);
37 : 66494 : probe.scan ();
38 : 66494 : return probe.trait_references;
39 : 66494 : }
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 : 2002001 : 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 : 2002001 : if (!impl->has_trait_ref ())
72 : : return true;
73 : :
74 : : // can be recursive trait resolution
75 : 1782604 : HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
76 : 1782604 : if (t == nullptr)
77 : : return true;
78 : :
79 : 1782604 : HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
80 : 1782604 : TyTy::BaseType *impl_type = nullptr;
81 : 1782604 : if (!query_type (impl_ty_id, &impl_type))
82 : : return true;
83 : :
84 : 1779593 : if (!types_compatable (TyTy::TyWithLocation (receiver),
85 : 1779593 : TyTy::TyWithLocation (impl_type), impl->get_locus (),
86 : : false /*emit_errors*/, false /*check-bounds*/))
87 : : return true;
88 : :
89 : 283655 : possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
90 : 283655 : return true;
91 : : }
92 : :
93 : : void
94 : 66494 : TypeBoundsProbe::scan ()
95 : : {
96 : 66494 : std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
97 : 66494 : possible_trait_paths;
98 : 66494 : mappings.iterate_impl_blocks (
99 : 66494 : [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
100 : 2002001 : return process_impl_block (id, impl, possible_trait_paths);
101 : : });
102 : :
103 : 350149 : for (auto &path : possible_trait_paths)
104 : : {
105 : 283655 : HIR::TypePath *trait_path = path.first;
106 : 283655 : TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
107 : :
108 : 283655 : if (!trait_ref->is_error ())
109 : 283655 : trait_references.emplace_back (trait_ref, path.second);
110 : : }
111 : :
112 : : // marker traits...
113 : 66494 : assemble_marker_builtins ();
114 : :
115 : : // add auto trait bounds
116 : 66512 : for (auto *auto_trait : mappings.get_auto_traits ())
117 : 18 : add_trait_bound (auto_trait);
118 : 66494 : }
119 : :
120 : : void
121 : 66494 : TypeBoundsProbe::assemble_marker_builtins ()
122 : : {
123 : 66494 : 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 : 66494 : switch (raw->get_kind ())
134 : : {
135 : 50680 : case TyTy::ARRAY:
136 : 50680 : case TyTy::REF:
137 : 50680 : case TyTy::POINTER:
138 : 50680 : case TyTy::PARAM:
139 : 50680 : case TyTy::FNDEF:
140 : 50680 : case TyTy::BOOL:
141 : 50680 : case TyTy::CHAR:
142 : 50680 : case TyTy::INT:
143 : 50680 : case TyTy::UINT:
144 : 50680 : case TyTy::FLOAT:
145 : 50680 : case TyTy::USIZE:
146 : 50680 : case TyTy::ISIZE:
147 : 50680 : case TyTy::INFER:
148 : 50680 : case TyTy::NEVER:
149 : 50680 : case TyTy::PLACEHOLDER:
150 : 50680 : case TyTy::PROJECTION:
151 : 50680 : case TyTy::OPAQUE:
152 : 50680 : assemble_builtin_candidate (LangItem::Kind::SIZED);
153 : 50680 : 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 : 15410 : case TyTy::SLICE:
165 : 15410 : case TyTy::STR:
166 : 15410 : case TyTy::ADT:
167 : 15410 : case TyTy::TUPLE:
168 : : // FIXME add extra checks
169 : 15410 : assemble_builtin_candidate (LangItem::Kind::SIZED);
170 : 15410 : break;
171 : :
172 : : case TyTy::CONST:
173 : : case TyTy::DYNAMIC:
174 : : case TyTy::ERROR:
175 : : break;
176 : : }
177 : 66494 : }
178 : :
179 : : void
180 : 66201 : TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
181 : : {
182 : 66201 : auto trait_ref = TraitResolver::Resolve (*trait);
183 : :
184 : 66201 : trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
185 : 66201 : }
186 : :
187 : : void
188 : 66790 : TypeBoundsProbe::assemble_builtin_candidate (LangItem::Kind lang_item)
189 : : {
190 : 66790 : auto lang_item_defined = mappings.lookup_lang_item (lang_item);
191 : 66790 : if (!lang_item_defined)
192 : 607 : return;
193 : 66183 : DefId &id = lang_item_defined.value ();
194 : :
195 : 66183 : auto defid = mappings.lookup_defid (id);
196 : 66183 : if (!defid)
197 : : return;
198 : 66183 : auto item = defid.value ();
199 : :
200 : 66183 : rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
201 : 66183 : HIR::Trait *trait = static_cast<HIR::Trait *> (item);
202 : 66183 : const TyTy::BaseType *raw = receiver->destructure ();
203 : :
204 : 66183 : add_trait_bound (trait);
205 : :
206 : 66183 : 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 : 6745 : TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
213 : : {
214 : 6745 : return TraitResolver::Resolve (path);
215 : : }
216 : :
217 : : TyTy::TypeBoundPredicate
218 : 38114 : 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 : 38114 : TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
224 : 38114 : bool already_resolved
225 : 38114 : = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
226 : : &lookup);
227 : 38114 : if (already_resolved)
228 : 31369 : return lookup;
229 : :
230 : 6745 : TraitReference *trait = resolve_trait_path (type_path);
231 : 6745 : if (trait->is_error ())
232 : 12 : return TyTy::TypeBoundPredicate::error ();
233 : :
234 : 6733 : TyTy::TypeBoundPredicate predicate (*trait, polarity, type_path.get_locus ());
235 : 6733 : HIR::GenericArgs args
236 : 6733 : = HIR::GenericArgs::create_empty (type_path.get_locus ());
237 : :
238 : 6733 : auto &final_seg = type_path.get_final_segment ();
239 : 6733 : 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 : 6733 : if (associated_self.has_value ())
322 : : {
323 : 5935 : std::vector<std::unique_ptr<HIR::Type>> type_args;
324 : 5935 : type_args.push_back (std::unique_ptr<HIR::Type> (
325 : 5935 : associated_self.value ().get ().clone_type ()));
326 : 6524 : 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 : 17805 : args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
332 : 5935 : args.get_binding_args (), args.get_const_args (),
333 : 11870 : args.get_locus ());
334 : 5935 : }
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 : 6733 : if (!args.is_empty () || predicate.requires_generic_args ())
340 : : {
341 : : // this is applying generic arguments to a trait reference
342 : 6209 : predicate.apply_generic_arguments (&args, associated_self.has_value (),
343 : : is_super_trait);
344 : : }
345 : :
346 : 6733 : context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
347 : : predicate);
348 : :
349 : 6733 : return predicate;
350 : 38114 : }
351 : :
352 : : } // namespace Resolver
353 : :
354 : : namespace TyTy {
355 : :
356 : 20175 : TypeBoundPredicate::TypeBoundPredicate (
357 : : const Resolver::TraitReference &trait_reference, BoundPolarity polarity,
358 : 20175 : location_t locus)
359 : 40350 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
360 : 20175 : reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
361 : 20175 : error_flag (false), polarity (polarity),
362 : 60525 : super_traits (trait_reference.get_super_traits ())
363 : : {
364 : 20175 : rust_assert (!trait_reference.get_trait_substs ().empty ());
365 : :
366 : 20175 : substitutions.clear ();
367 : 43242 : for (const auto &p : trait_reference.get_trait_substs ())
368 : 23067 : substitutions.push_back (p.clone ());
369 : :
370 : : // we setup a dummy implict self argument
371 : 20175 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
372 : 20175 : used_arguments.get_mappings ().push_back (placeholder_self);
373 : 20175 : }
374 : :
375 : 3678 : TypeBoundPredicate::TypeBoundPredicate (
376 : : DefId reference, std::vector<SubstitutionParamMapping> subst,
377 : 3678 : BoundPolarity polarity, location_t locus)
378 : 7356 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
379 : 3678 : reference (reference), locus (locus), error_flag (false),
380 : 7356 : polarity (polarity)
381 : : {
382 : 3678 : rust_assert (!subst.empty ());
383 : :
384 : 3678 : substitutions.clear ();
385 : 8005 : for (const auto &p : subst)
386 : 4327 : substitutions.push_back (p.clone ());
387 : :
388 : : // we setup a dummy implict self argument
389 : 3678 : SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
390 : 3678 : used_arguments.get_mappings ().push_back (placeholder_self);
391 : 3678 : }
392 : :
393 : 108704 : TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
394 : 217408 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
395 : 108704 : reference (UNKNOWN_DEFID), locus (UNDEF_LOCATION), error_flag (true),
396 : 108704 : polarity (BoundPolarity::RegularBound)
397 : 108704 : {}
398 : :
399 : 73862015 : TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
400 : 147724030 : : SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
401 : 73862015 : reference (other.reference), locus (other.locus),
402 : 73862015 : error_flag (other.error_flag), polarity (other.polarity),
403 : 147724030 : super_traits (other.super_traits)
404 : : {
405 : 73862015 : substitutions.clear ();
406 : 157187091 : for (const auto &p : other.get_substs ())
407 : 83325076 : substitutions.push_back (p.clone ());
408 : :
409 : 73862015 : std::vector<SubstitutionArg> mappings;
410 : 149365369 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
411 : : {
412 : 75503354 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
413 : 75503354 : SubstitutionArg arg (oa);
414 : 75503354 : mappings.push_back (std::move (arg));
415 : : }
416 : :
417 : : // we need to remap the argument mappings based on this copied constructor
418 : 73862015 : std::vector<SubstitutionArg> copied_arg_mappings;
419 : 73862015 : size_t i = 0;
420 : 149365369 : for (const auto &m : other.used_arguments.get_mappings ())
421 : : {
422 : 75503354 : TyTy::BaseType *argument
423 : 75503354 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
424 : 75503354 : SubstitutionArg c (&substitutions.at (i++), argument);
425 : 75503354 : copied_arg_mappings.push_back (std::move (c));
426 : : }
427 : :
428 : 73862015 : used_arguments
429 : 73862015 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
430 : : other.used_arguments.get_regions (),
431 : 147724030 : other.used_arguments.get_locus ());
432 : 73862015 : }
433 : :
434 : : TypeBoundPredicate &
435 : 81070 : TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
436 : : {
437 : 81070 : reference = other.reference;
438 : 81070 : locus = other.locus;
439 : 81070 : error_flag = other.error_flag;
440 : 81070 : polarity = other.polarity;
441 : 81070 : used_arguments = SubstitutionArgumentMappings::empty ();
442 : :
443 : 81070 : substitutions.clear ();
444 : 199783 : for (const auto &p : other.get_substs ())
445 : 118713 : substitutions.push_back (p.clone ());
446 : :
447 : 81070 : if (other.is_error ())
448 : : return *this;
449 : :
450 : 71932 : std::vector<SubstitutionArg> mappings;
451 : 190634 : for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
452 : : {
453 : 118702 : const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
454 : 118702 : SubstitutionArg arg (oa);
455 : 118702 : mappings.push_back (std::move (arg));
456 : : }
457 : :
458 : : // we need to remap the argument mappings based on this copied constructor
459 : 71932 : std::vector<SubstitutionArg> copied_arg_mappings;
460 : 71932 : size_t i = 0;
461 : 190634 : for (const auto &m : other.used_arguments.get_mappings ())
462 : : {
463 : 118702 : TyTy::BaseType *argument
464 : 118702 : = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
465 : :
466 : 118702 : copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
467 : : }
468 : :
469 : 71932 : used_arguments
470 : 71932 : = SubstitutionArgumentMappings (copied_arg_mappings, {},
471 : : other.used_arguments.get_regions (),
472 : 143864 : other.used_arguments.get_locus ());
473 : 71932 : super_traits = other.super_traits;
474 : :
475 : 71932 : return *this;
476 : 71932 : }
477 : :
478 : : TypeBoundPredicate
479 : 108704 : TypeBoundPredicate::error ()
480 : : {
481 : 108704 : return TypeBoundPredicate (mark_is_error ());
482 : : }
483 : :
484 : : std::string
485 : 3264 : TypeBoundPredicate::as_string () const
486 : : {
487 : 3264 : 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 : 362820 : TypeBoundPredicate::get () const
498 : : {
499 : 362820 : auto context = Resolver::TypeCheckContext::get ();
500 : :
501 : 362820 : Resolver::TraitReference *ref = nullptr;
502 : 362820 : bool ok = context->lookup_trait_reference (reference, &ref);
503 : 362820 : rust_assert (ok);
504 : :
505 : 362820 : return ref;
506 : : }
507 : :
508 : : std::string
509 : 8534 : TypeBoundPredicate::get_name () const
510 : : {
511 : 8534 : 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 : 6274 : TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
524 : : bool has_associated_self,
525 : : bool is_super_trait)
526 : : {
527 : 6274 : rust_assert (!substitutions.empty ());
528 : 6274 : if (has_associated_self)
529 : : {
530 : 5935 : 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 : 6274 : auto args = get_mappings_from_generic_args (
542 : : *generic_args,
543 : 6274 : Resolver::TypeCheckContext::get ()->regions_from_generic_args (
544 : 12548 : *generic_args));
545 : :
546 : 6274 : apply_argument_mappings (args, is_super_trait);
547 : 6274 : }
548 : :
549 : : void
550 : 10301 : TypeBoundPredicate::apply_argument_mappings (
551 : : SubstitutionArgumentMappings &arguments, bool is_super_trait)
552 : : {
553 : 10301 : used_arguments = arguments;
554 : 10301 : error_flag |= used_arguments.is_error ();
555 : 10301 : auto &subst_mappings = used_arguments;
556 : :
557 : 10301 : bool substs_need_bounds_check = !is_super_trait;
558 : 23593 : for (auto &sub : get_substs ())
559 : : {
560 : 13292 : SubstitutionArg arg = SubstitutionArg::error ();
561 : 13292 : bool ok
562 : 13292 : = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
563 : 13292 : if (ok && arg.get_tyty () != nullptr)
564 : 12872 : sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
565 : : substs_need_bounds_check);
566 : : }
567 : :
568 : : // associated argument mappings
569 : 10381 : 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 : 14320 : 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 : 10301 : }
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 : 24732 : TypeBoundPredicate::lookup_associated_item (const std::string &search) const
603 : : {
604 : 24732 : auto trait_ref = get ();
605 : 24732 : const Resolver::TraitItemReference *trait_item_ref = nullptr;
606 : 24732 : if (trait_ref->lookup_trait_item (search, &trait_item_ref,
607 : : false /*lookup supers*/))
608 : 23252 : return TypeBoundPredicateItem (*this, trait_item_ref);
609 : :
610 : 1596 : 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 : 1360 : return tl::nullopt;
618 : : }
619 : :
620 : 28726 : TypeBoundPredicateItem::TypeBoundPredicateItem (
621 : : const TypeBoundPredicate parent,
622 : 28726 : const Resolver::TraitItemReference *trait_item_ref)
623 : 28726 : : parent (parent), trait_item_ref (trait_item_ref)
624 : 28726 : {}
625 : :
626 : 31308 : TypeBoundPredicateItem::TypeBoundPredicateItem (
627 : 31308 : const TypeBoundPredicateItem &other)
628 : 31308 : : parent (other.parent), trait_item_ref (other.trait_item_ref)
629 : 31308 : {}
630 : :
631 : : TypeBoundPredicateItem &
632 : 5397 : TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
633 : : {
634 : 5397 : parent = other.parent;
635 : 5397 : trait_item_ref = other.trait_item_ref;
636 : :
637 : 5397 : return *this;
638 : : }
639 : :
640 : : TypeBoundPredicateItem
641 : 5401 : TypeBoundPredicateItem::error ()
642 : : {
643 : 5401 : return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
644 : : }
645 : :
646 : : bool
647 : 5473 : TypeBoundPredicateItem::is_error () const
648 : : {
649 : 5473 : 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 : 5336 : TypeBoundPredicate::lookup_associated_item (
660 : : const Resolver::TraitItemReference *ref) const
661 : : {
662 : 5336 : return lookup_associated_item (ref->get_identifier ());
663 : : }
664 : :
665 : : BaseType *
666 : 7370 : TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
667 : : {
668 : 7370 : TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
669 : 7370 : if (parent.get_substitution_arguments ().is_empty ())
670 : : return trait_item_tyty;
671 : :
672 : 7370 : const Resolver::TraitItemReference *tref = get_raw_item ();
673 : 7370 : bool is_associated_type = tref->get_trait_item_type ();
674 : 7370 : if (is_associated_type)
675 : : return trait_item_tyty;
676 : :
677 : : // set up the self mapping
678 : 5878 : SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
679 : 5878 : rust_assert (!gargs.is_empty ());
680 : :
681 : : // setup the adjusted mappings
682 : 5878 : std::vector<SubstitutionArg> adjusted_mappings;
683 : 14221 : for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
684 : : {
685 : 8343 : auto &mapping = gargs.get_mappings ().at (i);
686 : :
687 : 8343 : bool is_implicit_self = i == 0;
688 : 8343 : TyTy::BaseType *argument
689 : 8343 : = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
690 : :
691 : 8343 : adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument);
692 : : }
693 : :
694 : 5878 : SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
695 : : gargs.get_regions (),
696 : : gargs.get_locus (),
697 : 5878 : gargs.get_subst_cb (),
698 : 5878 : true /* trait-mode-flag */);
699 : 5878 : return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
700 : 5878 : }
701 : : bool
702 : 152782 : TypeBoundPredicate::is_error () const
703 : : {
704 : 152782 : auto context = Resolver::TypeCheckContext::get ();
705 : :
706 : 152782 : Resolver::TraitReference *ref = nullptr;
707 : 152782 : bool ok = context->lookup_trait_reference (reference, &ref);
708 : :
709 : 152782 : return !ok || error_flag;
710 : : }
711 : :
712 : : BaseType *
713 : 36933 : TypeBoundPredicate::handle_substitions (
714 : : SubstitutionArgumentMappings &subst_mappings)
715 : : {
716 : 82028 : for (auto &sub : get_substs ())
717 : : {
718 : 45095 : if (sub.get_param_ty () == nullptr)
719 : 0 : continue;
720 : :
721 : 45095 : auto p = sub.get_param_ty ();
722 : 45095 : BaseType *r = p->resolve ();
723 : 45095 : BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
724 : :
725 : 45095 : p->set_ty_ref (s->get_ty_ref ());
726 : : }
727 : :
728 : : // associated argument mappings
729 : 36976 : 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 : 36933 : 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 : 21697 : TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
834 : : {
835 : : // check they match the same trait reference
836 : 40115 : if (reference != other.reference)
837 : : return false;
838 : :
839 : : // check that the generics match
840 : 3294 : if (get_num_substitutions () != other.get_num_substitutions ())
841 : : return false;
842 : :
843 : : // then match the generics applied
844 : 7699 : for (size_t i = 0; i < get_num_substitutions (); i++)
845 : : {
846 : 4420 : SubstitutionParamMapping a = substitutions.at (i);
847 : 4420 : SubstitutionParamMapping b = other.substitutions.at (i);
848 : :
849 : 4420 : auto ap = a.get_param_ty ();
850 : 4420 : auto bp = b.get_param_ty ();
851 : :
852 : 4420 : BaseType *apd = ap->destructure ();
853 : 4420 : BaseType *bpd = bp->destructure ();
854 : :
855 : 4420 : if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
856 : 4420 : TyTy::TyWithLocation (bpd),
857 : : UNKNOWN_LOCATION, false))
858 : 15 : return false;
859 : : }
860 : :
861 : : return true;
862 : : }
863 : :
864 : : bool
865 : 8301 : TypeBoundPredicate::validate_type_implements_super_traits (
866 : : TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
867 : : {
868 : 8301 : if (get_polarity () != BoundPolarity::RegularBound)
869 : : return true;
870 : :
871 : 8296 : auto &ptref = *get ();
872 : 11955 : 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.as_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.as_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 : 43503 : TypeBoundPredicateItem::get_raw_item () const
927 : : {
928 : 43503 : 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 : 3 : TypeBoundPredicateItem::get_locus () const
939 : : {
940 : 3 : return get_raw_item ()->get_locus ();
941 : : }
942 : :
943 : : // TypeBoundsMappings
944 : :
945 : 87421186 : TypeBoundsMappings::TypeBoundsMappings (
946 : 87421186 : std::vector<TypeBoundPredicate> specified_bounds)
947 : 87421186 : : specified_bounds (specified_bounds)
948 : 87421186 : {}
949 : :
950 : : std::vector<TypeBoundPredicate> &
951 : 105540 : TypeBoundsMappings::get_specified_bounds ()
952 : : {
953 : 105540 : return specified_bounds;
954 : : }
955 : :
956 : : const std::vector<TypeBoundPredicate> &
957 : 85852487 : TypeBoundsMappings::get_specified_bounds () const
958 : : {
959 : 85852487 : return specified_bounds;
960 : : }
961 : :
962 : : TypeBoundPredicate
963 : 2400 : TypeBoundsMappings::lookup_predicate (DefId id)
964 : : {
965 : 2582 : for (auto &b : specified_bounds)
966 : : {
967 : 2749 : if (b.get_id () == id)
968 : 2385 : return b;
969 : : }
970 : 15 : return TypeBoundPredicate::error ();
971 : : }
972 : :
973 : : size_t
974 : 232451 : TypeBoundsMappings::num_specified_bounds () const
975 : : {
976 : 232451 : return specified_bounds.size ();
977 : : }
978 : :
979 : : std::string
980 : 30551 : TypeBoundsMappings::raw_bounds_as_string () const
981 : : {
982 : 30551 : std::string buf;
983 : 31572 : 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 : 30551 : return buf;
990 : : }
991 : :
992 : : std::string
993 : 29603 : TypeBoundsMappings::bounds_as_string () const
994 : : {
995 : 59206 : return "bounds:[" + raw_bounds_as_string () + "]";
996 : : }
997 : :
998 : : std::string
999 : 49544 : TypeBoundsMappings::raw_bounds_as_name () const
1000 : : {
1001 : 49544 : std::string buf;
1002 : 99159 : 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 : 49544 : return buf;
1010 : : }
1011 : :
1012 : : void
1013 : 59928 : TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
1014 : : {
1015 : 65721 : for (auto &bound : specified_bounds)
1016 : : {
1017 : 35514 : bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
1018 : 5793 : if (same_trait_ref_p)
1019 : 59928 : return;
1020 : : }
1021 : :
1022 : 30207 : specified_bounds.push_back (predicate);
1023 : : }
1024 : :
1025 : : } // namespace TyTy
1026 : : } // namespace Rust
|