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