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 "rich-location.h"
21 : #include "rust-hir-trait-reference.h"
22 : #include "rust-hir-type-check-expr.h"
23 : #include "rust-rib.h"
24 : #include "rust-substitution-mapper.h"
25 : #include "text-range-label.h"
26 : #include "rust-type-util.h"
27 : #include "rust-finalized-name-resolution-context.h"
28 :
29 : namespace Rust {
30 : namespace Resolver {
31 :
32 : static bool
33 3689 : validate_impl_substitution_bounds (
34 : const std::vector<TyTy::SubstitutionArg> &resolved_args, location_t locus,
35 : bool emit_error)
36 : {
37 3689 : auto &mctx = Analysis::Mappings::get ();
38 :
39 3689 : std::vector<TyTy::SubstitutionArg> args;
40 4608 : for (const auto &arg : resolved_args)
41 919 : args.push_back (arg);
42 :
43 3689 : TyTy::SubstitutionArgumentMappings mappings (std::move (args),
44 : {} /*binding_args*/,
45 3689 : TyTy::RegionParamList (0),
46 3689 : locus);
47 :
48 4607 : for (const auto &arg : resolved_args)
49 : {
50 919 : TyTy::BaseGeneric *param
51 919 : = const_cast<TyTy::BaseGeneric *> (arg.get_param_ty ());
52 919 : if (param == nullptr)
53 0 : continue;
54 :
55 919 : TyTy::BaseType *resolved_arg = arg.get_tyty ();
56 919 : if (resolved_arg->get_kind () == TyTy::TypeKind::PARAM)
57 18 : resolved_arg
58 18 : = static_cast<TyTy::ParamType *> (resolved_arg)->resolve ();
59 :
60 919 : if (resolved_arg->get_kind () == TyTy::TypeKind::PARAM
61 919 : || resolved_arg->get_kind () == TyTy::TypeKind::INFER)
62 128 : continue;
63 :
64 791 : auto arg_type_locus
65 791 : = mctx.lookup_location (arg.get_tyty ()->get_ty_ref ());
66 1741 : for (auto bound : param->get_specified_bounds ())
67 : {
68 951 : auto bound_locus = bound.get_locus ();
69 951 : auto trait_locus = bound.get ()->get_locus ();
70 951 : bound.apply_argument_mappings (mappings, false /*is_super_trait*/);
71 :
72 951 : if (!resolved_arg->satisfies_bound (bound, false /*emit_error*/))
73 : {
74 1 : if (emit_error)
75 : {
76 1 : rich_location r (line_table, locus);
77 :
78 2 : std::string arg_label_text = "the trait " + bound.get_name ()
79 2 : + " is not implemented for "
80 2 : + resolved_arg->get_name ();
81 :
82 1 : text_range_label arg_label (arg_label_text.c_str ());
83 1 : r.add_range (arg_type_locus, SHOW_RANGE_WITHOUT_CARET,
84 : &arg_label);
85 :
86 1 : bool ambiguous = false;
87 1 : auto *trait_impl
88 1 : = lookup_associated_impl_block (bound, resolved_arg,
89 : &ambiguous);
90 1 : text_range_label trait_label (
91 1 : "this trait has no implementations, consider adding one");
92 1 : if (trait_impl == nullptr)
93 1 : r.add_range (trait_locus, SHOW_RANGE_WITHOUT_CARET,
94 : &trait_label);
95 :
96 1 : text_range_label bound_label (
97 1 : "unsatisfied trait bound introduced here");
98 1 : r.add_range (bound_locus, SHOW_RANGE_WITHOUT_CARET,
99 : &bound_label);
100 :
101 1 : rust_error_at (r, ErrorCode::E0277,
102 : "the trait bound %<%s: %s%> is not satisfied",
103 2 : resolved_arg->get_name ().c_str (),
104 2 : bound.get_name ().c_str ());
105 1 : }
106 1 : return false;
107 : }
108 951 : }
109 : }
110 :
111 : return true;
112 3689 : }
113 :
114 : TraitItemReference
115 3602 : ResolveTraitItemToRef::Resolve (
116 : HIR::TraitItem &item, TyTy::BaseType *self,
117 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
118 : {
119 3602 : ResolveTraitItemToRef resolver (self, std::move (substitutions));
120 3602 : item.accept_vis (resolver);
121 3602 : return std::move (resolver.resolved);
122 3602 : }
123 :
124 : void
125 814 : ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
126 : {
127 : // create trait-item-ref
128 814 : location_t locus = type.get_locus ();
129 814 : bool is_optional = false;
130 1628 : std::string identifier = type.get_name ().as_string ();
131 :
132 814 : resolved = TraitItemReference (identifier, is_optional,
133 : TraitItemReference::TraitItemType::TYPE, &type,
134 2442 : self, substitutions, locus);
135 814 : }
136 :
137 : void
138 40 : ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
139 : {
140 : // create trait-item-ref
141 40 : location_t locus = cst.get_locus ();
142 40 : bool is_optional = cst.has_expr ();
143 80 : std::string identifier = cst.get_name ().as_string ();
144 :
145 40 : resolved = TraitItemReference (identifier, is_optional,
146 : TraitItemReference::TraitItemType::CONST, &cst,
147 120 : self, substitutions, locus);
148 40 : }
149 :
150 : void
151 2748 : ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
152 : {
153 : // create trait-item-ref
154 2748 : location_t locus = fn.get_locus ();
155 2748 : bool is_optional = fn.has_definition ();
156 5496 : std::string identifier = fn.get_decl ().get_function_name ().as_string ();
157 :
158 2748 : resolved = TraitItemReference (identifier, is_optional,
159 : TraitItemReference::TraitItemType::FN, &fn,
160 8244 : self, std::move (substitutions), locus);
161 2748 : }
162 :
163 3602 : ResolveTraitItemToRef::ResolveTraitItemToRef (
164 : TyTy::BaseType *self,
165 : std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
166 3602 : : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
167 3602 : substitutions (std::move (substitutions))
168 3602 : {}
169 :
170 : // TraitItemReference items
171 :
172 : TraitReference *
173 67651 : TraitResolver::Resolve (HIR::TypePath &path)
174 : {
175 67651 : TraitResolver resolver;
176 67651 : return resolver.resolve_path (path);
177 67651 : }
178 :
179 : TraitReference *
180 82788 : TraitResolver::Resolve (HIR::Trait &trait)
181 : {
182 82788 : TraitResolver resolver;
183 82788 : return resolver.resolve_trait (&trait);
184 82788 : }
185 :
186 : TraitReference *
187 360 : TraitResolver::Lookup (HIR::TypePath &path)
188 : {
189 360 : TraitResolver resolver;
190 360 : return resolver.lookup_path (path);
191 360 : }
192 :
193 : HIR::Trait *
194 278934 : TraitResolver::ResolveHirItem (const HIR::TypePath &path)
195 : {
196 278934 : TraitResolver resolver;
197 :
198 278934 : HIR::Trait *lookup = nullptr;
199 278934 : bool ok = resolver.resolve_path_to_trait (path, &lookup);
200 278934 : return ok ? lookup : nullptr;
201 278934 : }
202 :
203 429733 : TraitResolver::TraitResolver () : TypeCheckBase () {}
204 :
205 : bool
206 346945 : TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
207 : HIR::Trait **resolved) const
208 : {
209 346945 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
210 :
211 346945 : NodeId ref;
212 346945 : if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid (),
213 346945 : Resolver2_0::Namespace::Types))
214 : {
215 346945 : ref = *ref_opt;
216 : }
217 : else
218 : {
219 0 : rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
220 0 : return false;
221 : }
222 :
223 346945 : auto hid = mappings.lookup_node_to_hir (ref);
224 346945 : if (!hid)
225 : {
226 0 : rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
227 0 : return false;
228 : }
229 :
230 346945 : auto resolved_item = mappings.lookup_hir_item (hid.value ());
231 346945 : if (!resolved_item.has_value ())
232 : {
233 0 : rust_error_at (path.get_locus (),
234 : "Failed to resolve trait by looking up hir node");
235 0 : return false;
236 : }
237 :
238 346945 : if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
239 : {
240 3 : rich_location r (line_table, path.get_locus ());
241 3 : r.add_fixit_replace ("not a trait");
242 3 : rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
243 6 : path.as_simple_path ().as_string ().c_str ());
244 3 : return false;
245 3 : }
246 :
247 346942 : *resolved = static_cast<HIR::Trait *> (*resolved_item);
248 346942 : return true;
249 : }
250 :
251 : TraitReference *
252 67651 : TraitResolver::resolve_path (HIR::TypePath &path)
253 : {
254 67651 : HIR::Trait *resolved_trait_reference;
255 67651 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
256 67651 : if (!ok)
257 3 : return &TraitReference::error_node ();
258 :
259 67648 : return resolve_trait (resolved_trait_reference);
260 : }
261 :
262 : TraitReference *
263 150436 : TraitResolver::resolve_trait (HIR::Trait *trait_reference)
264 : {
265 150436 : TraitReference *tref = &TraitReference::error_node ();
266 150436 : if (context->lookup_trait_reference (
267 150436 : trait_reference->get_mappings ().get_defid (), &tref))
268 : {
269 146250 : return tref;
270 : }
271 :
272 4186 : DefId trait_id = trait_reference->get_mappings ().get_defid ();
273 4186 : if (context->trait_query_in_progress (trait_id))
274 : {
275 4 : rust_error_at (
276 : trait_reference->get_locus (), ErrorCode::E0391,
277 : "cycle detected when computing the super predicates of %qs",
278 4 : trait_reference->get_name ().as_string ().c_str ());
279 4 : return &TraitReference::error_node ();
280 : }
281 :
282 4182 : TraitQueryGuard guard (trait_id);
283 4182 : TyTy::BaseType *self = nullptr;
284 4182 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
285 :
286 : // this needs to be special cased for the sized trait to not auto implemented
287 : // Sized on Self
288 9082 : for (auto &generic_param : trait_reference->get_generic_params ())
289 : {
290 4900 : switch (generic_param.get ()->get_kind ())
291 : {
292 : case HIR::GenericParam::GenericKind::LIFETIME:
293 : case HIR::GenericParam::GenericKind::CONST:
294 : // FIXME: Skipping Lifetime and Const completely until better
295 : // handling.
296 : break;
297 :
298 4895 : case HIR::GenericParam::GenericKind::TYPE:
299 4895 : {
300 4895 : auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
301 4895 : bool is_self
302 4895 : = typaram.get_type_representation ().as_string ().compare ("Self")
303 4895 : == 0;
304 :
305 : // https://doc.rust-lang.org/std/marker/trait.Sized.html
306 : // The one exception is the implicit Self type of a trait
307 4895 : bool apply_sized = !is_self;
308 4895 : auto param_type
309 4895 : = TypeResolveGenericParam::Resolve (*generic_param, true,
310 4895 : apply_sized);
311 :
312 4895 : context->insert_type (generic_param->get_mappings (), param_type);
313 4895 : substitutions.emplace_back (typaram, param_type);
314 :
315 4895 : if (is_self)
316 : {
317 4182 : rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
318 4182 : TyTy::ParamType *p
319 : = static_cast<TyTy::ParamType *> (param_type);
320 4182 : p->set_implicit_self_trait ();
321 4182 : self = p;
322 : }
323 : }
324 4895 : break;
325 : }
326 : }
327 4182 : rust_assert (self != nullptr);
328 :
329 : // Check if there is a super-trait, and apply this bound to the Self
330 : // TypeParam
331 4182 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
332 :
333 : // copy the substitition mappings
334 4182 : std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
335 4182 : self_subst_copy.reserve (substitutions.size ());
336 :
337 9077 : for (auto &sub : substitutions)
338 4895 : self_subst_copy.push_back (sub.clone ());
339 :
340 : // They also inherit themselves as a bound this enables a trait item to
341 : // reference other Self::trait_items
342 4182 : specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
343 : std::move (self_subst_copy),
344 8364 : BoundPolarity::RegularBound,
345 4182 : trait_reference->get_locus ());
346 :
347 : // look for any
348 4182 : std::vector<TyTy::TypeBoundPredicate> super_traits;
349 4182 : if (trait_reference->has_type_param_bounds ())
350 : {
351 1220 : for (auto &bound : trait_reference->get_type_param_bounds ())
352 : {
353 656 : if (bound->get_bound_type ()
354 : == HIR::TypeParamBound::BoundType::TRAITBOUND)
355 : {
356 656 : HIR::TraitBound *b
357 656 : = static_cast<HIR::TraitBound *> (bound.get ());
358 :
359 656 : auto predicate = get_predicate_from_bound (
360 : b->get_path (),
361 : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
362 656 : BoundPolarity::RegularBound, false, true);
363 656 : if (predicate.is_error ())
364 15 : return &TraitReference::error_node ();
365 :
366 641 : specified_bounds.push_back (predicate);
367 641 : super_traits.push_back (predicate);
368 656 : }
369 : }
370 : }
371 4167 : self->inherit_bounds (specified_bounds);
372 :
373 4167 : context->block_context ().enter (TypeCheckBlockContextItem (trait_reference));
374 4167 : std::vector<TraitItemReference> item_refs;
375 7769 : for (auto &item : trait_reference->get_trait_items ())
376 : {
377 : // make a copy of the substs
378 3602 : std::vector<TyTy::SubstitutionParamMapping> item_subst;
379 3602 : item_subst.reserve (substitutions.size ());
380 :
381 8723 : for (auto &sub : substitutions)
382 5121 : item_subst.push_back (sub.clone ());
383 :
384 3602 : TraitItemReference trait_item_ref
385 3602 : = ResolveTraitItemToRef::Resolve (*item.get (), self,
386 3602 : std::move (item_subst));
387 3602 : item_refs.push_back (std::move (trait_item_ref));
388 3602 : }
389 :
390 4167 : TraitReference trait_object (trait_reference, item_refs, super_traits,
391 4167 : std::move (substitutions));
392 4167 : context->insert_trait_reference (
393 4167 : trait_reference->get_mappings ().get_defid (), std::move (trait_object));
394 :
395 4167 : tref = &TraitReference::error_node ();
396 4167 : bool ok = context->lookup_trait_reference (
397 4167 : trait_reference->get_mappings ().get_defid (), &tref);
398 4167 : rust_assert (ok);
399 :
400 : // hook to allow the trait to resolve its optional item blocks, we cant
401 : // resolve the blocks of functions etc because it can end up in a recursive
402 : // loop of trying to resolve traits as required by the types
403 4167 : tref->on_resolved ();
404 4167 : context->block_context ().exit ();
405 :
406 4167 : return tref;
407 4182 : }
408 :
409 : TraitReference *
410 360 : TraitResolver::lookup_path (HIR::TypePath &path)
411 : {
412 360 : HIR::Trait *resolved_trait_reference;
413 360 : bool ok = resolve_path_to_trait (path, &resolved_trait_reference);
414 360 : if (!ok)
415 0 : return &TraitReference::error_node ();
416 :
417 360 : TraitReference *tref = &TraitReference::error_node ();
418 360 : if (context->lookup_trait_reference (
419 360 : resolved_trait_reference->get_mappings ().get_defid (), &tref))
420 : {
421 360 : return tref;
422 : }
423 0 : return &TraitReference::error_node ();
424 : }
425 :
426 : void
427 3602 : TraitItemReference::on_resolved (const TraitReference *tref)
428 : {
429 3602 : switch (type)
430 : {
431 40 : case CONST:
432 40 : resolve_item (tref, static_cast<HIR::TraitItemConst &> (*hir_trait_item));
433 40 : break;
434 :
435 814 : case TYPE:
436 814 : resolve_item (tref, static_cast<HIR::TraitItemType &> (*hir_trait_item));
437 814 : break;
438 :
439 2748 : case FN:
440 2748 : {
441 2748 : TyTy::BaseType *fn_type = get_tyty ();
442 2748 : if (is_optional () && fn_type->get_kind () == TyTy::TypeKind::FNDEF)
443 869 : context->mark_function_body_pending (
444 : static_cast<TyTy::FnType *> (fn_type)->get_id ());
445 : }
446 : break;
447 :
448 : default:
449 : break;
450 : }
451 3602 : }
452 :
453 : void
454 3591 : TraitItemReference::resolve_default_function_body (const TraitReference *tref)
455 : {
456 3591 : if (type != FN || !is_optional ())
457 : return;
458 :
459 869 : auto &func = static_cast<HIR::TraitItemFunc &> (*hir_trait_item);
460 869 : TyTy::BaseType *item_tyty = get_tyty ();
461 869 : if (item_tyty->get_kind () != TyTy::TypeKind::FNDEF)
462 : return;
463 :
464 869 : auto fn_type = static_cast<TyTy::FnType *> (item_tyty);
465 869 : if (!context->function_body_pending (fn_type->get_id ()))
466 : return;
467 :
468 869 : resolve_item (tref, func);
469 : }
470 :
471 : void
472 814 : TraitItemReference::resolve_item (const TraitReference *tref,
473 : HIR::TraitItemType &type)
474 : {
475 814 : auto substitutions = inherited_substitutions;
476 814 : if (type.has_generics ())
477 : {
478 17 : auto binder_pin = context->push_lifetime_binder ();
479 17 : TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::TypeAlias,
480 : type.get_locus (),
481 17 : type.get_generic_params (),
482 : substitutions, false, ABI::RUST);
483 17 : }
484 :
485 814 : size_t inherited_count = inherited_substitutions.size ();
486 814 : auto projection
487 814 : = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), nullptr,
488 814 : tref, type.get_mappings ().get_defid (),
489 : substitutions, self,
490 1628 : TyTy::SubstitutionArgumentMappings::error (),
491 1628 : {}, {}, inherited_count);
492 :
493 814 : context->insert_type (type.get_mappings (), projection);
494 :
495 : // Attach the bounds declared on the associated type itself:
496 : //
497 : // type IntoIter: Iterator<Item = Self::Item>
498 : //
499 : // so satisfies_bound finds them in specified_bounds
500 814 : if (type.has_type_param_bounds ())
501 : {
502 47 : std::vector<TyTy::TypeBoundPredicate> trait_item_bounds;
503 94 : for (auto &bound : type.get_type_param_bounds ())
504 : {
505 47 : if (bound->get_bound_type ()
506 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
507 0 : continue;
508 47 : auto *b = static_cast<HIR::TraitBound *> (bound.get ());
509 47 : auto predicate = TypeCheckBase::ResolvePredicateFromBound (
510 : b->get_path (),
511 : tl::nullopt /*this will setup a PLACEHOLDER for self*/,
512 47 : BoundPolarity::RegularBound, false, true);
513 47 : if (!predicate.is_error ())
514 47 : trait_item_bounds.push_back (std::move (predicate));
515 47 : }
516 47 : if (!trait_item_bounds.empty ())
517 47 : projection->inherit_bounds (trait_item_bounds);
518 47 : }
519 814 : }
520 :
521 : void
522 40 : TraitItemReference::resolve_item (const TraitReference *tref,
523 : HIR::TraitItemConst &constant)
524 : {
525 40 : TyTy::BaseType *ty = nullptr;
526 40 : if (constant.has_type ())
527 11 : ty = TypeCheckType::Resolve (constant.get_type ());
528 :
529 40 : TyTy::BaseType *expr = nullptr;
530 40 : if (constant.has_expr ())
531 11 : expr = TypeCheckExpr::Resolve (constant.get_expr ());
532 :
533 51 : bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
534 51 : bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
535 :
536 10 : if (have_specified_ty && have_expr_ty)
537 : {
538 20 : coercion_site (constant.get_mappings ().get_hirid (),
539 : TyTy::TyWithLocation (ty,
540 10 : constant.get_type ().get_locus ()),
541 : TyTy::TyWithLocation (expr,
542 10 : constant.get_expr ().get_locus ()),
543 : constant.get_locus ());
544 : }
545 40 : }
546 :
547 : void
548 869 : TraitItemReference::resolve_item (const TraitReference *tref,
549 : HIR::TraitItemFunc &func)
550 : {
551 869 : TyTy::BaseType *item_tyty = get_tyty ();
552 869 : if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
553 : return;
554 :
555 869 : if (!is_optional ())
556 : return;
557 :
558 : // check the block and return types
559 869 : rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
560 :
561 : // need to get the return type from this
562 869 : TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
563 869 : context->clear_function_body_pending (resolved_fn_type->get_id ());
564 869 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
565 869 : context->push_return_type (TypeCheckContextItem (&func), expected_ret_tyty);
566 :
567 869 : auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ());
568 :
569 869 : location_t fn_return_locus
570 869 : = func.get_decl ().has_return_type ()
571 869 : ? func.get_decl ().get_return_type ().get_locus ()
572 203 : : func.get_locus ();
573 :
574 1738 : coercion_site (func.get_mappings ().get_hirid (),
575 869 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
576 869 : TyTy::TyWithLocation (block_expr_ty), func.get_locus ());
577 :
578 869 : context->pop_return_type ();
579 : }
580 :
581 : TyTy::SubstitutionArgumentMappings
582 1227 : AssociatedImplTrait::bind_impl_for_projection (TyTy::ProjectionType &proj,
583 : location_t locus)
584 : {
585 1227 : std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
586 2008 : for (auto &generic_param : impl->get_generic_params ())
587 : {
588 781 : if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE
589 781 : && generic_param->get_kind ()
590 : != HIR::GenericParam::GenericKind::CONST)
591 0 : continue;
592 781 : TyTy::BaseType *l = nullptr;
593 781 : bool ok
594 781 : = context->lookup_type (generic_param->get_mappings ().get_hirid (),
595 : &l);
596 781 : if (!ok)
597 0 : continue;
598 :
599 781 : TyTy::BaseGeneric *param = nullptr;
600 781 : if (l->get_kind () == TyTy::TypeKind::PARAM)
601 547 : param = static_cast<TyTy::ParamType *> (l);
602 234 : else if (l->get_kind () == TyTy::TypeKind::CONST
603 234 : && l->as_const_type ()->const_kind ()
604 : == TyTy::BaseConstType::ConstKind::Decl)
605 0 : param = static_cast<TyTy::ConstParamType *> (l);
606 781 : if (param != nullptr)
607 547 : impl_substitutions.emplace_back (*generic_param, param);
608 : }
609 :
610 : // Build infer args for each impl param so we dont mutate the impls own
611 : // ParamTys when unifying. param_mappings records impl_param_symbol ->
612 : // hirid_of_fresh_infer_var so we can read out what each param resolved to
613 : // after unification.
614 1227 : std::vector<TyTy::SubstitutionArg> infer_arg_vec;
615 1227 : std::map<std::string, HirId> param_mappings;
616 1774 : for (auto &p : impl_substitutions)
617 : {
618 547 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
619 547 : TyTy::TyVar infer_var
620 547 : = p.get_generic_param ().get_kind ()
621 : == HIR::GenericParam::GenericKind::CONST
622 547 : ? TyTy::TyVar::get_implicit_const_infer_var (locus)
623 547 : : TyTy::TyVar::get_implicit_infer_var (locus);
624 547 : TyTy::BaseType *resolved = infer_var.get_tyty ();
625 547 : infer_arg_vec.emplace_back (&p, resolved);
626 547 : param_mappings[symbol] = resolved->get_ref ();
627 547 : }
628 1227 : TyTy::SubstitutionArgumentMappings infer_arguments (
629 : std::move (infer_arg_vec), {} /*binding_args*/,
630 1227 : TyTy::RegionParamList (0) /*regions*/, locus);
631 :
632 1227 : TyTy::BaseType *impl_self_infer
633 1227 : = !self->is_concrete ()
634 1227 : ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
635 1016 : : self->clone ();
636 :
637 : // sub the impls trait predicate args with infers:
638 : // SliceIndex<[Y]> -> SliceIndex<[?Y]>
639 1227 : const TyTy::TypeBoundPredicate &impl_predicate = predicate;
640 1227 : std::vector<TyTy::BaseType *> impl_predicate_args;
641 1791 : for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
642 : {
643 564 : auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
644 564 : TyTy::BaseType *r = p->resolve ();
645 564 : if (!r->is_concrete ())
646 392 : r = SubstMapperInternal::Resolve (r, infer_arguments);
647 564 : impl_predicate_args.push_back (r);
648 : }
649 :
650 : // Read the projections own (trait-coord) substs and skip Self at index 0.
651 : // The projection's substs match by symbol in handle_substitions, so a
652 : // fn-level substitution that binds T won't have walked into the
653 : // projections X slot whose resolved value is [T]. Re-apply the
654 : // projections own used_arguments to each arg so any stale impl-coord
655 : // params inside (the T inside [T]) are followed through to their
656 : // current bindings
657 1227 : TyTy::SubstitutionArgumentMappings proj_used
658 1227 : = proj.get_substitution_arguments ();
659 1227 : std::vector<TyTy::BaseType *> proj_args;
660 1798 : for (size_t i = 1; i < proj.get_substs ().size (); i++)
661 : {
662 571 : auto p = proj.get_substs ().at (i).get_param_ty ();
663 571 : TyTy::BaseType *r = p->resolve ();
664 571 : if (!r->is_concrete () && !proj_used.is_empty ())
665 14 : r = SubstMapperInternal::Resolve (r, proj_used);
666 571 : proj_args.push_back (r);
667 : }
668 :
669 1227 : if (impl_predicate_args.size () != proj_args.size ())
670 7 : return TyTy::SubstitutionArgumentMappings::error ();
671 :
672 : // unify trait args [?Y] -> [{integer}]
673 1784 : for (size_t i = 0; i < proj_args.size (); i++)
674 : {
675 564 : TyTy::BaseType *proj_arg = proj_args[i];
676 564 : if (impl_predicate_args[i]->get_kind () == TyTy::TypeKind::SLICE
677 564 : && proj_arg->get_kind () != TyTy::TypeKind::SLICE)
678 : {
679 294 : auto &mappings = Analysis::Mappings::get ();
680 294 : HirId id = mappings.get_next_hir_id ();
681 294 : auto *wrapped
682 : = new TyTy::SliceType (id, proj_arg->get_locus (),
683 294 : TyTy::TyVar (proj_arg->get_ref ()));
684 294 : context->insert_implicit_type (id, wrapped);
685 294 : proj_arg = wrapped;
686 : }
687 :
688 564 : auto *res = unify_site_and (0 /*id*/,
689 564 : TyTy::TyWithLocation (impl_predicate_args[i]),
690 564 : TyTy::TyWithLocation (proj_arg), locus,
691 : false /*emit_errors*/, true /*commit_if_ok*/,
692 : true /*infer*/, true /*cleanup_on_fail*/,
693 : false /*check_bounds*/);
694 564 : if (res->get_kind () == TyTy::TypeKind::ERROR)
695 0 : return TyTy::SubstitutionArgumentMappings::error ();
696 : }
697 :
698 : // unify self Range<{integer}> -> Range<usize>
699 1220 : auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
700 1220 : TyTy::TyWithLocation (proj.get_self ()),
701 1220 : TyTy::TyWithLocation (impl_self_infer), locus,
702 : false /*emit_errors*/, true /*commit_if_ok*/,
703 : true /*infer*/, true /*cleanup_on_fail*/,
704 : false /*check_bounds*/);
705 1220 : if (res->get_kind () == TyTy::TypeKind::ERROR)
706 0 : return TyTy::SubstitutionArgumentMappings::error ();
707 :
708 1220 : std::vector<TyTy::SubstitutionArg> resolved_args;
709 1767 : for (auto &p : impl_substitutions)
710 : {
711 547 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
712 547 : auto it = param_mappings.find (symbol);
713 547 : if (it == param_mappings.end ())
714 0 : continue;
715 547 : TyTy::BaseType *r = nullptr;
716 547 : bool ok = context->lookup_type (it->second, &r);
717 547 : if (!ok)
718 0 : continue;
719 547 : resolved_args.emplace_back (&p, r);
720 547 : }
721 :
722 1220 : if (!validate_impl_substitution_bounds (resolved_args, locus,
723 : false /*emit_error*/))
724 0 : return TyTy::SubstitutionArgumentMappings::error ();
725 :
726 1220 : return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
727 : {} /*binding_args*/,
728 1220 : TyTy::RegionParamList (0)
729 : /*regions*/,
730 2440 : locus);
731 2447 : }
732 :
733 : TyTy::SubstitutionArgumentMappings
734 2469 : AssociatedImplTrait::bind_impl_for_bound (TyTy::BaseType *receiver,
735 : const TyTy::TypeBoundPredicate &bound,
736 : location_t locus, bool emit_error)
737 : {
738 : // Same shape as bind_impl_for_projection but the receiver/trait-args are
739 : // taken from the (binding, bound) pair instead of a ProjectionType.
740 2469 : std::vector<TyTy::SubstitutionParamMapping> impl_substitutions;
741 2863 : for (auto &generic_param : impl->get_generic_params ())
742 : {
743 394 : if (generic_param->get_kind () != HIR::GenericParam::GenericKind::TYPE
744 394 : && generic_param->get_kind ()
745 : != HIR::GenericParam::GenericKind::CONST)
746 22 : continue;
747 372 : TyTy::BaseType *l = nullptr;
748 372 : bool ok
749 372 : = context->lookup_type (generic_param->get_mappings ().get_hirid (),
750 : &l);
751 372 : if (!ok)
752 0 : continue;
753 :
754 372 : TyTy::BaseGeneric *param = nullptr;
755 372 : if (l->get_kind () == TyTy::TypeKind::PARAM)
756 366 : param = static_cast<TyTy::ParamType *> (l);
757 6 : else if (l->get_kind () == TyTy::TypeKind::CONST
758 6 : && l->as_const_type ()->const_kind ()
759 : == TyTy::BaseConstType::ConstKind::Decl)
760 6 : param = static_cast<TyTy::ConstParamType *> (l);
761 372 : if (param != nullptr)
762 372 : impl_substitutions.emplace_back (*generic_param, param);
763 : }
764 :
765 2469 : std::vector<TyTy::SubstitutionArg> infer_arg_vec;
766 2469 : std::map<std::string, HirId> param_mappings;
767 2841 : for (auto &p : impl_substitutions)
768 : {
769 372 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
770 372 : TyTy::TyVar infer_var
771 372 : = p.get_generic_param ().get_kind ()
772 : == HIR::GenericParam::GenericKind::CONST
773 372 : ? TyTy::TyVar::get_implicit_const_infer_var (locus)
774 366 : : TyTy::TyVar::get_implicit_infer_var (locus);
775 372 : TyTy::BaseType *resolved = infer_var.get_tyty ();
776 372 : infer_arg_vec.emplace_back (&p, resolved);
777 372 : param_mappings[symbol] = resolved->get_ref ();
778 372 : }
779 2469 : TyTy::SubstitutionArgumentMappings infer_arguments (
780 : std::move (infer_arg_vec), {} /*binding_args*/,
781 2469 : TyTy::RegionParamList (0) /*regions*/, locus);
782 :
783 2469 : TyTy::BaseType *impl_self_infer
784 2469 : = !self->is_concrete ()
785 2469 : ? SubstMapperInternal::Resolve (self->clone (), infer_arguments)
786 2252 : : self->clone ();
787 :
788 2469 : const TyTy::TypeBoundPredicate &impl_predicate = predicate;
789 2469 : std::vector<TyTy::BaseType *> impl_predicate_args;
790 3704 : for (size_t i = 1; i < impl_predicate.get_substs ().size (); i++)
791 : {
792 1235 : auto p = impl_predicate.get_substs ().at (i).get_param_ty ();
793 1235 : TyTy::BaseType *r = p->resolve ();
794 1235 : if (!r->is_concrete ())
795 278 : r = SubstMapperInternal::Resolve (r, infer_arguments);
796 1235 : impl_predicate_args.push_back (r);
797 : }
798 :
799 : // Trait args from the bound predicate the caller passed in (skip Self).
800 : // Apply the bound's own used_arguments so any stale impl-coord params
801 : // inside follow through to their current bindings.
802 2469 : TyTy::SubstitutionArgumentMappings bound_used
803 2469 : = bound.get_substitution_arguments ();
804 2469 : std::vector<TyTy::BaseType *> bound_args;
805 3704 : for (size_t i = 1; i < bound.get_substs ().size (); i++)
806 : {
807 1235 : auto p = bound.get_substs ().at (i).get_param_ty ();
808 1235 : TyTy::BaseType *r = p->resolve ();
809 1235 : if (!r->is_concrete () && !bound_used.is_empty ())
810 7 : r = SubstMapperInternal::Resolve (r, bound_used);
811 1235 : bound_args.push_back (r);
812 : }
813 :
814 2469 : if (impl_predicate_args.size () != bound_args.size ())
815 0 : return TyTy::SubstitutionArgumentMappings::error ();
816 :
817 3704 : for (size_t i = 0; i < bound_args.size (); i++)
818 : {
819 2470 : auto *res = unify_site_and (0 /*id*/,
820 1235 : TyTy::TyWithLocation (impl_predicate_args[i]),
821 1235 : TyTy::TyWithLocation (bound_args[i]), locus,
822 : false /*emit_errors*/, true /*commit_if_ok*/,
823 : true /*infer*/, true /*cleanup_on_fail*/,
824 : false /*check_bounds*/);
825 1235 : if (res->get_kind () == TyTy::TypeKind::ERROR)
826 0 : return TyTy::SubstitutionArgumentMappings::error ();
827 : }
828 :
829 2469 : auto *res = unify_site_and (impl->get_mappings ().get_hirid (),
830 2469 : TyTy::TyWithLocation (receiver),
831 2469 : TyTy::TyWithLocation (impl_self_infer), locus,
832 : false /*emit_errors*/, true /*commit_if_ok*/,
833 : true /*infer*/, true /*cleanup_on_fail*/,
834 : false /*check_bounds*/);
835 2469 : if (res->get_kind () == TyTy::TypeKind::ERROR)
836 0 : return TyTy::SubstitutionArgumentMappings::error ();
837 :
838 2469 : std::vector<TyTy::SubstitutionArg> resolved_args;
839 2841 : for (auto &p : impl_substitutions)
840 : {
841 372 : const std::string &symbol = p.get_param_ty ()->get_symbol ();
842 372 : auto it = param_mappings.find (symbol);
843 372 : if (it == param_mappings.end ())
844 0 : continue;
845 372 : TyTy::BaseType *r = nullptr;
846 372 : bool ok = context->lookup_type (it->second, &r);
847 372 : if (!ok)
848 0 : continue;
849 372 : resolved_args.emplace_back (&p, r);
850 372 : }
851 :
852 2469 : if (!validate_impl_substitution_bounds (resolved_args, locus, emit_error))
853 1 : return TyTy::SubstitutionArgumentMappings::error ();
854 :
855 2468 : return TyTy::SubstitutionArgumentMappings (std::move (resolved_args),
856 : {} /*binding_args*/,
857 2468 : TyTy::RegionParamList (0)
858 : /*regions*/,
859 4936 : locus);
860 4938 : }
861 :
862 : location_t
863 0 : AssociatedImplTrait::get_locus () const
864 : {
865 0 : return impl->get_locus ();
866 : }
867 :
868 : Analysis::NodeMapping
869 0 : TraitItemReference::get_parent_trait_mappings () const
870 : {
871 0 : auto &mappings = Analysis::Mappings::get ();
872 :
873 0 : HIR::Trait *trait
874 0 : = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
875 0 : rust_assert (trait != nullptr);
876 :
877 0 : return trait->get_mappings ();
878 : }
879 :
880 : bool
881 1907 : TraitItemReference::is_object_safe () const
882 : {
883 : // https://doc.rust-lang.org/reference/items/traits.html#object-safety
884 1907 : switch (get_trait_item_type ())
885 : {
886 1896 : case TraitItemReference::TraitItemType::FN:
887 1896 : {
888 : // lets be boring and just check that this is indeed a method will do
889 : // for now
890 1896 : const HIR::TraitItem *item = get_hir_trait_item ();
891 1896 : const HIR::TraitItemFunc *fn
892 : = static_cast<const HIR::TraitItemFunc *> (item);
893 1896 : return fn->get_decl ().is_method ();
894 : }
895 :
896 : // constants are not available via dyn dispatch and so is not object safe
897 : case TraitItemReference::TraitItemType::CONST:
898 : return false;
899 :
900 : // types are object safe since they are not available via dyn dispatch
901 9 : case TraitItemReference::TraitItemType::TYPE:
902 9 : return true;
903 :
904 : // this is just an error so lets just fail it
905 : case TraitItemReference::TraitItemType::ERROR:
906 : return false;
907 : }
908 : return false;
909 : }
910 :
911 : } // namespace Resolver
912 : } // namespace Rust
|