Line data Source code
1 : // Copyright (C) 2021-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "rust-hir-trait-resolve.h"
20 : #include "rust-hir-type-check-expr.h"
21 : #include "rust-substitution-mapper.h"
22 : #include "rust-type-util.h"
23 : #include "rust-immutable-name-resolution-context.h"
24 :
25 : namespace Rust {
26 : namespace Resolver {
27 :
28 : TraitItemReference
29 3310 : ResolveTraitItemToRef::Resolve (
30 : HIR::TraitItem &item, TyTy::BaseType *self,
31 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
32 : {
33 3310 : ResolveTraitItemToRef resolver (self, std::move (substitutions));
34 3310 : item.accept_vis (resolver);
35 3310 : return std::move (resolver.resolved);
36 3310 : }
37 :
38 : void
39 736 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
40 : {
41 : // create trait-item-ref
42 736 : location_t locus = type.get_locus ();
43 736 : bool is_optional = false;
44 1472 : std::string identifier = type.get_name ().as_string ();
45 :
46 736 : resolved = TraitItemReference (identifier, is_optional,
47 : TraitItemReference::TraitItemType::TYPE, &type,
48 2208 : self, substitutions, locus);
49 736 : }
50 :
51 : void
52 38 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
53 : {
54 : // create trait-item-ref
55 38 : location_t locus = cst.get_locus ();
56 38 : bool is_optional = cst.has_expr ();
57 76 : std::string identifier = cst.get_name ().as_string ();
58 :
59 38 : resolved = TraitItemReference (identifier, is_optional,
60 : TraitItemReference::TraitItemType::CONST, &cst,
61 114 : self, substitutions, locus);
62 38 : }
63 :
64 : void
65 2536 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
66 : {
67 : // create trait-item-ref
68 2536 : location_t locus = fn.get_locus ();
69 2536 : bool is_optional = fn.has_definition ();
70 5072 : std::string identifier = fn.get_decl ().get_function_name ().as_string ();
71 :
72 2536 : resolved = TraitItemReference (identifier, is_optional,
73 : TraitItemReference::TraitItemType::FN, &fn,
74 7608 : self, std::move (substitutions), locus);
75 2536 : }
76 :
77 3310 : ResolveTraitItemToRef::ResolveTraitItemToRef (
78 : TyTy::BaseType *self,
79 3310 : std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
80 3310 : : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
81 3310 : substitutions (std::move (substitutions))
82 3310 : {}
83 :
84 : // TraitItemReference items
85 :
86 : TraitReference *
87 423288 : TraitResolver::Resolve (HIR::TypePath &path)
88 : {
89 423288 : TraitResolver resolver;
90 423288 : return resolver.resolve_path (path);
91 423288 : }
92 :
93 : TraitReference *
94 82438 : TraitResolver::Resolve (HIR::Trait &trait)
95 : {
96 82438 : TraitResolver resolver;
97 82438 : return resolver.resolve_trait (&trait);
98 82438 : }
99 :
100 : TraitReference *
101 21935 : TraitResolver::Lookup (HIR::TypePath &path)
102 : {
103 21935 : TraitResolver resolver;
104 21935 : return resolver.lookup_path (path);
105 21935 : }
106 :
107 : HIR::Trait *
108 1782618 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
109 : {
110 1782618 : TraitResolver resolver;
111 :
112 1782618 : HIR::Trait *lookup = nullptr;
113 1782618 : bool ok = resolver.resolve_path_to_trait (path, &lookup);
114 1782618 : return ok ? lookup : nullptr;
115 1782618 : }
116 :
117 2310279 : TraitResolver::TraitResolver () : TypeCheckBase () {}
118 :
119 : bool
120 2227841 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
121 : HIR::Trait **resolved) const
122 : {
123 2227841 : auto &nr_ctx
124 2227841 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
125 :
126 2227841 : NodeId ref;
127 2227841 : if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
128 : {
129 2227841 : ref = *ref_opt;
130 : }
131 : else
132 : {
133 0 : rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
134 0 : return false;
135 : }
136 :
137 2227841 : auto hid = mappings.lookup_node_to_hir (ref);
138 2227841 : if (!hid)
139 : {
140 0 : rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
141 0 : return false;
142 : }
143 :
144 2227841 : auto resolved_item = mappings.lookup_hir_item (hid.value ());
145 2227841 : if (!resolved_item.has_value ())
146 : {
147 0 : rust_error_at (path.get_locus (),
148 : "Failed to resolve trait by looking up hir node");
149 0 : return false;
150 : }
151 :
152 2227841 : if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
153 : {
154 2 : rich_location r (line_table, path.get_locus ());
155 2 : r.add_fixit_replace ("not a trait");
156 2 : rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
157 4 : path.as_simple_path ().as_string ().c_str ());
158 2 : return false;
159 2 : }
160 :
161 2227839 : *resolved = static_cast<HIR::Trait *> (*resolved_item);
162 2227839 : return true;
163 : }
164 :
165 : TraitReference *
166 423288 : TraitResolver::resolve_path (HIR::TypePath &path)
167 : {
168 423288 : HIR::Trait *resolved_trait_reference;
169 423288 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
170 423288 : if (!ok)
171 2 : return &TraitReference::error_node ();
172 :
173 423286 : return resolve_trait (resolved_trait_reference);
174 : }
175 :
176 : TraitReference *
177 505724 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
178 : {
179 505724 : TraitReference *tref = &TraitReference::error_node ();
180 505724 : if (context->lookup_trait_reference (
181 505724 : trait_reference->get_mappings ().get_defid (), &tref))
182 : {
183 502032 : return tref;
184 : }
185 :
186 3692 : DefId trait_id = trait_reference->get_mappings ().get_defid ();
187 3692 : if (context->trait_query_in_progress (trait_id))
188 : {
189 4 : rust_error_at (
190 : trait_reference->get_locus (), ErrorCode::E0391,
191 : "cycle detected when computing the super predicates of %qs",
192 4 : trait_reference->get_name ().as_string ().c_str ());
193 4 : return &TraitReference::error_node ();
194 : }
195 :
196 3688 : TraitQueryGuard guard (trait_id);
197 3688 : TyTy::BaseType *self = nullptr;
198 3688 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
199 :
200 : // this needs to be special cased for the sized trait to not auto implemented
201 : // Sized on Self
202 8026 : for (auto &generic_param : trait_reference->get_generic_params ())
203 : {
204 4338 : switch (generic_param.get ()->get_kind ())
205 : {
206 : case HIR::GenericParam::GenericKind::LIFETIME:
207 : case HIR::GenericParam::GenericKind::CONST:
208 : // FIXME: Skipping Lifetime and Const completely until better
209 : // handling.
210 : break;
211 :
212 4329 : case HIR::GenericParam::GenericKind::TYPE:
213 4329 : {
214 4329 : auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
215 4329 : bool is_self
216 4329 : = typaram.get_type_representation ().as_string ().compare ("Self")
217 4329 : == 0;
218 :
219 : // https://doc.rust-lang.org/std/marker/trait.Sized.html
220 : // The one exception is the implicit Self type of a trait
221 4329 : bool apply_sized = !is_self;
222 4329 : auto param_type
223 4329 : = TypeResolveGenericParam::Resolve (*generic_param, true,
224 4329 : apply_sized);
225 :
226 4329 : context->insert_type (generic_param->get_mappings (), param_type);
227 4329 : substitutions.emplace_back (typaram, param_type);
228 :
229 4329 : if (is_self)
230 : {
231 3688 : rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
232 3688 : TyTy::ParamType *p
233 : = static_cast<TyTy::ParamType *> (param_type);
234 3688 : p->set_implicit_self_trait ();
235 3688 : self = p;
236 : }
237 : }
238 4329 : break;
239 : }
240 : }
241 3688 : rust_assert (self != nullptr);
242 :
243 : // Check if there is a super-trait, and apply this bound to the Self
244 : // TypeParam
245 7376 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
246 :
247 : // copy the substitition mappings
248 3688 : std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
249 3688 : self_subst_copy.reserve (substitutions.size ());
250 :
251 8017 : for (auto &sub : substitutions)
252 4329 : self_subst_copy.push_back (sub.clone ());
253 :
254 : // They also inherit themselves as a bound this enables a trait item to
255 : // reference other Self::trait_items
256 3688 : specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
257 : std::move (self_subst_copy),
258 7376 : BoundPolarity::RegularBound,
259 3688 : trait_reference->get_locus ());
260 :
261 : // look for any
262 7376 : std::vector<TyTy::TypeBoundPredicate> super_traits;
263 3688 : if (trait_reference->has_type_param_bounds ())
264 : {
265 1132 : for (auto &bound : trait_reference->get_type_param_bounds ())
266 : {
267 606 : if (bound->get_bound_type ()
268 : == HIR::TypeParamBound::BoundType::TRAITBOUND)
269 : {
270 606 : HIR::TraitBound *b
271 606 : = static_cast<HIR::TraitBound *> (bound.get ());
272 :
273 606 : auto predicate = get_predicate_from_bound (
274 : b->get_path (),
275 : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
276 606 : BoundPolarity::RegularBound, false, true);
277 606 : if (predicate.is_error ())
278 8 : return &TraitReference::error_node ();
279 :
280 598 : specified_bounds.push_back (predicate);
281 598 : super_traits.push_back (predicate);
282 606 : }
283 : }
284 : }
285 3680 : self->inherit_bounds (specified_bounds);
286 :
287 3680 : context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
288 7360 : std::vector<TraitItemReference> item_refs;
289 6990 : for (auto &item : trait_reference->get_trait_items ())
290 : {
291 : // make a copy of the substs
292 3310 : std::vector<TyTy::SubstitutionParamMapping> item_subst;
293 3310 : item_subst.reserve (substitutions.size ());
294 :
295 8045 : for (auto &sub : substitutions)
296 4735 : item_subst.push_back (sub.clone ());
297 :
298 3310 : TraitItemReference trait_item_ref
299 3310 : = ResolveTraitItemToRef::Resolve (*item.get (), self,
300 3310 : std::move (item_subst));
301 3310 : item_refs.push_back (std::move (trait_item_ref));
302 3310 : }
303 :
304 3680 : TraitReference trait_object (trait_reference, item_refs, super_traits,
305 3680 : std::move (substitutions));
306 3680 : context->insert_trait_reference (
307 3680 : trait_reference->get_mappings ().get_defid (), std::move (trait_object));
308 :
309 3680 : tref = &TraitReference::error_node ();
310 3680 : bool ok = context->lookup_trait_reference (
311 3680 : trait_reference->get_mappings ().get_defid (), &tref);
312 3680 : rust_assert (ok);
313 :
314 : // hook to allow the trait to resolve its optional item blocks, we cant
315 : // resolve the blocks of functions etc because it can end up in a recursive
316 : // loop of trying to resolve traits as required by the types
317 3680 : tref->on_resolved ();
318 3680 : context->block_context ().exit ();
319 :
320 3680 : return tref;
321 3688 : }
322 :
323 : TraitReference *
324 21935 : TraitResolver::lookup_path (HIR::TypePath &path)
325 : {
326 21935 : HIR::Trait *resolved_trait_reference;
327 21935 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
328 21935 : if (!ok)
329 0 : return &TraitReference::error_node ();
330 :
331 21935 : TraitReference *tref = &TraitReference::error_node ();
332 21935 : if (context->lookup_trait_reference (
333 21935 : resolved_trait_reference->get_mappings ().get_defid (), &tref))
334 : {
335 21935 : return tref;
336 : }
337 0 : return &TraitReference::error_node ();
338 : }
339 :
340 : void
341 3310 : TraitItemReference::on_resolved ()
342 : {
343 3310 : switch (type)
344 : {
345 38 : case CONST:
346 38 : resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
347 38 : break;
348 :
349 736 : case TYPE:
350 736 : resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
351 736 : break;
352 :
353 2536 : case FN:
354 2536 : resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
355 2536 : break;
356 :
357 : default:
358 : break;
359 : }
360 3310 : }
361 :
362 : void
363 736 : TraitItemReference::resolve_item (HIR::TraitItemType &type)
364 : {
365 736 : TyTy::BaseType *ty
366 736 : = new TyTy::PlaceholderType (type.get_name ().as_string (),
367 736 : type.get_mappings ().get_defid (),
368 1472 : type.get_mappings ().get_hirid ());
369 736 : context->insert_type (type.get_mappings (), ty);
370 736 : }
371 :
372 : void
373 38 : TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
374 : {
375 38 : TyTy::BaseType *ty = nullptr;
376 38 : if (constant.has_type ())
377 11 : ty = TypeCheckType::Resolve (constant.get_type ());
378 :
379 38 : TyTy::BaseType *expr = nullptr;
380 38 : if (constant.has_expr ())
381 11 : expr = TypeCheckExpr::Resolve (constant.get_expr ());
382 :
383 49 : bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
384 49 : bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
385 :
386 10 : if (have_specified_ty && have_expr_ty)
387 : {
388 20 : coercion_site (constant.get_mappings ().get_hirid (),
389 : TyTy::TyWithLocation (ty,
390 10 : constant.get_type ().get_locus ()),
391 : TyTy::TyWithLocation (expr,
392 10 : constant.get_expr ().get_locus ()),
393 : constant.get_locus ());
394 : }
395 38 : }
396 :
397 : void
398 2536 : TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
399 : {
400 2536 : TyTy::BaseType *item_tyty = get_tyty ();
401 2536 : if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
402 : return;
403 :
404 2534 : if (!is_optional ())
405 : return;
406 :
407 : // check the block and return types
408 855 : rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
409 :
410 : // need to get the return type from this
411 855 : TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
412 855 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
413 855 : context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
414 :
415 855 : auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
416 :
417 855 : location_t fn_return_locus
418 855 : = func.get_decl ().has_return_type ()
419 855 : ? func.get_decl ().get_return_type ().get_locus ()
420 191 : : func.get_locus ();
421 :
422 1710 : coercion_site (func.get_mappings ().get_hirid (),
423 855 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
424 855 : TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
425 :
426 855 : context->pop_return_type ();
427 : }
428 :
429 : void
430 2959 : TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
431 : {
432 2959 : rust_assert (get_trait_item_type () == TraitItemType::TYPE);
433 :
434 : // this isnt super safe there are cases like the FnTraits where the type is
435 : // set to the impls placeholder associated type. For example
436 : //
437 : // type Output = F::Output; -- see the fn trait impls in libcore
438 : //
439 : // then this projection ends up resolving back to this placeholder so it just
440 : // ends up being cyclical
441 :
442 2959 : TyTy::BaseType *item_ty = get_tyty ();
443 2959 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
444 2959 : TyTy::PlaceholderType *placeholder
445 : = static_cast<TyTy::PlaceholderType *> (item_ty);
446 :
447 2959 : if (ty->is<TyTy::ProjectionType> ())
448 : {
449 2771 : const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
450 2771 : const auto resolved = projection.get ();
451 2771 : if (resolved == item_ty)
452 : return;
453 : }
454 :
455 2959 : placeholder->set_associated_type (ty->get_ty_ref ());
456 : }
457 :
458 : void
459 1353 : TraitItemReference::associated_type_reset (bool only_projections) const
460 : {
461 1353 : rust_assert (get_trait_item_type () == TraitItemType::TYPE);
462 :
463 1353 : TyTy::BaseType *item_ty = get_tyty ();
464 1353 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
465 1353 : TyTy::PlaceholderType *placeholder
466 : = static_cast<TyTy::PlaceholderType *> (item_ty);
467 :
468 1353 : if (!only_projections)
469 : {
470 1177 : placeholder->clear_associated_type ();
471 : }
472 : else
473 : {
474 176 : if (!placeholder->can_resolve ())
475 : return;
476 :
477 40 : const TyTy::BaseType *r = placeholder->resolve ();
478 40 : if (r->get_kind () == TyTy::TypeKind::PROJECTION)
479 : {
480 14 : placeholder->clear_associated_type ();
481 : }
482 : }
483 : }
484 :
485 : void
486 5534 : AssociatedImplTrait::setup_raw_associated_types ()
487 : {
488 5534 : auto &impl_items = impl->get_impl_items ();
489 17909 : for (auto &impl_item : impl_items)
490 : {
491 12375 : bool is_type_alias = impl_item->get_impl_item_type ()
492 12375 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
493 12375 : if (!is_type_alias)
494 11416 : continue;
495 :
496 959 : HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
497 :
498 959 : TraitItemReference *resolved_trait_item = nullptr;
499 959 : bool ok
500 959 : = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
501 : &resolved_trait_item);
502 959 : if (!ok)
503 0 : continue;
504 959 : if (resolved_trait_item->get_trait_item_type ()
505 : != TraitItemReference::TraitItemType::TYPE)
506 0 : continue;
507 :
508 959 : TyTy::BaseType *lookup;
509 959 : ok = context->lookup_type (type.get_mappings ().get_hirid (), &lookup);
510 959 : rust_assert (ok);
511 :
512 959 : resolved_trait_item->associated_type_set (lookup);
513 : }
514 5534 : }
515 :
516 : TyTy::BaseType *
517 2242 : AssociatedImplTrait::setup_associated_types (
518 : const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
519 : TyTy::SubstitutionArgumentMappings *args, bool infer)
520 : {
521 : // compute the constrained impl block generic arguments based on self and the
522 : // higher ranked trait bound
523 2242 : TyTy::BaseType *receiver = self->clone ();
524 :
525 : // impl<Y> SliceIndex<[Y]> for Range<usize>
526 : // vs
527 : // I: SliceIndex<[<integer>]> and Range<<integer>>
528 : //
529 : // we need to figure out what Y is
530 :
531 2242 : TyTy::BaseType *associated_self = get_self ();
532 :
533 2242 : rust_debug ("setup_associated_types for: %s->%s bound %s",
534 : associated_self->debug_str ().c_str (),
535 : self->debug_str ().c_str (), bound.as_string ().c_str ());
536 :
537 : // grab the parameters
538 2242 : HIR::ImplBlock &impl_block = *get_impl_block ();
539 2242 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
540 2641 : for (auto &generic_param : impl_block.get_generic_params ())
541 : {
542 399 : switch (generic_param.get ()->get_kind ())
543 : {
544 : case HIR::GenericParam::GenericKind::LIFETIME:
545 : case HIR::GenericParam::GenericKind::CONST:
546 : // FIXME: Skipping Lifetime and Const completely until better
547 : // handling.
548 : break;
549 :
550 385 : case HIR::GenericParam::GenericKind::TYPE:
551 385 : {
552 385 : TyTy::BaseType *l = nullptr;
553 385 : bool ok = context->lookup_type (
554 385 : generic_param->get_mappings ().get_hirid (), &l);
555 385 : if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
556 : {
557 385 : substitutions.emplace_back (static_cast<HIR::TypeParam &> (
558 385 : *generic_param),
559 385 : static_cast<TyTy::ParamType *> (l));
560 : }
561 : }
562 385 : break;
563 : }
564 : }
565 :
566 : // this callback gives us the parameters that get substituted so we can
567 : // compute the constrained type parameters for this impl block
568 4484 : std::map<std::string, HirId> param_mappings;
569 2242 : TyTy::ParamSubstCb param_subst_cb
570 2242 : = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
571 575 : param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
572 2242 : };
573 :
574 : // generate inference variables for these bound arguments so we can compute
575 : // their values
576 2242 : location_t locus = UNKNOWN_LOCATION;
577 4484 : std::vector<TyTy::SubstitutionArg> subst_args;
578 2627 : for (auto &p : substitutions)
579 : {
580 385 : if (p.needs_substitution () && infer)
581 : {
582 334 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
583 334 : subst_args.emplace_back (&p, infer_var.get_tyty ());
584 : }
585 : else
586 : {
587 51 : auto param = p.get_param_ty ();
588 51 : auto resolved = param->destructure ();
589 51 : subst_args.emplace_back (&p, resolved);
590 51 : param_mappings[param->get_symbol ()] = resolved->get_ref ();
591 : }
592 : }
593 :
594 2242 : TyTy::SubstitutionArgumentMappings infer_arguments (
595 : std::move (subst_args), {},
596 4484 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
597 6726 : locus, param_subst_cb);
598 2242 : TyTy::BaseType *impl_self_infer
599 2242 : = (!associated_self->is_concrete ())
600 2242 : ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
601 : : associated_self;
602 :
603 2242 : const TyTy::TypeBoundPredicate &impl_predicate
604 2242 : = associated_self->lookup_predicate (bound.get_id ());
605 2242 : rust_assert (!impl_predicate.is_error ());
606 :
607 : // infer the arguments on the predicate
608 4484 : std::vector<TyTy::BaseType *> impl_trait_predicate_args;
609 :
610 5467 : for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
611 : {
612 3225 : const auto &arg = impl_predicate.get_substs ().at (i);
613 3225 : if (i == 0)
614 2242 : continue;
615 :
616 983 : const auto p = arg.get_param_ty ();
617 983 : auto r = p->resolve ();
618 983 : if (!r->is_concrete ())
619 : {
620 295 : r = SubstMapperInternal::Resolve (r, infer_arguments);
621 : }
622 983 : impl_trait_predicate_args.push_back (r);
623 : }
624 :
625 : // unify the bounds arguments
626 4484 : std::vector<TyTy::BaseType *> hrtb_bound_arguments;
627 5467 : for (size_t i = 0; i < bound.get_substs ().size (); i++)
628 : {
629 3225 : const auto &arg = bound.get_substs ().at (i);
630 3225 : if (i == 0)
631 2242 : continue;
632 :
633 983 : const auto p = arg.get_param_ty ();
634 983 : auto r = p->resolve ();
635 983 : if (!r->is_concrete ())
636 : {
637 1 : r = SubstMapperInternal::Resolve (r, infer_arguments);
638 : }
639 983 : hrtb_bound_arguments.push_back (r);
640 : }
641 :
642 2242 : rust_assert (impl_trait_predicate_args.size ()
643 : == hrtb_bound_arguments.size ());
644 3225 : for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
645 : {
646 983 : TyTy::BaseType *a = impl_trait_predicate_args.at (i);
647 983 : TyTy::BaseType *b = hrtb_bound_arguments.at (i);
648 :
649 983 : TyTy::BaseType *result
650 983 : = unify_site_and (a->get_ref (), TyTy::TyWithLocation (a),
651 983 : TyTy::TyWithLocation (b), impl_predicate.get_locus (),
652 : true /*emit-errors*/, true /*commit-if-ok*/,
653 : true /*infer*/, true /*cleanup-on-fail*/);
654 983 : rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
655 : }
656 :
657 : // we need to unify the receiver with the impl-block Self so that we compute
658 : // the type correctly as our receiver may be generic and we are inferring its
659 : // generic arguments and this Self might be the concrete version or vice
660 : // versa.
661 4484 : auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
662 2242 : TyTy::TyWithLocation (receiver),
663 2242 : TyTy::TyWithLocation (impl_self_infer),
664 : impl_predicate.get_locus (),
665 : true /*emit-errors*/, true /*commit-if-ok*/,
666 : true /*infer*/, true /*cleanup-on-fail*/);
667 2242 : rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
668 2242 : TyTy::BaseType *self_result = result;
669 :
670 : // create the argument list
671 4484 : std::vector<TyTy::SubstitutionArg> associated_arguments;
672 2627 : for (auto &p : substitutions)
673 : {
674 385 : std::string symbol = p.get_param_ty ()->get_symbol ();
675 385 : auto it = param_mappings.find (symbol);
676 385 : rust_assert (it != param_mappings.end ());
677 :
678 385 : HirId id = it->second;
679 385 : TyTy::BaseType *argument = nullptr;
680 385 : bool ok = context->lookup_type (id, &argument);
681 385 : rust_assert (ok);
682 :
683 385 : TyTy::SubstitutionArg arg (&p, argument);
684 385 : associated_arguments.push_back (arg);
685 385 : }
686 :
687 2242 : TyTy::SubstitutionArgumentMappings associated_type_args (
688 : std::move (associated_arguments), {},
689 2242 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
690 4484 : locus);
691 :
692 2242 : auto &impl_items = impl->get_impl_items ();
693 5253 : for (auto &impl_item : impl_items)
694 : {
695 3011 : bool is_type_alias = impl_item->get_impl_item_type ()
696 3011 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
697 3011 : if (!is_type_alias)
698 2374 : continue;
699 :
700 637 : HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
701 :
702 637 : TraitItemReference *resolved_trait_item = nullptr;
703 637 : bool ok
704 637 : = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
705 : &resolved_trait_item);
706 637 : if (!ok)
707 0 : continue;
708 637 : if (resolved_trait_item->get_trait_item_type ()
709 : != TraitItemReference::TraitItemType::TYPE)
710 0 : continue;
711 :
712 637 : TyTy::BaseType *lookup;
713 637 : if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
714 0 : continue;
715 :
716 : // this might be generic
717 637 : TyTy::BaseType *substituted
718 637 : = SubstMapperInternal::Resolve (lookup, associated_type_args);
719 637 : resolved_trait_item->associated_type_set (substituted);
720 : }
721 :
722 2242 : if (args != nullptr)
723 : {
724 92 : *args = associated_type_args;
725 : }
726 :
727 2242 : return self_result;
728 2242 : }
729 :
730 : void
731 0 : AssociatedImplTrait::reset_associated_types ()
732 : {
733 0 : trait->clear_associated_types ();
734 0 : }
735 :
736 : location_t
737 0 : AssociatedImplTrait::get_locus () const
738 : {
739 0 : return impl->get_locus ();
740 : }
741 :
742 : Analysis::NodeMapping
743 0 : TraitItemReference::get_parent_trait_mappings () const
744 : {
745 0 : auto &mappings = Analysis::Mappings::get ();
746 :
747 0 : HIR::Trait *trait
748 0 : = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
749 0 : rust_assert (trait != nullptr);
750 :
751 0 : return trait->get_mappings ();
752 : }
753 :
754 : bool
755 1590 : TraitItemReference::is_object_safe () const
756 : {
757 : // https://doc.rust-lang.org/reference/items/traits.html#object-safety
758 1590 : switch (get_trait_item_type ())
759 : {
760 1588 : case TraitItemReference::TraitItemType::FN:
761 1588 : {
762 : // lets be boring and just check that this is indeed a method will do
763 : // for now
764 1588 : const HIR::TraitItem *item = get_hir_trait_item ();
765 1588 : const HIR::TraitItemFunc *fn
766 : = static_cast<const HIR::TraitItemFunc *> (item);
767 1588 : return fn->get_decl ().is_method ();
768 : }
769 :
770 : // constants are not available via dyn dispatch and so is not object safe
771 : case TraitItemReference::TraitItemType::CONST:
772 : return false;
773 :
774 : // types are object safe since they are not available via dyn dispatch
775 0 : case TraitItemReference::TraitItemType::TYPE:
776 0 : return true;
777 :
778 : // this is just an error so lets just fail it
779 : case TraitItemReference::TraitItemType::ERROR:
780 : return false;
781 : }
782 : return false;
783 : }
784 :
785 : } // namespace Resolver
786 : } // namespace Rust
|