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-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 : 3278 : ResolveTraitItemToRef::Resolve (
30 : : HIR::TraitItem &item, TyTy::BaseType *self,
31 : : std::vector<TyTy::SubstitutionParamMapping> substitutions)
32 : : {
33 : 3278 : ResolveTraitItemToRef resolver (self, std::move (substitutions));
34 : 3278 : item.accept_vis (resolver);
35 : 3278 : return std::move (resolver.resolved);
36 : 3278 : }
37 : :
38 : : void
39 : 724 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
40 : : {
41 : : // create trait-item-ref
42 : 724 : location_t locus = type.get_locus ();
43 : 724 : bool is_optional = false;
44 : 1448 : std::string identifier = type.get_name ().as_string ();
45 : :
46 : 724 : resolved = TraitItemReference (identifier, is_optional,
47 : : TraitItemReference::TraitItemType::TYPE, &type,
48 : 2172 : self, substitutions, locus);
49 : 724 : }
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 : 2516 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
66 : : {
67 : : // create trait-item-ref
68 : 2516 : location_t locus = fn.get_locus ();
69 : 2516 : bool is_optional = fn.has_definition ();
70 : 5032 : std::string identifier = fn.get_decl ().get_function_name ().as_string ();
71 : :
72 : 2516 : resolved = TraitItemReference (identifier, is_optional,
73 : : TraitItemReference::TraitItemType::FN, &fn,
74 : 7548 : self, std::move (substitutions), locus);
75 : 2516 : }
76 : :
77 : 3278 : ResolveTraitItemToRef::ResolveTraitItemToRef (
78 : : TyTy::BaseType *self,
79 : 3278 : std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
80 : 3278 : : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
81 : 3278 : substitutions (std::move (substitutions))
82 : 3278 : {}
83 : :
84 : : // TraitItemReference items
85 : :
86 : : TraitReference *
87 : 251456 : TraitResolver::Resolve (HIR::TypePath &path)
88 : : {
89 : 251456 : TraitResolver resolver;
90 : 251456 : return resolver.resolve_path (path);
91 : 251456 : }
92 : :
93 : : TraitReference *
94 : 53210 : TraitResolver::Resolve (HIR::Trait &trait)
95 : : {
96 : 53210 : TraitResolver resolver;
97 : 53210 : return resolver.resolve_trait (&trait);
98 : 53210 : }
99 : :
100 : : TraitReference *
101 : 21932 : TraitResolver::Lookup (HIR::TypePath &path)
102 : : {
103 : 21932 : TraitResolver resolver;
104 : 21932 : return resolver.lookup_path (path);
105 : 21932 : }
106 : :
107 : : HIR::Trait *
108 : 622023 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
109 : : {
110 : 622023 : TraitResolver resolver;
111 : :
112 : 622023 : HIR::Trait *lookup = nullptr;
113 : 622023 : bool ok = resolver.resolve_path_to_trait (path, &lookup);
114 : 622023 : return ok ? lookup : nullptr;
115 : 622023 : }
116 : :
117 : 948621 : TraitResolver::TraitResolver () : TypeCheckBase () {}
118 : :
119 : : bool
120 : 895411 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
121 : : HIR::Trait **resolved) const
122 : : {
123 : 895411 : auto &nr_ctx
124 : 895411 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
125 : :
126 : 895411 : NodeId ref;
127 : 895411 : if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
128 : : {
129 : 895411 : 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 : 895411 : auto hid = mappings.lookup_node_to_hir (ref);
138 : 895411 : 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 : 895411 : auto resolved_item = mappings.lookup_hir_item (hid.value ());
145 : 895411 : 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 : 895411 : 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 : 895409 : *resolved = static_cast<HIR::Trait *> (*resolved_item);
162 : 895409 : return true;
163 : : }
164 : :
165 : : TraitReference *
166 : 251456 : TraitResolver::resolve_path (HIR::TypePath &path)
167 : : {
168 : 251456 : HIR::Trait *resolved_trait_reference;
169 : 251456 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
170 : 251456 : if (!ok)
171 : 2 : return &TraitReference::error_node ();
172 : :
173 : 251454 : return resolve_trait (resolved_trait_reference);
174 : : }
175 : :
176 : : TraitReference *
177 : 304664 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
178 : : {
179 : 304664 : TraitReference *tref = &TraitReference::error_node ();
180 : 304664 : if (context->lookup_trait_reference (
181 : 304664 : trait_reference->get_mappings ().get_defid (), &tref))
182 : : {
183 : 301060 : return tref;
184 : : }
185 : :
186 : 3604 : DefId trait_id = trait_reference->get_mappings ().get_defid ();
187 : 3604 : 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 : 3600 : TraitQueryGuard guard (trait_id);
197 : 3600 : TyTy::BaseType *self = nullptr;
198 : 3600 : 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 : 7845 : for (auto &generic_param : trait_reference->get_generic_params ())
203 : : {
204 : 4245 : 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 : 4236 : case HIR::GenericParam::GenericKind::TYPE:
213 : 4236 : {
214 : 4236 : auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
215 : 4236 : bool is_self
216 : 4236 : = typaram.get_type_representation ().as_string ().compare ("Self")
217 : 4236 : == 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 : 4236 : bool apply_sized = !is_self;
222 : 4236 : auto param_type
223 : 4236 : = TypeResolveGenericParam::Resolve (*generic_param, true,
224 : : apply_sized);
225 : :
226 : 4236 : context->insert_type (generic_param->get_mappings (), param_type);
227 : 8472 : substitutions.push_back (
228 : 4236 : TyTy::SubstitutionParamMapping (typaram, param_type));
229 : :
230 : 4236 : if (is_self)
231 : : {
232 : 3600 : rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
233 : 3600 : TyTy::ParamType *p
234 : : = static_cast<TyTy::ParamType *> (param_type);
235 : 3600 : p->set_implicit_self_trait ();
236 : 3600 : self = p;
237 : : }
238 : : }
239 : : break;
240 : : }
241 : : }
242 : 3600 : rust_assert (self != nullptr);
243 : :
244 : : // Check if there is a super-trait, and apply this bound to the Self
245 : : // TypeParam
246 : 7200 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
247 : :
248 : : // copy the substitition mappings
249 : 3600 : std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
250 : 7836 : for (auto &sub : substitutions)
251 : 4236 : self_subst_copy.push_back (sub.clone ());
252 : :
253 : : // They also inherit themselves as a bound this enables a trait item to
254 : : // reference other Self::trait_items
255 : 3600 : auto self_hrtb
256 : 3600 : = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
257 : : std::move (self_subst_copy),
258 : : BoundPolarity::RegularBound,
259 : 7200 : trait_reference->get_locus ());
260 : 3600 : specified_bounds.push_back (self_hrtb);
261 : :
262 : : // look for any
263 : 7200 : std::vector<TyTy::TypeBoundPredicate> super_traits;
264 : 3600 : if (trait_reference->has_type_param_bounds ())
265 : : {
266 : 1128 : for (auto &bound : trait_reference->get_type_param_bounds ())
267 : : {
268 : 604 : if (bound->get_bound_type ()
269 : : == HIR::TypeParamBound::BoundType::TRAITBOUND)
270 : : {
271 : 604 : HIR::TraitBound *b
272 : 604 : = static_cast<HIR::TraitBound *> (bound.get ());
273 : :
274 : 604 : auto predicate = get_predicate_from_bound (
275 : : b->get_path (),
276 : : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
277 : 604 : BoundPolarity::RegularBound, false, true);
278 : 604 : if (predicate.is_error ())
279 : 8 : return &TraitReference::error_node ();
280 : :
281 : 596 : specified_bounds.push_back (predicate);
282 : 596 : super_traits.push_back (predicate);
283 : 604 : }
284 : : }
285 : : }
286 : 3592 : self->inherit_bounds (specified_bounds);
287 : :
288 : 3592 : context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
289 : 7184 : std::vector<TraitItemReference> item_refs;
290 : 6870 : for (auto &item : trait_reference->get_trait_items ())
291 : : {
292 : : // make a copy of the substs
293 : 3278 : std::vector<TyTy::SubstitutionParamMapping> item_subst;
294 : 7971 : for (auto &sub : substitutions)
295 : 4693 : item_subst.push_back (sub.clone ());
296 : :
297 : 3278 : TraitItemReference trait_item_ref
298 : 3278 : = ResolveTraitItemToRef::Resolve (*item.get (), self,
299 : 3278 : std::move (item_subst));
300 : 3278 : item_refs.push_back (std::move (trait_item_ref));
301 : 3278 : }
302 : :
303 : 3592 : TraitReference trait_object (trait_reference, item_refs, super_traits,
304 : 3592 : std::move (substitutions));
305 : 3592 : context->insert_trait_reference (
306 : 3592 : trait_reference->get_mappings ().get_defid (), std::move (trait_object));
307 : :
308 : 3592 : tref = &TraitReference::error_node ();
309 : 3592 : bool ok = context->lookup_trait_reference (
310 : 3592 : trait_reference->get_mappings ().get_defid (), &tref);
311 : 3592 : rust_assert (ok);
312 : :
313 : : // hook to allow the trait to resolve its optional item blocks, we cant
314 : : // resolve the blocks of functions etc because it can end up in a recursive
315 : : // loop of trying to resolve traits as required by the types
316 : 3592 : tref->on_resolved ();
317 : 3592 : context->block_context ().exit ();
318 : :
319 : 3592 : return tref;
320 : 3600 : }
321 : :
322 : : TraitReference *
323 : 21932 : TraitResolver::lookup_path (HIR::TypePath &path)
324 : : {
325 : 21932 : HIR::Trait *resolved_trait_reference;
326 : 21932 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
327 : 21932 : if (!ok)
328 : 0 : return &TraitReference::error_node ();
329 : :
330 : 21932 : TraitReference *tref = &TraitReference::error_node ();
331 : 21932 : if (context->lookup_trait_reference (
332 : 21932 : resolved_trait_reference->get_mappings ().get_defid (), &tref))
333 : : {
334 : 21932 : return tref;
335 : : }
336 : 0 : return &TraitReference::error_node ();
337 : : }
338 : :
339 : : void
340 : 3278 : TraitItemReference::on_resolved ()
341 : : {
342 : 3278 : switch (type)
343 : : {
344 : 38 : case CONST:
345 : 38 : resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
346 : 38 : break;
347 : :
348 : 724 : case TYPE:
349 : 724 : resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
350 : 724 : break;
351 : :
352 : 2516 : case FN:
353 : 2516 : resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
354 : 2516 : break;
355 : :
356 : : default:
357 : : break;
358 : : }
359 : 3278 : }
360 : :
361 : : void
362 : 724 : TraitItemReference::resolve_item (HIR::TraitItemType &type)
363 : : {
364 : 724 : TyTy::BaseType *ty
365 : 724 : = new TyTy::PlaceholderType (type.get_name ().as_string (),
366 : 724 : type.get_mappings ().get_defid (),
367 : 1448 : type.get_mappings ().get_hirid ());
368 : 724 : context->insert_type (type.get_mappings (), ty);
369 : 724 : }
370 : :
371 : : void
372 : 38 : TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
373 : : {
374 : 38 : TyTy::BaseType *ty = nullptr;
375 : 38 : if (constant.has_type ())
376 : 11 : ty = TypeCheckType::Resolve (constant.get_type ());
377 : :
378 : 38 : TyTy::BaseType *expr = nullptr;
379 : 38 : if (constant.has_expr ())
380 : 11 : expr = TypeCheckExpr::Resolve (constant.get_expr ());
381 : :
382 : 49 : bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
383 : 49 : bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
384 : :
385 : 10 : if (have_specified_ty && have_expr_ty)
386 : : {
387 : 20 : coercion_site (constant.get_mappings ().get_hirid (),
388 : : TyTy::TyWithLocation (ty,
389 : 10 : constant.get_type ().get_locus ()),
390 : : TyTy::TyWithLocation (expr,
391 : 10 : constant.get_expr ().get_locus ()),
392 : : constant.get_locus ());
393 : : }
394 : 38 : }
395 : :
396 : : void
397 : 2516 : TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
398 : : {
399 : 2516 : TyTy::BaseType *item_tyty = get_tyty ();
400 : 2516 : if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
401 : : return;
402 : :
403 : 2514 : if (!is_optional ())
404 : : return;
405 : :
406 : : // check the block and return types
407 : 849 : rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
408 : :
409 : : // need to get the return type from this
410 : 849 : TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
411 : 849 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
412 : 849 : context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
413 : :
414 : 849 : auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
415 : :
416 : 849 : location_t fn_return_locus
417 : 849 : = func.get_decl ().has_return_type ()
418 : 849 : ? func.get_decl ().get_return_type ().get_locus ()
419 : 189 : : func.get_locus ();
420 : :
421 : 1698 : coercion_site (func.get_mappings ().get_hirid (),
422 : 849 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
423 : 849 : TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
424 : :
425 : 849 : context->pop_return_type ();
426 : : }
427 : :
428 : : void
429 : 2942 : TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
430 : : {
431 : 2942 : rust_assert (get_trait_item_type () == TraitItemType::TYPE);
432 : :
433 : : // this isnt super safe there are cases like the FnTraits where the type is
434 : : // set to the impls placeholder associated type. For example
435 : : //
436 : : // type Output = F::Output; -- see the fn trait impls in libcore
437 : : //
438 : : // then this projection ends up resolving back to this placeholder so it just
439 : : // ends up being cyclical
440 : :
441 : 2942 : TyTy::BaseType *item_ty = get_tyty ();
442 : 2942 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
443 : 2942 : TyTy::PlaceholderType *placeholder
444 : : = static_cast<TyTy::PlaceholderType *> (item_ty);
445 : :
446 : 2942 : if (ty->is<TyTy::ProjectionType> ())
447 : : {
448 : 2755 : const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
449 : 2755 : const auto resolved = projection.get ();
450 : 2755 : if (resolved == item_ty)
451 : : return;
452 : : }
453 : :
454 : 2942 : placeholder->set_associated_type (ty->get_ty_ref ());
455 : : }
456 : :
457 : : void
458 : 1344 : TraitItemReference::associated_type_reset (bool only_projections) const
459 : : {
460 : 1344 : rust_assert (get_trait_item_type () == TraitItemType::TYPE);
461 : :
462 : 1344 : TyTy::BaseType *item_ty = get_tyty ();
463 : 1344 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
464 : 1344 : TyTy::PlaceholderType *placeholder
465 : : = static_cast<TyTy::PlaceholderType *> (item_ty);
466 : :
467 : 1344 : if (!only_projections)
468 : : {
469 : 1168 : placeholder->clear_associated_type ();
470 : : }
471 : : else
472 : : {
473 : 176 : if (!placeholder->can_resolve ())
474 : : return;
475 : :
476 : 40 : const TyTy::BaseType *r = placeholder->resolve ();
477 : 40 : if (r->get_kind () == TyTy::TypeKind::PROJECTION)
478 : : {
479 : 14 : placeholder->clear_associated_type ();
480 : : }
481 : : }
482 : : }
483 : :
484 : : void
485 : 5528 : AssociatedImplTrait::setup_raw_associated_types ()
486 : : {
487 : 5528 : auto &impl_items = impl->get_impl_items ();
488 : 17897 : for (auto &impl_item : impl_items)
489 : : {
490 : 12369 : bool is_type_alias = impl_item->get_impl_item_type ()
491 : 12369 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
492 : 12369 : if (!is_type_alias)
493 : 11410 : continue;
494 : :
495 : 959 : HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
496 : :
497 : 959 : TraitItemReference *resolved_trait_item = nullptr;
498 : 959 : bool ok
499 : 959 : = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
500 : : &resolved_trait_item);
501 : 959 : if (!ok)
502 : 0 : continue;
503 : 959 : if (resolved_trait_item->get_trait_item_type ()
504 : : != TraitItemReference::TraitItemType::TYPE)
505 : 0 : continue;
506 : :
507 : 959 : TyTy::BaseType *lookup;
508 : 959 : ok = context->lookup_type (type.get_mappings ().get_hirid (), &lookup);
509 : 959 : rust_assert (ok);
510 : :
511 : 959 : resolved_trait_item->associated_type_set (lookup);
512 : : }
513 : 5528 : }
514 : :
515 : : TyTy::BaseType *
516 : 2236 : AssociatedImplTrait::setup_associated_types (
517 : : const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
518 : : TyTy::SubstitutionArgumentMappings *args, bool infer)
519 : : {
520 : : // compute the constrained impl block generic arguments based on self and the
521 : : // higher ranked trait bound
522 : 2236 : TyTy::BaseType *receiver = self->clone ();
523 : :
524 : : // impl<Y> SliceIndex<[Y]> for Range<usize>
525 : : // vs
526 : : // I: SliceIndex<[<integer>]> and Range<<integer>>
527 : : //
528 : : // we need to figure out what Y is
529 : :
530 : 2236 : TyTy::BaseType *associated_self = get_self ();
531 : :
532 : 2236 : rust_debug ("setup_associated_types for: %s->%s bound %s",
533 : : associated_self->debug_str ().c_str (),
534 : : self->debug_str ().c_str (), bound.as_string ().c_str ());
535 : :
536 : : // grab the parameters
537 : 2236 : HIR::ImplBlock &impl_block = *get_impl_block ();
538 : 2236 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
539 : 2635 : for (auto &generic_param : impl_block.get_generic_params ())
540 : : {
541 : 399 : switch (generic_param.get ()->get_kind ())
542 : : {
543 : : case HIR::GenericParam::GenericKind::LIFETIME:
544 : : case HIR::GenericParam::GenericKind::CONST:
545 : : // FIXME: Skipping Lifetime and Const completely until better
546 : : // handling.
547 : : break;
548 : :
549 : 385 : case HIR::GenericParam::GenericKind::TYPE:
550 : 385 : {
551 : 385 : TyTy::BaseType *l = nullptr;
552 : 385 : bool ok = context->lookup_type (
553 : 385 : generic_param->get_mappings ().get_hirid (), &l);
554 : 385 : if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
555 : : {
556 : 385 : substitutions.push_back (TyTy::SubstitutionParamMapping (
557 : 385 : static_cast<HIR::TypeParam &> (*generic_param),
558 : 385 : static_cast<TyTy::ParamType *> (l)));
559 : : }
560 : : }
561 : 385 : break;
562 : : }
563 : : }
564 : :
565 : : // this callback gives us the parameters that get substituted so we can
566 : : // compute the constrained type parameters for this impl block
567 : 4472 : std::map<std::string, HirId> param_mappings;
568 : 2236 : TyTy::ParamSubstCb param_subst_cb
569 : 2236 : = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
570 : 575 : param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
571 : 2236 : };
572 : :
573 : : // generate inference variables for these bound arguments so we can compute
574 : : // their values
575 : 2236 : location_t locus = UNKNOWN_LOCATION;
576 : 4472 : std::vector<TyTy::SubstitutionArg> subst_args;
577 : 2621 : for (auto &p : substitutions)
578 : : {
579 : 385 : if (p.needs_substitution () && infer)
580 : : {
581 : 334 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
582 : 668 : subst_args.push_back (
583 : 334 : TyTy::SubstitutionArg (&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.push_back (TyTy::SubstitutionArg (&p, resolved));
590 : 51 : param_mappings[param->get_symbol ()] = resolved->get_ref ();
591 : : }
592 : : }
593 : :
594 : 2236 : TyTy::SubstitutionArgumentMappings infer_arguments (
595 : : std::move (subst_args), {},
596 : 4472 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
597 : 6708 : locus, param_subst_cb);
598 : 2236 : TyTy::BaseType *impl_self_infer
599 : 2236 : = (!associated_self->is_concrete ())
600 : 2236 : ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
601 : : : associated_self;
602 : :
603 : 2236 : const TyTy::TypeBoundPredicate &impl_predicate
604 : 2236 : = associated_self->lookup_predicate (bound.get_id ());
605 : 2236 : rust_assert (!impl_predicate.is_error ());
606 : :
607 : : // infer the arguments on the predicate
608 : 4472 : std::vector<TyTy::BaseType *> impl_trait_predicate_args;
609 : :
610 : 5455 : for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
611 : : {
612 : 3219 : const auto &arg = impl_predicate.get_substs ().at (i);
613 : 3219 : if (i == 0)
614 : 2236 : 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 : 4472 : std::vector<TyTy::BaseType *> hrtb_bound_arguments;
627 : 5455 : for (size_t i = 0; i < bound.get_substs ().size (); i++)
628 : : {
629 : 3219 : const auto &arg = bound.get_substs ().at (i);
630 : 3219 : if (i == 0)
631 : 2236 : 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 : 2236 : rust_assert (impl_trait_predicate_args.size ()
643 : : == hrtb_bound_arguments.size ());
644 : 3219 : 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 : 4472 : auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
662 : 2236 : TyTy::TyWithLocation (receiver),
663 : 2236 : 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 : 2236 : rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
668 : 2236 : TyTy::BaseType *self_result = result;
669 : :
670 : : // create the argument list
671 : 4472 : std::vector<TyTy::SubstitutionArg> associated_arguments;
672 : 2621 : 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 : 2236 : TyTy::SubstitutionArgumentMappings associated_type_args (
688 : : std::move (associated_arguments), {},
689 : 2236 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
690 : 4472 : locus);
691 : :
692 : 2236 : auto &impl_items = impl->get_impl_items ();
693 : 5241 : for (auto &impl_item : impl_items)
694 : : {
695 : 3005 : bool is_type_alias = impl_item->get_impl_item_type ()
696 : 3005 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
697 : 3005 : if (!is_type_alias)
698 : 2375 : continue;
699 : :
700 : 630 : HIR::TypeAlias &type = *static_cast<HIR::TypeAlias *> (impl_item.get ());
701 : :
702 : 630 : TraitItemReference *resolved_trait_item = nullptr;
703 : 630 : bool ok
704 : 630 : = trait->lookup_trait_item (type.get_new_type_name ().as_string (),
705 : : &resolved_trait_item);
706 : 630 : if (!ok)
707 : 0 : continue;
708 : 630 : if (resolved_trait_item->get_trait_item_type ()
709 : : != TraitItemReference::TraitItemType::TYPE)
710 : 0 : continue;
711 : :
712 : 630 : TyTy::BaseType *lookup;
713 : 630 : if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
714 : 0 : continue;
715 : :
716 : : // this might be generic
717 : 630 : TyTy::BaseType *substituted
718 : 630 : = SubstMapperInternal::Resolve (lookup, associated_type_args);
719 : 630 : resolved_trait_item->associated_type_set (substituted);
720 : : }
721 : :
722 : 2236 : if (args != nullptr)
723 : : {
724 : 85 : *args = associated_type_args;
725 : : }
726 : :
727 : 2236 : return self_result;
728 : 2236 : }
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
|