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