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