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