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