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 : 3299 : ResolveTraitItemToRef::Resolve (
30 : : HIR::TraitItem &item, TyTy::BaseType *self,
31 : : std::vector<TyTy::SubstitutionParamMapping> substitutions)
32 : : {
33 : 3299 : ResolveTraitItemToRef resolver (self, std::move (substitutions));
34 : 3299 : item.accept_vis (resolver);
35 : 3299 : return std::move (resolver.resolved);
36 : 3299 : }
37 : :
38 : : void
39 : 726 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
40 : : {
41 : : // create trait-item-ref
42 : 726 : location_t locus = type.get_locus ();
43 : 726 : bool is_optional = false;
44 : 1452 : std::string identifier = type.get_name ().as_string ();
45 : :
46 : 726 : resolved = TraitItemReference (identifier, is_optional,
47 : : TraitItemReference::TraitItemType::TYPE, &type,
48 : 2178 : self, substitutions, locus);
49 : 726 : }
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 : 2535 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
66 : : {
67 : : // create trait-item-ref
68 : 2535 : location_t locus = fn.get_locus ();
69 : 2535 : bool is_optional = fn.has_definition ();
70 : 5070 : std::string identifier = fn.get_decl ().get_function_name ().as_string ();
71 : :
72 : 2535 : resolved = TraitItemReference (identifier, is_optional,
73 : : TraitItemReference::TraitItemType::FN, &fn,
74 : 7605 : self, std::move (substitutions), locus);
75 : 2535 : }
76 : :
77 : 3299 : ResolveTraitItemToRef::ResolveTraitItemToRef (
78 : : TyTy::BaseType *self,
79 : 3299 : std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
80 : 3299 : : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
81 : 3299 : substitutions (std::move (substitutions))
82 : 3299 : {}
83 : :
84 : : // TraitItemReference items
85 : :
86 : : TraitReference *
87 : 423235 : TraitResolver::Resolve (HIR::TypePath &path)
88 : : {
89 : 423235 : TraitResolver resolver;
90 : 423235 : return resolver.resolve_path (path);
91 : 423235 : }
92 : :
93 : : TraitReference *
94 : 82390 : TraitResolver::Resolve (HIR::Trait &trait)
95 : : {
96 : 82390 : TraitResolver resolver;
97 : 82390 : return resolver.resolve_trait (&trait);
98 : 82390 : }
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 : 1782604 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
109 : : {
110 : 1782604 : TraitResolver resolver;
111 : :
112 : 1782604 : HIR::Trait *lookup = nullptr;
113 : 1782604 : bool ok = resolver.resolve_path_to_trait (path, &lookup);
114 : 1782604 : return ok ? lookup : nullptr;
115 : 1782604 : }
116 : :
117 : 2310164 : TraitResolver::TraitResolver () : TypeCheckBase () {}
118 : :
119 : : bool
120 : 2227774 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
121 : : HIR::Trait **resolved) const
122 : : {
123 : 2227774 : auto &nr_ctx
124 : 2227774 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
125 : :
126 : 2227774 : NodeId ref;
127 : 2227774 : if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
128 : : {
129 : 2227774 : 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 : 2227774 : auto hid = mappings.lookup_node_to_hir (ref);
138 : 2227774 : 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 : 2227774 : auto resolved_item = mappings.lookup_hir_item (hid.value ());
145 : 2227774 : if (!resolved_item.has_value ())
146 : : {
147 : 3 : rust_error_at (path.get_locus (),
148 : : "Failed to resolve trait by looking up hir node");
149 : 3 : return false;
150 : : }
151 : :
152 : 2227771 : 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 : 2227769 : *resolved = static_cast<HIR::Trait *> (*resolved_item);
162 : 2227769 : return true;
163 : : }
164 : :
165 : : TraitReference *
166 : 423235 : TraitResolver::resolve_path (HIR::TypePath &path)
167 : : {
168 : 423235 : HIR::Trait *resolved_trait_reference;
169 : 423235 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
170 : 423235 : if (!ok)
171 : 5 : return &TraitReference::error_node ();
172 : :
173 : 423230 : return resolve_trait (resolved_trait_reference);
174 : : }
175 : :
176 : : TraitReference *
177 : 505620 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
178 : : {
179 : 505620 : TraitReference *tref = &TraitReference::error_node ();
180 : 505620 : if (context->lookup_trait_reference (
181 : 505620 : trait_reference->get_mappings ().get_defid (), &tref))
182 : : {
183 : 501946 : return tref;
184 : : }
185 : :
186 : 3674 : DefId trait_id = trait_reference->get_mappings ().get_defid ();
187 : 3674 : 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 : 3670 : TraitQueryGuard guard (trait_id);
197 : 3670 : TyTy::BaseType *self = nullptr;
198 : 3670 : 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 : 7990 : for (auto &generic_param : trait_reference->get_generic_params ())
203 : : {
204 : 4320 : 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 : 4311 : case HIR::GenericParam::GenericKind::TYPE:
213 : 4311 : {
214 : 4311 : auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
215 : 4311 : bool is_self
216 : 4311 : = typaram.get_type_representation ().as_string ().compare ("Self")
217 : 4311 : == 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 : 4311 : bool apply_sized = !is_self;
222 : 4311 : auto param_type
223 : 4311 : = TypeResolveGenericParam::Resolve (*generic_param, true,
224 : 4311 : apply_sized);
225 : :
226 : 4311 : context->insert_type (generic_param->get_mappings (), param_type);
227 : 4311 : substitutions.emplace_back (typaram, param_type);
228 : :
229 : 4311 : if (is_self)
230 : : {
231 : 3670 : rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
232 : 3670 : TyTy::ParamType *p
233 : : = static_cast<TyTy::ParamType *> (param_type);
234 : 3670 : p->set_implicit_self_trait ();
235 : 3670 : self = p;
236 : : }
237 : : }
238 : 4311 : break;
239 : : }
240 : : }
241 : 3670 : rust_assert (self != nullptr);
242 : :
243 : : // Check if there is a super-trait, and apply this bound to the Self
244 : : // TypeParam
245 : 7340 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
246 : :
247 : : // copy the substitition mappings
248 : 3670 : std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
249 : 3670 : self_subst_copy.reserve (substitutions.size ());
250 : :
251 : 7981 : for (auto &sub : substitutions)
252 : 4311 : 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 : 3670 : specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
257 : : std::move (self_subst_copy),
258 : 7340 : BoundPolarity::RegularBound,
259 : 3670 : trait_reference->get_locus ());
260 : :
261 : : // look for any
262 : 7340 : std::vector<TyTy::TypeBoundPredicate> super_traits;
263 : 3670 : 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 : 3662 : self->inherit_bounds (specified_bounds);
286 : :
287 : 3662 : context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
288 : 7324 : std::vector<TraitItemReference> item_refs;
289 : 6961 : for (auto &item : trait_reference->get_trait_items ())
290 : : {
291 : : // make a copy of the substs
292 : 3299 : std::vector<TyTy::SubstitutionParamMapping> item_subst;
293 : 3299 : item_subst.reserve (substitutions.size ());
294 : :
295 : 8023 : for (auto &sub : substitutions)
296 : 4724 : item_subst.push_back (sub.clone ());
297 : :
298 : 3299 : TraitItemReference trait_item_ref
299 : 3299 : = ResolveTraitItemToRef::Resolve (*item.get (), self,
300 : 3299 : std::move (item_subst));
301 : 3299 : item_refs.push_back (std::move (trait_item_ref));
302 : 3299 : }
303 : :
304 : 3662 : TraitReference trait_object (trait_reference, item_refs, super_traits,
305 : 3662 : std::move (substitutions));
306 : 3662 : context->insert_trait_reference (
307 : 3662 : trait_reference->get_mappings ().get_defid (), std::move (trait_object));
308 : :
309 : 3662 : tref = &TraitReference::error_node ();
310 : 3662 : bool ok = context->lookup_trait_reference (
311 : 3662 : trait_reference->get_mappings ().get_defid (), &tref);
312 : 3662 : 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 : 3662 : tref->on_resolved ();
318 : 3662 : context->block_context ().exit ();
319 : :
320 : 3662 : return tref;
321 : 3670 : }
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 : 3299 : TraitItemReference::on_resolved ()
342 : : {
343 : 3299 : switch (type)
344 : : {
345 : 38 : case CONST:
346 : 38 : resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
347 : 38 : break;
348 : :
349 : 726 : case TYPE:
350 : 726 : resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
351 : 726 : break;
352 : :
353 : 2535 : case FN:
354 : 2535 : resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
355 : 2535 : break;
356 : :
357 : : default:
358 : : break;
359 : : }
360 : 3299 : }
361 : :
362 : : void
363 : 726 : TraitItemReference::resolve_item (HIR::TraitItemType &type)
364 : : {
365 : 726 : TyTy::BaseType *ty
366 : 726 : = new TyTy::PlaceholderType (type.get_name ().as_string (),
367 : 726 : type.get_mappings ().get_defid (),
368 : 1452 : type.get_mappings ().get_hirid ());
369 : 726 : context->insert_type (type.get_mappings (), ty);
370 : 726 : }
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 : 2535 : TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
399 : : {
400 : 2535 : TyTy::BaseType *item_tyty = get_tyty ();
401 : 2535 : if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
402 : : return;
403 : :
404 : 2533 : 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 : 2943 : TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
431 : : {
432 : 2943 : 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 : 2943 : TyTy::BaseType *item_ty = get_tyty ();
443 : 2943 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
444 : 2943 : TyTy::PlaceholderType *placeholder
445 : : = static_cast<TyTy::PlaceholderType *> (item_ty);
446 : :
447 : 2943 : if (ty->is<TyTy::ProjectionType> ())
448 : : {
449 : 2755 : const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
450 : 2755 : const auto resolved = projection.get ();
451 : 2755 : if (resolved == item_ty)
452 : : return;
453 : : }
454 : :
455 : 2943 : placeholder->set_associated_type (ty->get_ty_ref ());
456 : : }
457 : :
458 : : void
459 : 1344 : TraitItemReference::associated_type_reset (bool only_projections) const
460 : : {
461 : 1344 : rust_assert (get_trait_item_type () == TraitItemType::TYPE);
462 : :
463 : 1344 : TyTy::BaseType *item_ty = get_tyty ();
464 : 1344 : rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
465 : 1344 : TyTy::PlaceholderType *placeholder
466 : : = static_cast<TyTy::PlaceholderType *> (item_ty);
467 : :
468 : 1344 : if (!only_projections)
469 : : {
470 : 1168 : 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 : 2235 : 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 : 2235 : 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 : 2235 : TyTy::BaseType *associated_self = get_self ();
532 : :
533 : 2235 : 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 : 2235 : HIR::ImplBlock &impl_block = *get_impl_block ();
539 : 2235 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
540 : 2634 : 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 : 4470 : std::map<std::string, HirId> param_mappings;
569 : 2235 : TyTy::ParamSubstCb param_subst_cb
570 : 2235 : = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
571 : 575 : param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
572 : 2235 : };
573 : :
574 : : // generate inference variables for these bound arguments so we can compute
575 : : // their values
576 : 2235 : location_t locus = UNKNOWN_LOCATION;
577 : 4470 : std::vector<TyTy::SubstitutionArg> subst_args;
578 : 2620 : 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 : 2235 : TyTy::SubstitutionArgumentMappings infer_arguments (
595 : : std::move (subst_args), {},
596 : 4470 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
597 : 6705 : locus, param_subst_cb);
598 : 2235 : TyTy::BaseType *impl_self_infer
599 : 2235 : = (!associated_self->is_concrete ())
600 : 2235 : ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
601 : : : associated_self;
602 : :
603 : 2235 : const TyTy::TypeBoundPredicate &impl_predicate
604 : 2235 : = associated_self->lookup_predicate (bound.get_id ());
605 : 2235 : rust_assert (!impl_predicate.is_error ());
606 : :
607 : : // infer the arguments on the predicate
608 : 4470 : std::vector<TyTy::BaseType *> impl_trait_predicate_args;
609 : :
610 : 5453 : for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
611 : : {
612 : 3218 : const auto &arg = impl_predicate.get_substs ().at (i);
613 : 3218 : if (i == 0)
614 : 2235 : 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 : 4470 : std::vector<TyTy::BaseType *> hrtb_bound_arguments;
627 : 5453 : for (size_t i = 0; i < bound.get_substs ().size (); i++)
628 : : {
629 : 3218 : const auto &arg = bound.get_substs ().at (i);
630 : 3218 : if (i == 0)
631 : 2235 : 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 : 2235 : rust_assert (impl_trait_predicate_args.size ()
643 : : == hrtb_bound_arguments.size ());
644 : 3218 : 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 : 4470 : auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
662 : 2235 : TyTy::TyWithLocation (receiver),
663 : 2235 : 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 : 2235 : rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
668 : 2235 : TyTy::BaseType *self_result = result;
669 : :
670 : : // create the argument list
671 : 4470 : std::vector<TyTy::SubstitutionArg> associated_arguments;
672 : 2620 : 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 : 2235 : TyTy::SubstitutionArgumentMappings associated_type_args (
688 : : std::move (associated_arguments), {},
689 : 2235 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (args),
690 : 4470 : locus);
691 : :
692 : 2235 : auto &impl_items = impl->get_impl_items ();
693 : 5239 : for (auto &impl_item : impl_items)
694 : : {
695 : 3004 : bool is_type_alias = impl_item->get_impl_item_type ()
696 : 3004 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
697 : 3004 : if (!is_type_alias)
698 : 2374 : 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 : 2235 : if (args != nullptr)
723 : : {
724 : 85 : *args = associated_type_args;
725 : : }
726 : :
727 : 2235 : return self_result;
728 : 2235 : }
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
|