Line data Source code
1 : // Copyright (C) 2021-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "rust-hir-trait-resolve.h"
20 : #include "rust-hir-trait-reference.h"
21 : #include "rust-hir-type-check-expr.h"
22 : #include "rust-rib.h"
23 : #include "rust-substitution-mapper.h"
24 : #include "rust-type-util.h"
25 : #include "rust-finalized-name-resolution-context.h"
26 :
27 : namespace Rust {
28 : namespace Resolver {
29 :
30 : TraitItemReference
31 3355 : ResolveTraitItemToRef::Resolve (
32 : HIR::TraitItem &item, TyTy::BaseType *self,
33 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
34 : {
35 3355 : ResolveTraitItemToRef resolver (self, std::move (substitutions));
36 3355 : item.accept_vis (resolver);
37 3355 : return std::move (resolver.resolved);
38 3355 : }
39 :
40 : void
41 739 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
42 : {
43 : // create trait-item-ref
44 739 : location_t locus = type.get_locus ();
45 739 : bool is_optional = false;
46 1478 : std::string identifier = type.get_name ().as_string ();
47 :
48 739 : resolved = TraitItemReference (identifier, is_optional,
49 : TraitItemReference::TraitItemType::TYPE, &type,
50 2217 : self, substitutions, locus);
51 739 : }
52 :
53 : void
54 39 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
55 : {
56 : // create trait-item-ref
57 39 : location_t locus = cst.get_locus ();
58 39 : bool is_optional = cst.has_expr ();
59 78 : std::string identifier = cst.get_name ().as_string ();
60 :
61 39 : resolved = TraitItemReference (identifier, is_optional,
62 : TraitItemReference::TraitItemType::CONST, &cst,
63 117 : self, substitutions, locus);
64 39 : }
65 :
66 : void
67 2577 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
68 : {
69 : // create trait-item-ref
70 2577 : location_t locus = fn.get_locus ();
71 2577 : bool is_optional = fn.has_definition ();
72 5154 : std::string identifier = fn.get_decl ().get_function_name ().as_string ();
73 :
74 2577 : resolved = TraitItemReference (identifier, is_optional,
75 : TraitItemReference::TraitItemType::FN, &fn,
76 7731 : self, std::move (substitutions), locus);
77 2577 : }
78 :
79 3355 : ResolveTraitItemToRef::ResolveTraitItemToRef (
80 : TyTy::BaseType *self,
81 3355 : std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
82 3355 : : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
83 3355 : substitutions (std::move (substitutions))
84 3355 : {}
85 :
86 : // TraitItemReference items
87 :
88 : TraitReference *
89 496306 : TraitResolver::Resolve (HIR::TypePath &path)
90 : {
91 496306 : TraitResolver resolver;
92 496306 : return resolver.resolve_path (path);
93 496306 : }
94 :
95 : TraitReference *
96 96871 : TraitResolver::Resolve (HIR::Trait &trait)
97 : {
98 96871 : TraitResolver resolver;
99 96871 : return resolver.resolve_trait (&trait);
100 96871 : }
101 :
102 : TraitReference *
103 21990 : TraitResolver::Lookup (HIR::TypePath &path)
104 : {
105 21990 : TraitResolver resolver;
106 21990 : return resolver.lookup_path (path);
107 21990 : }
108 :
109 : HIR::Trait *
110 2234012 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
111 : {
112 2234012 : TraitResolver resolver;
113 :
114 2234012 : HIR::Trait *lookup = nullptr;
115 2234012 : bool ok = resolver.resolve_path_to_trait (path, &lookup);
116 2234012 : return ok ? lookup : nullptr;
117 2234012 : }
118 :
119 2849179 : TraitResolver::TraitResolver () : TypeCheckBase () {}
120 :
121 : bool
122 2752308 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
123 : HIR::Trait **resolved) const
124 : {
125 2752308 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
126 :
127 2752308 : NodeId ref;
128 2752308 : if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid (),
129 2752308 : Resolver2_0::Namespace::Types))
130 : {
131 2752308 : ref = *ref_opt;
132 : }
133 : else
134 : {
135 0 : rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
136 0 : return false;
137 : }
138 :
139 2752308 : auto hid = mappings.lookup_node_to_hir (ref);
140 2752308 : if (!hid)
141 : {
142 0 : rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
143 0 : return false;
144 : }
145 :
146 2752308 : auto resolved_item = mappings.lookup_hir_item (hid.value ());
147 2752308 : if (!resolved_item.has_value ())
148 : {
149 0 : rust_error_at (path.get_locus (),
150 : "Failed to resolve trait by looking up hir node");
151 0 : return false;
152 : }
153 :
154 2752308 : if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
155 : {
156 3 : rich_location r (line_table, path.get_locus ());
157 3 : r.add_fixit_replace ("not a trait");
158 3 : rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
159 6 : path.as_simple_path ().as_string ().c_str ());
160 3 : return false;
161 3 : }
162 :
163 2752305 : *resolved = static_cast<HIR::Trait *> (*resolved_item);
164 2752305 : return true;
165 : }
166 :
167 : TraitReference *
168 496306 : TraitResolver::resolve_path (HIR::TypePath &path)
169 : {
170 496306 : HIR::Trait *resolved_trait_reference;
171 496306 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
172 496306 : if (!ok)
173 3 : return &TraitReference::error_node ();
174 :
175 496303 : return resolve_trait (resolved_trait_reference);
176 : }
177 :
178 : TraitReference *
179 593174 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
180 : {
181 593174 : TraitReference *tref = &TraitReference::error_node ();
182 593174 : if (context->lookup_trait_reference (
183 593174 : trait_reference->get_mappings ().get_defid (), &tref))
184 : {
185 589236 : return tref;
186 : }
187 :
188 3938 : DefId trait_id = trait_reference->get_mappings ().get_defid ();
189 3938 : if (context->trait_query_in_progress (trait_id))
190 : {
191 4 : rust_error_at (
192 : trait_reference->get_locus (), ErrorCode::E0391,
193 : "cycle detected when computing the super predicates of %qs",
194 4 : trait_reference->get_name ().as_string ().c_str ());
195 4 : return &TraitReference::error_node ();
196 : }
197 :
198 3934 : TraitQueryGuard guard (trait_id);
199 3934 : TyTy::BaseType *self = nullptr;
200 3934 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
201 :
202 : // this needs to be special cased for the sized trait to not auto implemented
203 : // Sized on Self
204 8514 : for (auto &generic_param : trait_reference->get_generic_params ())
205 : {
206 4580 : switch (generic_param.get ()->get_kind ())
207 : {
208 : case HIR::GenericParam::GenericKind::LIFETIME:
209 : case HIR::GenericParam::GenericKind::CONST:
210 : // FIXME: Skipping Lifetime and Const completely until better
211 : // handling.
212 : break;
213 :
214 4578 : case HIR::GenericParam::GenericKind::TYPE:
215 4578 : {
216 4578 : auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
217 4578 : bool is_self
218 4578 : = typaram.get_type_representation ().as_string ().compare ("Self")
219 4578 : == 0;
220 :
221 : // https://doc.rust-lang.org/std/marker/trait.Sized.html
222 : // The one exception is the implicit Self type of a trait
223 4578 : bool apply_sized = !is_self;
224 4578 : auto param_type
225 4578 : = TypeResolveGenericParam::Resolve (*generic_param, true,
226 4578 : apply_sized);
227 :
228 4578 : context->insert_type (generic_param->get_mappings (), param_type);
229 4578 : substitutions.emplace_back (typaram, param_type);
230 :
231 4578 : if (is_self)
232 : {
233 3934 : rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
234 3934 : TyTy::ParamType *p
235 : = static_cast<TyTy::ParamType *> (param_type);
236 3934 : p->set_implicit_self_trait ();
237 3934 : self = p;
238 : }
239 : }
240 4578 : break;
241 : }
242 : }
243 3934 : rust_assert (self != nullptr);
244 :
245 : // Check if there is a super-trait, and apply this bound to the Self
246 : // TypeParam
247 7868 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
248 :
249 : // copy the substitition mappings
250 3934 : std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
251 3934 : self_subst_copy.reserve (substitutions.size ());
252 :
253 8512 : for (auto &sub : substitutions)
254 4578 : self_subst_copy.push_back (sub.clone ());
255 :
256 : // They also inherit themselves as a bound this enables a trait item to
257 : // reference other Self::trait_items
258 3934 : specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
259 : std::move (self_subst_copy),
260 7868 : BoundPolarity::RegularBound,
261 3934 : trait_reference->get_locus ());
262 :
263 : // look for any
264 7868 : std::vector<TyTy::TypeBoundPredicate> super_traits;
265 3934 : if (trait_reference->has_type_param_bounds ())
266 : {
267 1154 : for (auto &bound : trait_reference->get_type_param_bounds ())
268 : {
269 626 : if (bound->get_bound_type ()
270 : == HIR::TypeParamBound::BoundType::TRAITBOUND)
271 : {
272 626 : HIR::TraitBound *b
273 626 : = static_cast<HIR::TraitBound *> (bound.get ());
274 :
275 626 : auto predicate = get_predicate_from_bound (
276 : b->get_path (),
277 : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
278 626 : BoundPolarity::RegularBound, false, true);
279 626 : if (predicate.is_error ())
280 19 : return &TraitReference::error_node ();
281 :
282 607 : specified_bounds.push_back (predicate);
283 607 : super_traits.push_back (predicate);
284 626 : }
285 : }
286 : }
287 3915 : self->inherit_bounds (specified_bounds);
288 :
289 3915 : context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
290 7830 : std::vector<TraitItemReference> item_refs;
291 7270 : for (auto &item : trait_reference->get_trait_items ())
292 : {
293 : // make a copy of the substs
294 3355 : std::vector<TyTy::SubstitutionParamMapping> item_subst;
295 3355 : item_subst.reserve (substitutions.size ());
296 :
297 8136 : for (auto &sub : substitutions)
298 4781 : item_subst.push_back (sub.clone ());
299 :
300 3355 : TraitItemReference trait_item_ref
301 3355 : = ResolveTraitItemToRef::Resolve (*item.get (), self,
302 3355 : std::move (item_subst));
303 3355 : item_refs.push_back (std::move (trait_item_ref));
304 3355 : }
305 :
306 3915 : TraitReference trait_object (trait_reference, item_refs, super_traits,
307 3915 : std::move (substitutions));
308 3915 : context->insert_trait_reference (
309 3915 : trait_reference->get_mappings ().get_defid (), std::move (trait_object));
310 :
311 3915 : tref = &TraitReference::error_node ();
312 3915 : bool ok = context->lookup_trait_reference (
313 3915 : trait_reference->get_mappings ().get_defid (), &tref);
314 3915 : rust_assert (ok);
315 :
316 : // hook to allow the trait to resolve its optional item blocks, we cant
317 : // resolve the blocks of functions etc because it can end up in a recursive
318 : // loop of trying to resolve traits as required by the types
319 3915 : tref->on_resolved ();
320 3915 : context->block_context ().exit ();
321 :
322 3915 : return tref;
323 3934 : }
324 :
325 : TraitReference *
326 21990 : TraitResolver::lookup_path (HIR::TypePath &path)
327 : {
328 21990 : HIR::Trait *resolved_trait_reference;
329 21990 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
330 21990 : if (!ok)
331 0 : return &TraitReference::error_node ();
332 :
333 21990 : TraitReference *tref = &TraitReference::error_node ();
334 21990 : if (context->lookup_trait_reference (
335 21990 : resolved_trait_reference->get_mappings ().get_defid (), &tref))
336 : {
337 21990 : return tref;
338 : }
339 0 : return &TraitReference::error_node ();
340 : }
341 :
342 : void
343 3355 : TraitItemReference::on_resolved (const TraitReference *tref)
344 : {
345 3355 : switch (type)
346 : {
347 39 : case CONST:
348 39 : resolve_item (tref, static_cast<HIR::TraitItemConst &> (*hir_trait_item));
349 39 : break;
350 :
351 739 : case TYPE:
352 739 : resolve_item (tref, static_cast<HIR::TraitItemType &> (*hir_trait_item));
353 739 : break;
354 :
355 2577 : case FN:
356 2577 : resolve_item (tref, static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
357 2577 : break;
358 :
359 : default:
360 : break;
361 : }
362 3355 : }
363 :
364 : void
365 739 : TraitItemReference::resolve_item (const TraitReference *tref,
366 : HIR::TraitItemType &type)
367 : {
368 739 : auto substitutions = inherited_substitutions;
369 739 : if (type.has_generics ())
370 : {
371 17 : auto binder_pin = context->push_lifetime_binder ();
372 17 : TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::TypeAlias,
373 : type.get_locus (),
374 17 : type.get_generic_params (),
375 : substitutions, false, ABI::RUST);
376 17 : }
377 :
378 739 : size_t inherited_count = inherited_substitutions.size ();
379 739 : auto projection
380 739 : = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), nullptr,
381 739 : tref, type.get_mappings ().get_defid (),
382 : substitutions, self,
383 1478 : TyTy::SubstitutionArgumentMappings::error (),
384 1478 : {}, {}, inherited_count);
385 :
386 : // Attach the bounds declared on the associated type itself:
387 : //
388 : // type IntoIter: Iterator<Item = Self::Item>
389 : //
390 : // so satisfies_bound finds them in specified_bounds
391 739 : if (type.has_type_param_bounds ())
392 : {
393 36 : std::vector<TyTy::TypeBoundPredicate> trait_item_bounds;
394 72 : for (auto &bound : type.get_type_param_bounds ())
395 : {
396 36 : if (bound->get_bound_type ()
397 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
398 0 : continue;
399 36 : auto *b = static_cast<HIR::TraitBound *> (bound.get ());
400 36 : auto predicate = TypeCheckBase::ResolvePredicateFromBound (
401 : b->get_path (),
402 : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
403 36 : BoundPolarity::RegularBound, false, true);
404 36 : if (!predicate.is_error ())
405 36 : trait_item_bounds.push_back (std::move (predicate));
406 36 : }
407 36 : if (!trait_item_bounds.empty ())
408 36 : projection->inherit_bounds (trait_item_bounds);
409 36 : }
410 :
411 739 : context->insert_type (type.get_mappings (), projection);
412 739 : }
413 :
414 : void
415 39 : TraitItemReference::resolve_item (const TraitReference *tref,
416 : HIR::TraitItemConst &constant)
417 : {
418 39 : TyTy::BaseType *ty = nullptr;
419 39 : if (constant.has_type ())
420 11 : ty = TypeCheckType::Resolve (constant.get_type ());
421 :
422 39 : TyTy::BaseType *expr = nullptr;
423 39 : if (constant.has_expr ())
424 11 : expr = TypeCheckExpr::Resolve (constant.get_expr ());
425 :
426 50 : bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
427 50 : bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
428 :
429 10 : if (have_specified_ty && have_expr_ty)
430 : {
431 20 : coercion_site (constant.get_mappings ().get_hirid (),
432 : TyTy::TyWithLocation (ty,
433 10 : constant.get_type ().get_locus ()),
434 : TyTy::TyWithLocation (expr,
435 10 : constant.get_expr ().get_locus ()),
436 : constant.get_locus ());
437 : }
438 39 : }
439 :
440 : void
441 2577 : TraitItemReference::resolve_item (const TraitReference *tref,
442 : HIR::TraitItemFunc &func)
443 : {
444 2577 : TyTy::BaseType *item_tyty = get_tyty ();
445 2577 : if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
446 : return;
447 :
448 2575 : if (!is_optional ())
449 : return;
450 :
451 : // check the block and return types
452 858 : rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
453 :
454 : // need to get the return type from this
455 858 : TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
456 858 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
457 858 : context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
458 :
459 858 : auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
460 :
461 858 : location_t fn_return_locus
462 858 : = func.get_decl ().has_return_type ()
463 858 : ? func.get_decl ().get_return_type ().get_locus ()
464 193 : : func.get_locus ();
465 :
466 1716 : coercion_site (func.get_mappings ().get_hirid (),
467 858 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
468 858 : TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
469 :
470 858 : context->pop_return_type ();
471 : }
472 :
473 : TyTy::SubstitutionArgumentMappings
474 3220 : AssociatedImplTrait::bind_impl_for_projection (TyTy::ProjectionType &proj,
475 : location_t locus)
476 : {
477 3220 : std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
478 6158 : for (auto &generic_param : impl->get_generic_params ())
479 : {
480 2938 : if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE)
481 232 : continue;
482 2938 : TyTy::BaseType *l = nullptr;
483 2938 : bool ok
484 2938 : = context->lookup_type (generic_param->get_mappings ().get_hirid (),
485 : &l);
486 2938 : if (!ok || l->get_kind () != TyTy::TypeKind::PARAM)
487 232 : continue;
488 2706 : impl_substitutions.emplace_back (static_cast<HIR::TypeParam &> (
489 2706 : *generic_param),
490 2706 : static_cast<TyTy::ParamType *> (l));
491 : }
492 :
493 : // Build infer args for each impl param so we dont mutate the impls own
494 : // ParamTys when unifying. param_mappings records impl_param_symbol ->
495 : // hirid_of_fresh_infer_var so we can read out what each param resolved to
496 : // after unification.
497 3220 : std::vector<TyTy::SubstitutionArg> infer_arg_vec;
498 3220 : std::map<std::string, HirId> param_mappings;
499 5926 : for (auto &p : impl_substitutions)
500 : {
501 2706 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
502 2706 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
503 2706 : TyTy::BaseType *resolved = infer_var.get_tyty ();
504 2706 : infer_arg_vec.emplace_back (&p, resolved);
505 2706 : param_mappings[symbol] = resolved->get_ref ();
506 2706 : }
507 3220 : TyTy::SubstitutionArgumentMappings infer_arguments (
508 : std::move (infer_arg_vec), {} /*binding_args*/,
509 3220 : TyTy::RegionParamList (0) /*regions*/, locus);
510 :
511 3220 : TyTy::BaseType *impl_self_infer
512 3220 : = !self->is_concrete ()
513 3220 : ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
514 843 : : self->clone ();
515 :
516 : // sub the impls trait predicate args with infers:
517 : // SliceIndex<[Y]> -> SliceIndex<[?Y]>
518 3220 : const TyTy::TypeBoundPredicate &impl_predicate = predicate;
519 3220 : std::vector<TyTy::BaseType *> impl_predicate_args;
520 3675 : for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
521 : {
522 455 : auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
523 455 : TyTy::BaseType *r = p->resolve ();
524 455 : if (!r->is_concrete ())
525 364 : r = SubstMapperInternal::Resolve (r, infer_arguments);
526 455 : impl_predicate_args.push_back (r);
527 : }
528 :
529 : // Read the projections own (trait-coord) substs and skip Self at index 0.
530 : // The projection's substs match by symbol in handle_substitions, so a
531 : // fn-level substitution that binds T won't have walked into the
532 : // projections X slot whose resolved value is [T]. Re-apply the
533 : // projections own used_arguments to each arg so any stale impl-coord
534 : // params inside (the T inside [T]) are followed through to their
535 : // current bindings
536 3220 : TyTy::SubstitutionArgumentMappings proj_used
537 3220 : = proj.get_substitution_arguments ();
538 3220 : std::vector<TyTy::BaseType *> proj_args;
539 3682 : for (size_t i = 1; i < proj.get_substs ().size (); i++)
540 : {
541 462 : auto p = proj.get_substs ().at (i).get_param_ty ();
542 462 : TyTy::BaseType *r = p->resolve ();
543 462 : if (!r->is_concrete () && !proj_used.is_empty ())
544 14 : r = SubstMapperInternal::Resolve (r, proj_used);
545 462 : proj_args.push_back (r);
546 : }
547 :
548 3220 : if (impl_predicate_args.size () != proj_args.size ())
549 7 : return TyTy::SubstitutionArgumentMappings::error ();
550 :
551 : // unify trait args [?Y] -> [{integer}]
552 3668 : for (size_t i = 0; i < proj_args.size (); i++)
553 : {
554 455 : TyTy::BaseType *proj_arg = proj_args[i];
555 455 : if (impl_predicate_args[i]->get_kind () == TyTy::TypeKind::SLICE
556 455 : && proj_arg->get_kind () != TyTy::TypeKind::SLICE)
557 : {
558 252 : auto &mappings = Analysis::Mappings::get ();
559 252 : HirId id = mappings.get_next_hir_id ();
560 252 : auto *wrapped
561 : = new TyTy::SliceType (id, proj_arg->get_locus (),
562 252 : TyTy::TyVar (proj_arg->get_ref ()));
563 252 : context->insert_implicit_type (id, wrapped);
564 252 : proj_arg = wrapped;
565 : }
566 :
567 455 : auto *res = unify_site_and (0 /*id*/,
568 455 : TyTy::TyWithLocation (impl_predicate_args[i]),
569 455 : TyTy::TyWithLocation (proj_arg), locus,
570 : false /*emit_errors*/, true /*commit_if_ok*/,
571 : true /*infer*/, true /*cleanup_on_fail*/,
572 : false /*check_bounds*/);
573 455 : if (res->get_kind () == TyTy::TypeKind::ERROR)
574 0 : return TyTy::SubstitutionArgumentMappings::error ();
575 : }
576 :
577 : // unify self Range<{integer}> -> Range<usize>
578 3213 : auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
579 3213 : TyTy::TyWithLocation (proj.get_self ()),
580 3213 : TyTy::TyWithLocation (impl_self_infer), locus,
581 : false /*emit_errors*/, true /*commit_if_ok*/,
582 : true /*infer*/, true /*cleanup_on_fail*/,
583 : false /*check_bounds*/);
584 3213 : if (res->get_kind () == TyTy::TypeKind::ERROR)
585 0 : return TyTy::SubstitutionArgumentMappings::error ();
586 :
587 3213 : std::vector<TyTy::SubstitutionArg> resolved_args;
588 5919 : for (auto &p : impl_substitutions)
589 : {
590 2706 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
591 2706 : auto it = param_mappings.find (symbol);
592 2706 : if (it == param_mappings.end ())
593 0 : continue;
594 2706 : TyTy::BaseType *r = nullptr;
595 2706 : bool ok = context->lookup_type (it->second, &r);
596 2706 : if (!ok)
597 0 : continue;
598 2706 : resolved_args.emplace_back (&p, r);
599 2706 : }
600 :
601 3213 : return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
602 : {} /*binding_args*/,
603 3213 : TyTy::RegionParamList (0)
604 : /*regions*/,
605 6426 : locus);
606 6433 : }
607 :
608 : TyTy::SubstitutionArgumentMappings
609 1966 : AssociatedImplTrait::bind_impl_for_bound (TyTy::BaseType *receiver,
610 : const TyTy::TypeBoundPredicate &bound,
611 : location_t locus)
612 : {
613 : // Same shape as bind_impl_for_projection but the receiver/trait-args are
614 : // taken from the (binding, bound) pair instead of a ProjectionType.
615 1966 : std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
616 2280 : for (auto &generic_param : impl->get_generic_params ())
617 : {
618 314 : if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE)
619 15 : continue;
620 299 : TyTy::BaseType *l = nullptr;
621 299 : bool ok
622 299 : = context->lookup_type (generic_param->get_mappings ().get_hirid (),
623 : &l);
624 299 : if (!ok || l->get_kind () != TyTy::TypeKind::PARAM)
625 0 : continue;
626 299 : impl_substitutions.emplace_back (static_cast<HIR::TypeParam &> (
627 299 : *generic_param),
628 299 : static_cast<TyTy::ParamType *> (l));
629 : }
630 :
631 1966 : std::vector<TyTy::SubstitutionArg> infer_arg_vec;
632 1966 : std::map<std::string, HirId> param_mappings;
633 2265 : for (auto &p : impl_substitutions)
634 : {
635 299 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
636 299 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
637 299 : TyTy::BaseType *resolved = infer_var.get_tyty ();
638 299 : infer_arg_vec.emplace_back (&p, resolved);
639 299 : param_mappings[symbol] = resolved->get_ref ();
640 299 : }
641 1966 : TyTy::SubstitutionArgumentMappings infer_arguments (
642 : std::move (infer_arg_vec), {} /*binding_args*/,
643 1966 : TyTy::RegionParamList (0) /*regions*/, locus);
644 :
645 1966 : TyTy::BaseType *impl_self_infer
646 1966 : = !self->is_concrete ()
647 1966 : ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
648 1802 : : self->clone ();
649 :
650 1966 : const TyTy::TypeBoundPredicate &impl_predicate = predicate;
651 1966 : std::vector<TyTy::BaseType *> impl_predicate_args;
652 2848 : for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
653 : {
654 882 : auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
655 882 : TyTy::BaseType *r = p->resolve ();
656 882 : if (!r->is_concrete ())
657 235 : r = SubstMapperInternal::Resolve (r, infer_arguments);
658 882 : impl_predicate_args.push_back (r);
659 : }
660 :
661 : // Trait args from the bound predicate the caller passed in (skip Self).
662 : // Apply the bound's own used_arguments so any stale impl-coord params
663 : // inside follow through to their current bindings.
664 1966 : TyTy::SubstitutionArgumentMappings bound_used
665 1966 : = bound.get_substitution_arguments ();
666 1966 : std::vector<TyTy::BaseType *> bound_args;
667 2848 : for (size_t i = 1; i < bound.get_substs ().size (); i++)
668 : {
669 882 : auto p = bound.get_substs ().at (i).get_param_ty ();
670 882 : TyTy::BaseType *r = p->resolve ();
671 882 : if (!r->is_concrete () && !bound_used.is_empty ())
672 0 : r = SubstMapperInternal::Resolve (r, bound_used);
673 882 : bound_args.push_back (r);
674 : }
675 :
676 1966 : if (impl_predicate_args.size () != bound_args.size ())
677 0 : return TyTy::SubstitutionArgumentMappings::error ();
678 :
679 2848 : for (size_t i = 0; i < bound_args.size (); i++)
680 : {
681 1764 : auto *res = unify_site_and (0 /*id*/,
682 882 : TyTy::TyWithLocation (impl_predicate_args[i]),
683 882 : TyTy::TyWithLocation (bound_args[i]), locus,
684 : false /*emit_errors*/, true /*commit_if_ok*/,
685 : true /*infer*/, true /*cleanup_on_fail*/,
686 : false /*check_bounds*/);
687 882 : if (res->get_kind () == TyTy::TypeKind::ERROR)
688 0 : return TyTy::SubstitutionArgumentMappings::error ();
689 : }
690 :
691 1966 : auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
692 1966 : TyTy::TyWithLocation (receiver),
693 1966 : TyTy::TyWithLocation (impl_self_infer), locus,
694 : false /*emit_errors*/, true /*commit_if_ok*/,
695 : true /*infer*/, true /*cleanup_on_fail*/,
696 : false /*check_bounds*/);
697 1966 : if (res->get_kind () == TyTy::TypeKind::ERROR)
698 0 : return TyTy::SubstitutionArgumentMappings::error ();
699 :
700 1966 : std::vector<TyTy::SubstitutionArg> resolved_args;
701 2265 : for (auto &p : impl_substitutions)
702 : {
703 299 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
704 299 : auto it = param_mappings.find (symbol);
705 299 : if (it == param_mappings.end ())
706 0 : continue;
707 299 : TyTy::BaseType *r = nullptr;
708 299 : bool ok = context->lookup_type (it->second, &r);
709 299 : if (!ok)
710 0 : continue;
711 299 : resolved_args.emplace_back (&p, r);
712 299 : }
713 :
714 1966 : return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
715 : {} /*binding_args*/,
716 1966 : TyTy::RegionParamList (0)
717 : /*regions*/,
718 3932 : locus);
719 3932 : }
720 :
721 : location_t
722 0 : AssociatedImplTrait::get_locus () const
723 : {
724 0 : return impl->get_locus ();
725 : }
726 :
727 : Analysis::NodeMapping
728 0 : TraitItemReference::get_parent_trait_mappings () const
729 : {
730 0 : auto &mappings = Analysis::Mappings::get ();
731 :
732 0 : HIR::Trait *trait
733 0 : = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
734 0 : rust_assert (trait != nullptr);
735 :
736 0 : return trait->get_mappings ();
737 : }
738 :
739 : bool
740 1833 : TraitItemReference::is_object_safe () const
741 : {
742 : // https://doc.rust-lang.org/reference/items/traits.html#object-safety
743 1833 : switch (get_trait_item_type ())
744 : {
745 1831 : case TraitItemReference::TraitItemType::FN:
746 1831 : {
747 : // lets be boring and just check that this is indeed a method will do
748 : // for now
749 1831 : const HIR::TraitItem *item = get_hir_trait_item ();
750 1831 : const HIR::TraitItemFunc *fn
751 : = static_cast<const HIR::TraitItemFunc *> (item);
752 1831 : return fn->get_decl ().is_method ();
753 : }
754 :
755 : // constants are not available via dyn dispatch and so is not object safe
756 : case TraitItemReference::TraitItemType::CONST:
757 : return false;
758 :
759 : // types are object safe since they are not available via dyn dispatch
760 0 : case TraitItemReference::TraitItemType::TYPE:
761 0 : return true;
762 :
763 : // this is just an error so lets just fail it
764 : case TraitItemReference::TraitItemType::ERROR:
765 : return false;
766 : }
767 : return false;
768 : }
769 :
770 : } // namespace Resolver
771 : } // namespace Rust
|