Line data Source code
1 : // Copyright (C) 2020-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-item.h"
20 : #include "rust-system.h"
21 : #include "rust-type-util.h"
22 : #include "rust-diagnostics.h"
23 : #include "rust-hir-map.h"
24 : #include "rust-hir-type-check-implitem.h"
25 : #include "rust-hir-type-check-item.h"
26 : #include "rust-hir-type-check.h"
27 : #include "rust-casts.h"
28 : #include "rust-mapping-common.h"
29 : #include "rust-rib.h"
30 : #include "rust-unify.h"
31 : #include "rust-coercion.h"
32 : #include "rust-hir-type-bounds.h"
33 : #include "rust-hir-trait-resolve.h"
34 : #include "rust-substitution-mapper.h"
35 : #include "rust-finalized-name-resolution-context.h"
36 :
37 : namespace Rust {
38 : namespace Resolver {
39 :
40 : const size_t kNormalizeProjectionLimit = 10;
41 :
42 : bool
43 439598 : query_type (HirId reference, TyTy::BaseType **result)
44 : {
45 439598 : auto &mappings = Analysis::Mappings::get ();
46 439598 : TypeCheckContext *context = TypeCheckContext::get ();
47 :
48 439598 : if (context->lookup_type (reference, result))
49 : return true;
50 :
51 8129 : if (context->query_in_progress (reference))
52 : return false;
53 :
54 8127 : context->insert_query (reference);
55 :
56 8127 : std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate
57 8127 : = mappings.lookup_hir_enumitem (reference);
58 16254 : bool enum_candidiate_ok
59 8127 : = enum_candidiate.first != nullptr && enum_candidiate.second != nullptr;
60 8127 : if (enum_candidiate_ok)
61 : {
62 4599 : HIR::Enum *parent = enum_candidiate.first;
63 4599 : HIR::EnumItem *enum_item = enum_candidiate.second;
64 4599 : rust_debug_loc (enum_item->get_locus (), "resolved item {%u} to",
65 : reference);
66 :
67 4599 : *result = TypeCheckItem::Resolve (*parent);
68 :
69 4599 : context->query_completed (reference);
70 4599 : return true;
71 : }
72 :
73 3528 : if (auto item = mappings.hir.items.lookup (reference))
74 : {
75 955 : rust_debug_loc (item.value ()->get_locus (), "resolved item {%u} to",
76 : reference);
77 :
78 955 : DefId item_defid = item.value ()->get_mappings ().get_defid ();
79 955 : bool is_local
80 955 : = item_defid.crateNum == mappings.crate.get_current_crate ();
81 955 : bool is_fn
82 955 : = item.value ()->get_item_kind () == HIR::Item::ItemKind::Function;
83 955 : bool is_const_fn = false;
84 955 : if (is_fn)
85 : {
86 201 : auto &fn = *static_cast<HIR::Function *> (item.value ());
87 201 : is_const_fn = fn.get_qualifiers ().is_const ();
88 : }
89 :
90 201 : bool needs_full_resolve_for_const
91 201 : = is_fn && context->const_context_p () && is_const_fn;
92 955 : if (is_fn && is_local && !needs_full_resolve_for_const)
93 : {
94 180 : HIR::Function &fn = *static_cast<HIR::Function *> (item.value ());
95 180 : *result = TypeCheckItem::ResolveFunctionSignature (fn);
96 180 : }
97 775 : else if (item.value ()->get_item_kind () == HIR::Item::ItemKind::Trait
98 775 : && is_local && !context->const_context_p ())
99 : {
100 409 : HIR::Trait &trait = *static_cast<HIR::Trait *> (item.value ());
101 409 : *result = TypeCheckItem::ResolveTraitSignature (trait);
102 : }
103 : else
104 366 : *result = TypeCheckItem::Resolve (*item.value ());
105 :
106 955 : context->query_completed (reference);
107 955 : return true;
108 : }
109 :
110 2573 : if (auto impl_item = mappings.lookup_hir_implitem (reference))
111 : {
112 2051 : auto impl_block
113 2051 : = mappings.lookup_hir_impl_block (impl_item->second).value ();
114 2051 : auto lifetime_pin = context->push_clean_lifetime_resolver (true);
115 :
116 2051 : bool failure_flag = false;
117 2051 : auto substitutions
118 : = TypeCheckItem::ResolveImplBlockSubstitutions (*impl_block,
119 2051 : failure_flag);
120 2051 : if (failure_flag)
121 : {
122 1 : *result
123 1 : = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item->first);
124 1 : context->query_completed (reference);
125 1 : return true;
126 : }
127 :
128 2050 : TyTy::BaseType *self = nullptr;
129 2050 : bool ok
130 2050 : = query_type (impl_block->get_type ().get_mappings ().get_hirid (),
131 : &self);
132 2050 : if (!ok)
133 : {
134 0 : context->query_completed (reference);
135 0 : return false;
136 : }
137 :
138 2050 : tl::optional<ImplTraitFrameGuard> guard;
139 2050 : if (impl_block->has_trait_ref ())
140 : {
141 1427 : HIR::TypePath &ref = impl_block->get_trait_ref ();
142 1427 : auto trait_reference = TraitResolver::Resolve (ref);
143 1427 : if (trait_reference->is_error ())
144 : {
145 0 : context->query_completed (reference);
146 0 : return false;
147 : }
148 :
149 1427 : auto specified_bound = TypeCheckBase::ResolvePredicateFromBound (
150 1427 : ref, impl_block->get_type (), impl_block->get_polarity ());
151 :
152 1427 : std::map<DefId, AssocTypeEntry> assoc_types_by_trait_item;
153 1427 : std::vector<const TraitItemReference *> trait_item_refs;
154 1427 : TypeCheckItem::ResolveImplTraitAssociatedTypes (
155 : context, *impl_block, specified_bound, self, substitutions,
156 : assoc_types_by_trait_item, trait_item_refs);
157 :
158 1427 : ImplTraitContextFrame frame{trait_reference, self,
159 1427 : std::move (assoc_types_by_trait_item)};
160 1427 : guard.emplace (frame);
161 1427 : }
162 :
163 : // found an impl item
164 2050 : rust_debug_loc (impl_item->first->get_locus (),
165 : "resolved impl-item {%u} to", reference);
166 :
167 2050 : DefId item_defid = impl_item->first->get_impl_mappings ().get_defid ();
168 2050 : bool is_local
169 2050 : = item_defid.crateNum == mappings.crate.get_current_crate ();
170 2050 : bool is_fn
171 2050 : = impl_item->first->get_impl_item_type () == HIR::ImplItem::FUNCTION;
172 2050 : bool is_const_fn = false;
173 2050 : if (is_fn)
174 : {
175 2041 : auto &fn = *static_cast<HIR::Function *> (impl_item->first);
176 2041 : is_const_fn = fn.get_qualifiers ().is_const ();
177 : }
178 :
179 2041 : bool needs_full_resolve_for_const
180 2041 : = is_fn && context->const_context_p () && is_const_fn;
181 2050 : if (is_fn && is_local && !needs_full_resolve_for_const)
182 : {
183 2039 : HIR::Function &fn = *static_cast<HIR::Function *> (impl_item->first);
184 2039 : *result = TypeCheckImplItem::ResolveFunctionSignature (
185 : *impl_block, fn, self, std::move (substitutions));
186 2039 : }
187 : else
188 11 : *result = TypeCheckImplItem::Resolve (*impl_block, *impl_item->first,
189 : self, std::move (substitutions));
190 :
191 2050 : context->query_completed (reference);
192 2050 : return true;
193 2051 : }
194 :
195 : // is it an impl_type?
196 522 : if (auto impl_block_by_type = mappings.lookup_impl_block_type (reference))
197 : {
198 : // found an impl item
199 466 : HIR::ImplBlock *impl = impl_block_by_type.value ();
200 466 : rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to",
201 : reference);
202 :
203 : // this could be recursive to the root type
204 466 : if (impl->has_type ())
205 : {
206 466 : HIR::Type &ty = impl->get_type ();
207 466 : NodeId ref_node_id = UNKNOWN_NODEID;
208 466 : NodeId ast_node_id = ty.get_mappings ().get_nodeid ();
209 :
210 466 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
211 :
212 : // assign the ref_node_id if we've found something
213 466 : nr_ctx.lookup (ast_node_id, Resolver2_0::Namespace::Types)
214 909 : .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
215 :
216 466 : if (ref_node_id != UNKNOWN_NODEID)
217 : {
218 443 : tl::optional<HirId> hid
219 443 : = mappings.lookup_node_to_hir (ref_node_id);
220 443 : if (hid.has_value () && context->query_in_progress (hid.value ()))
221 : {
222 0 : context->query_completed (reference);
223 0 : return false;
224 : }
225 : }
226 : }
227 :
228 466 : *result = TypeCheckItem::ResolveImplBlockSelf (*impl);
229 466 : context->query_completed (reference);
230 466 : return true;
231 : }
232 :
233 : // is it an extern item?
234 56 : if (auto extern_item = mappings.lookup_hir_extern_item (reference))
235 : {
236 53 : auto block = mappings.hir.extern_blocks.lookup (extern_item->second);
237 53 : rust_assert (block.has_value ());
238 :
239 53 : *result
240 53 : = TypeCheckTopLevelExternItem::Resolve (*extern_item.value ().first,
241 53 : *block.value ());
242 53 : context->query_completed (reference);
243 53 : return true;
244 : }
245 :
246 : // more?
247 3 : location_t possible_locus = mappings.lookup_location (reference);
248 3 : rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
249 : reference);
250 3 : context->query_completed (reference);
251 :
252 3 : return false;
253 : }
254 :
255 : bool
256 327341 : types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
257 : location_t unify_locus, bool emit_errors, bool check_bounds)
258 : {
259 327341 : TyTy::BaseType *result
260 327341 : = unify_site_and (UNKNOWN_HIRID, lhs, rhs, unify_locus, emit_errors,
261 : false /*commit*/, true /*infer*/, true /*cleanup*/,
262 : check_bounds);
263 327341 : return result->get_kind () != TyTy::TypeKind::ERROR;
264 : }
265 :
266 : TyTy::BaseType *
267 33231 : unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
268 : location_t unify_locus)
269 : {
270 33231 : TyTy::BaseType *expected = lhs.get_ty ();
271 33231 : TyTy::BaseType *expr = rhs.get_ty ();
272 :
273 33231 : rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id,
274 : expected->debug_str ().c_str (), expr->debug_str ().c_str ());
275 :
276 33231 : std::vector<UnifyRules::CommitSite> commits;
277 33231 : std::vector<UnifyRules::InferenceSite> infers;
278 33231 : return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/,
279 : true /*emit_error*/, true /*check_bounds*/,
280 33231 : false /*infer*/, commits, infers);
281 33231 : }
282 :
283 : TyTy::BaseType *
284 460841 : unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
285 : location_t unify_locus, bool emit_errors, bool commit_if_ok,
286 : bool implicit_infer_vars, bool cleanup, bool check_bounds,
287 : bool allow_never_coercion)
288 : {
289 460841 : TypeCheckContext &context = *TypeCheckContext::get ();
290 :
291 460841 : TyTy::BaseType *expected = lhs.get_ty ();
292 460841 : TyTy::BaseType *expr = rhs.get_ty ();
293 :
294 460842 : rust_debug_loc (unify_locus,
295 : "begin unify_site_and commit %s infer %s check_bounds %s "
296 : "id={%u} expected={%s} expr={%s}",
297 : commit_if_ok ? "true" : "false",
298 : implicit_infer_vars ? "true" : "false",
299 : check_bounds ? "true" : "false", id == UNKNOWN_HIRID ? 0 : id,
300 : expected->debug_str ().c_str (), expr->debug_str ().c_str ());
301 :
302 460841 : std::vector<UnifyRules::CommitSite> commits;
303 460841 : std::vector<UnifyRules::InferenceSite> infers;
304 460841 : TyTy::BaseType *result
305 460841 : = UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/,
306 : emit_errors, check_bounds, implicit_infer_vars,
307 : commits, infers, nullptr, allow_never_coercion);
308 460841 : bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
309 :
310 460842 : rust_debug_loc (unify_locus,
311 : "unify_site_and done ok=%s commit %s infer %s id={%u} "
312 : "expected={%s} expr={%s}",
313 : ok ? "true" : "false", commit_if_ok ? "true" : "false",
314 : implicit_infer_vars ? "true" : "false",
315 : id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (),
316 : expr->debug_str ().c_str ());
317 :
318 460841 : if (ok && commit_if_ok)
319 : {
320 224366 : for (auto &c : commits)
321 : {
322 128582 : UnifyRules::commit (c.lhs, c.rhs, c.resolved);
323 : }
324 : }
325 365057 : else if (cleanup)
326 : {
327 369119 : for (auto &i : infers)
328 : {
329 4406 : if (i.param != nullptr)
330 : {
331 4362 : i.param->set_ref (i.pref);
332 4362 : i.param->set_ty_ref (i.ptyref);
333 : }
334 :
335 : // remove the inference variable
336 4406 : context.clear_type (i.infer);
337 : // FIXME: Don't delete - result might point to this
338 : // delete i.infer;
339 : }
340 : }
341 460841 : return result;
342 460841 : }
343 :
344 : TyTy::BaseType *
345 44628 : coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
346 : location_t locus)
347 : {
348 44628 : TyTy::BaseType *expected = lhs.get_ty ();
349 44628 : TyTy::BaseType *expr = rhs.get_ty ();
350 :
351 44628 : rust_debug ("coercion_site id={%u} expected={%s} expr={%s}", id,
352 : expected->debug_str ().c_str (), expr->debug_str ().c_str ());
353 :
354 44628 : auto context = TypeCheckContext::get ();
355 44628 : if (expected->get_kind () == TyTy::TypeKind::ERROR
356 44628 : || expr->get_kind () == TyTy::TypeKind::ERROR)
357 : return expr;
358 :
359 : // can we autoderef it?
360 44601 : auto result = TypeCoercionRules::Coerce (expr, expected, locus,
361 44601 : true /*allow-autodref*/);
362 :
363 : // the result needs to be unified
364 44601 : TyTy::BaseType *receiver = expr;
365 44601 : if (!result.is_error ())
366 : {
367 44540 : receiver = result.tyty;
368 : }
369 :
370 44601 : rust_debug ("coerce_default_unify(a={%s}, b={%s})",
371 : receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
372 44601 : TyTy::BaseType *coerced
373 44601 : = unify_site_and (id, lhs,
374 44601 : TyTy::TyWithLocation (receiver, rhs.get_locus ()), locus,
375 : true /*emit_error*/, true /*commit*/, true /*infer*/,
376 : true /*cleanup*/);
377 44601 : context->insert_autoderef_mappings (id, std::move (result.adjustments));
378 44601 : return coerced;
379 44601 : }
380 :
381 : TyTy::BaseType *
382 1637 : try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
383 : location_t locus)
384 : {
385 1637 : TyTy::BaseType *expected = lhs.get_ty ();
386 1637 : TyTy::BaseType *expr = rhs.get_ty ();
387 :
388 1637 : rust_debug ("try_coercion_site id={%u} expected={%s} expr={%s}", id,
389 : expected->debug_str ().c_str (), expr->debug_str ().c_str ());
390 :
391 1637 : auto result = TypeCoercionRules::TryCoerce (expr, expected, locus,
392 1637 : true /*allow-autodref*/);
393 1637 : if (result.is_error ())
394 97 : return new TyTy::ErrorType (id);
395 :
396 1540 : return result.tyty;
397 1637 : }
398 :
399 : TyTy::BaseType *
400 5768 : cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
401 : location_t cast_locus)
402 : {
403 5768 : rust_debug ("cast_site id={%u} from={%s} to={%s}", id,
404 : from.get_ty ()->debug_str ().c_str (),
405 : to.get_ty ()->debug_str ().c_str ());
406 :
407 5768 : auto context = TypeCheckContext::get ();
408 5768 : if (from.get_ty ()->get_kind () == TyTy::TypeKind::ERROR
409 5768 : || to.get_ty ()->get_kind () == TyTy::TypeKind::ERROR)
410 : return to.get_ty ();
411 :
412 : // do the cast
413 5768 : auto result = TypeCastRules::resolve (cast_locus, from, to);
414 :
415 : // we assume error has already been emitted
416 5768 : if (result.is_error ())
417 : return to.get_ty ();
418 :
419 : // the result needs to be unified
420 5752 : TyTy::BaseType *casted_result = result.tyty;
421 5752 : rust_debug ("cast_default_unify(a={%s}, b={%s})",
422 : casted_result->debug_str ().c_str (),
423 : to.get_ty ()->debug_str ().c_str ());
424 :
425 5752 : TyTy::BaseType *casted
426 5752 : = unify_site (id, to,
427 5752 : TyTy::TyWithLocation (casted_result, from.get_locus ()),
428 : cast_locus);
429 5752 : context->insert_cast_autoderef_mappings (id, std::move (result.adjustments));
430 5752 : return casted;
431 5768 : }
432 :
433 : AssociatedImplTrait *
434 11325 : lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
435 : TyTy::BaseType *binding, bool *ambigious)
436 : {
437 11325 : auto context = TypeCheckContext::get ();
438 :
439 : // setup any associated type mappings for the specified bonds and this
440 : // type
441 11325 : auto candidates
442 11325 : = TypeBoundsProbe::Probe (binding, bound.get ()->get_hir_trait_ref ());
443 11325 : std::vector<AssociatedImplTrait *> associated_impl_traits;
444 25251 : for (auto &probed_bound : candidates)
445 : {
446 13926 : HIR::ImplBlock *associated_impl = probed_bound.second;
447 :
448 13926 : HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
449 13926 : AssociatedImplTrait *associated = nullptr;
450 13926 : bool found_impl_trait
451 13926 : = context->lookup_associated_trait_impl (impl_block_id, &associated);
452 13926 : if (found_impl_trait)
453 : {
454 : // compare the bounds from here i think is what we can do:
455 2601 : if (bound.get ()->is_equal (*associated->get_predicate ().get ()))
456 : {
457 2601 : associated_impl_traits.push_back (associated);
458 : }
459 : }
460 : }
461 :
462 11325 : if (associated_impl_traits.empty ())
463 : return nullptr;
464 :
465 : // This code is important when you look at slices for example when
466 : // you have a slice such as:
467 : //
468 : // let slice = &array[1..3]
469 : //
470 : // the higher ranked bounds will end up having an Index trait
471 : // implementation for Range<usize> so we need this code to resolve
472 : // that we have an integer inference variable that needs to become
473 : // a usize
474 : //
475 : // The other complicated issue is that we might have an intrinsic
476 : // which requires the :Clone or Copy bound but the libcore adds
477 : // implementations for all the integral types so when there are
478 : // multiple candidates we need to resolve to the default
479 : // implementation for that type otherwise its an error for
480 : // ambiguous type bounds
481 :
482 : // if we have a non-general inference variable we need to be
483 : // careful about the selection here
484 2562 : bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER;
485 2562 : bool is_integer_infervar
486 : = is_infer_var
487 2562 : && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
488 2626 : == TyTy::InferType::InferTypeKind::INTEGRAL;
489 64 : bool is_float_infervar
490 : = is_infer_var
491 64 : && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
492 2562 : == TyTy::InferType::InferTypeKind::FLOAT;
493 :
494 2562 : AssociatedImplTrait *associate_impl_trait = nullptr;
495 2562 : if (associated_impl_traits.size () == 1)
496 : {
497 : // just go for it
498 2523 : associate_impl_trait = associated_impl_traits.at (0);
499 : }
500 39 : else if (is_integer_infervar)
501 : {
502 0 : TyTy::BaseType *type = nullptr;
503 0 : bool ok = context->lookup_builtin ("i32", &type);
504 0 : rust_assert (ok);
505 :
506 0 : for (auto &impl : associated_impl_traits)
507 : {
508 0 : bool found = impl->get_self ()->is_equal (*type);
509 0 : if (found)
510 : {
511 0 : associate_impl_trait = impl;
512 0 : break;
513 : }
514 : }
515 : }
516 39 : else if (is_float_infervar)
517 : {
518 0 : TyTy::BaseType *type = nullptr;
519 0 : bool ok = context->lookup_builtin ("f64", &type);
520 0 : rust_assert (ok);
521 :
522 0 : for (auto &impl : associated_impl_traits)
523 : {
524 0 : bool found = impl->get_self ()->is_equal (*type);
525 0 : if (found)
526 : {
527 0 : associate_impl_trait = impl;
528 0 : break;
529 : }
530 : }
531 : }
532 :
533 2562 : if (associate_impl_trait == nullptr && ambigious != nullptr)
534 : {
535 38 : *ambigious = true;
536 : }
537 :
538 : return associate_impl_trait;
539 11325 : }
540 :
541 : void
542 11745 : rebind_projection_self_from_fn (TyTy::FnType &fn, TyTy::BaseType *root)
543 : {
544 : // After substitution+monomorphize the fn's substitution clones carry the
545 : // call-site bindings. Inner projections in the return/params can still
546 : // reference the traits formal Self via TyVar(formal.ref) whose type table
547 : // entry resolves to the unbound formal
548 11745 : std::map<HirId, TyTy::BaseGeneric *> bound_by_formal;
549 17486 : for (auto &sub : fn.get_substs ())
550 : {
551 5741 : auto *pty = sub.get_param_ty ();
552 5741 : if (pty == nullptr || pty->get_kind () != TyTy::TypeKind::PARAM
553 11474 : || !pty->can_resolve ())
554 103 : continue;
555 5638 : bound_by_formal[pty->get_ref ()] = pty;
556 : }
557 :
558 11745 : std::function<void (TyTy::BaseType *)> rebind;
559 37576 : rebind = [&] (TyTy::BaseType *ty) {
560 14086 : if (ty == nullptr)
561 : return;
562 :
563 14086 : if (auto *proj = ty->try_as<TyTy::ProjectionType> ())
564 : {
565 203 : auto *self = proj->get_self ();
566 203 : if (self->get_kind () == TyTy::TypeKind::PARAM)
567 : {
568 172 : auto it = bound_by_formal.find (self->get_ref ());
569 172 : if (it != bound_by_formal.end ())
570 158 : proj->set_self (it->second);
571 : }
572 :
573 517 : for (auto &sub : proj->get_substs ())
574 : {
575 314 : auto *param = sub.get_param_ty ();
576 314 : if (param == nullptr || param->get_kind () != TyTy::TypeKind::PARAM
577 628 : || param->can_resolve ())
578 276 : continue;
579 :
580 38 : auto it = bound_by_formal.find (param->get_ref ());
581 38 : if (it == bound_by_formal.end ()
582 38 : || it->second->get_kind () != TyTy::TypeKind::PARAM)
583 0 : continue;
584 :
585 38 : auto *bound = static_cast<TyTy::ParamType *> (it->second);
586 38 : if (bound->can_resolve ())
587 38 : param->set_ty_ref (bound->get_ty_ref ());
588 : }
589 : return;
590 : }
591 :
592 13883 : if (auto *adt = ty->try_as<TyTy::ADTType> ())
593 : {
594 2811 : for (auto &variant : adt->get_variants ())
595 3330 : for (auto &field : variant->get_fields ())
596 1601 : rebind (field->get_field_type ());
597 : return;
598 : }
599 :
600 12801 : if (auto *ref = ty->try_as<TyTy::ReferenceType> ())
601 55 : rebind (ref->get_base ());
602 12746 : else if (auto *ptr = ty->try_as<TyTy::PointerType> ())
603 229 : rebind (ptr->get_base ());
604 12517 : else if (auto *tup = ty->try_as<TyTy::TupleType> ())
605 4963 : for (size_t i = 0; i < tup->num_fields (); i++)
606 456 : rebind (tup->get_field (i));
607 11745 : };
608 :
609 11745 : rebind (root);
610 11745 : }
611 :
612 : TyTy::BaseType *
613 4425 : normalize_projection (TyTy::ProjectionType *proj, location_t locus,
614 : bool emit_errors, bool unify_self)
615 : {
616 4995 : static std::vector<TyTy::ProjectionType *> active_projections;
617 8850 : if (ScopedPush<TyTy::ProjectionType *>::contains (active_projections, proj))
618 : return proj;
619 :
620 4425 : ScopedPush<TyTy::ProjectionType *> guard (active_projections, proj);
621 :
622 4425 : if (!proj->is_trait_position ())
623 : {
624 445 : TyTy::BaseType *base = proj->get ();
625 445 : if (auto *param = base->try_as<TyTy::ParamType> ())
626 : {
627 113 : if (param->can_resolve ())
628 : {
629 113 : TyTy::BaseType *resolved
630 113 : = TyTy::TyVar (param->get_ty_ref ()).get_tyty ();
631 113 : if (!resolved->is<TyTy::ParamType> ())
632 445 : base = resolved;
633 : }
634 : }
635 4870 : if (auto *base_proj = base->try_as<TyTy::ProjectionType> ())
636 0 : return normalize_projection (base_proj, locus, emit_errors, unify_self);
637 : return base;
638 : }
639 :
640 : // special case the discriminant_type lang item
641 3980 : auto &mappings = Analysis::Mappings::get ();
642 3980 : auto *ctx = TypeCheckContext::get ();
643 3980 : if (auto discriminant_type_id
644 3980 : = mappings.lookup_lang_item (LangItem::Kind::DISCRIMINANT_TYPE))
645 : {
646 72 : if (proj->get_item_defid () == discriminant_type_id.value ())
647 : {
648 72 : TyTy::BaseType *isize_ty = nullptr;
649 72 : bool ok = ctx->lookup_builtin ("isize", &isize_ty);
650 72 : rust_assert (ok);
651 :
652 : // If the self type is a concrete ADT, use its repr.
653 72 : TyTy::BaseType *self = proj->get_self ()->destructure ();
654 72 : if (auto *adt = self->try_as<TyTy::ADTType> ())
655 : {
656 0 : auto *repr = adt->get_repr_options ().repr;
657 0 : if (repr != nullptr)
658 : return repr;
659 : }
660 72 : return isize_ty;
661 : }
662 : }
663 :
664 3908 : ImplTraitContextFrame frame;
665 3908 : if (!ctx->find_matching_impl_trait_frame (*proj->get_trait_ref (),
666 3908 : *proj->get_self (), &frame))
667 : {
668 : // No concrete impl frame check WHERE clause bindings on the self type
669 : //
670 : // fn foo<T: Trait<AssocType = X>>()
671 : //
672 : // normalizes
673 : //
674 : // <T as Trait>::AssocType -> X.
675 :
676 2628 : TyTy::BaseType *self = proj->get_self ()->destructure ();
677 2628 : const DefId item_defid = proj->get_item_defid ();
678 :
679 : // find the name of the associated type from the trait reference
680 2628 : std::string assoc_name;
681 2867 : for (const auto &ti : proj->get_trait_ref ()->get_trait_items ())
682 : {
683 3106 : if (ti.get_mappings ().get_defid () == item_defid)
684 : {
685 2628 : assoc_name = ti.get_identifier ();
686 2628 : break;
687 : }
688 : }
689 :
690 2628 : if (!assoc_name.empty ())
691 : {
692 4339 : for (auto &bound : self->get_specified_bounds ())
693 : {
694 : // The associated type can be declared on a supertrait of
695 : // a bound: see issue-4884
696 : //
697 : // I: SplitIter<Item = T> binds Iterator2::Item,
698 :
699 1786 : auto item = bound.lookup_associated_item (assoc_name);
700 1786 : if (!item.has_value ())
701 439 : continue;
702 :
703 1347 : auto &item_val = item.value ();
704 1347 : const auto raw_item = item_val.get_raw_item ();
705 1347 : if (raw_item->get_mappings ().get_defid () != item_defid)
706 0 : continue;
707 :
708 1347 : const auto parent = item_val.get_parent ();
709 1347 : const auto &arguments = parent->get_substitution_arguments ();
710 1347 : const auto &binding = arguments.get_binding_args ();
711 1347 : auto it = binding.find (assoc_name);
712 1347 : if (it != binding.end ())
713 60 : return it->second;
714 :
715 1287 : const auto &constraints = arguments.get_constraint_args ();
716 1287 : auto constraint = constraints.find (assoc_name);
717 1287 : if (constraint != constraints.end ())
718 : {
719 15 : TyTy::BaseType *constrained = proj->clone ();
720 15 : constrained->inherit_bounds (*constraint->second);
721 :
722 : // Keep the constrained projection distinct from the canonical
723 : // associated-type declaration.
724 15 : auto &mappings = Analysis::Mappings::get ();
725 15 : HirId fresh = mappings.get_next_hir_id ();
726 15 : constrained->set_ref (fresh);
727 15 : constrained->set_ty_ref (fresh);
728 15 : ctx->insert_implicit_type (fresh, constrained);
729 15 : return constrained;
730 : }
731 1786 : }
732 : }
733 :
734 : // If self is a trait-position projection recursively normalize it first
735 : // so the impl-block lookup below works on a concrete type.
736 2553 : if (auto *self_proj = self->try_as<TyTy::ProjectionType> ())
737 : {
738 42 : if (self_proj->is_trait_position ())
739 : {
740 5 : auto *norm = normalize_projection (self_proj, locus, emit_errors,
741 : unify_self);
742 5 : if (norm != self_proj
743 5 : && norm->get_kind () != TyTy::TypeKind::ERROR)
744 4 : self = norm->destructure ();
745 : }
746 : else
747 : {
748 37 : auto *base = self_proj->get ();
749 37 : if (base && base != self_proj)
750 37 : self = base->destructure ();
751 : }
752 : }
753 :
754 : // Direct impl-block lookup for concrete self types (no active frame).
755 2553 : if (!assoc_name.empty () && self->get_kind () != TyTy::TypeKind::PARAM
756 1398 : && self->get_kind () != TyTy::TypeKind::INFER
757 3951 : && self->get_kind () != TyTy::TypeKind::PROJECTION)
758 : {
759 1393 : auto candidates = TypeBoundsProbe::Probe (
760 1393 : self, proj->get_trait_ref ()->get_hir_trait_ref ());
761 1593 : for (auto &probed : candidates)
762 : {
763 1493 : HIR::ImplBlock *impl_block = probed.second;
764 1493 : if (!impl_block->has_trait_ref ())
765 200 : continue;
766 :
767 1293 : HIR::TypePath &ref = impl_block->get_trait_ref ();
768 1293 : auto *tref = TraitResolver::Resolve (ref);
769 1293 : if (tref->is_error ()
770 1293 : || !tref->is_equal (*proj->get_trait_ref ()))
771 0 : continue;
772 :
773 1462 : for (auto &impl_item : impl_block->get_impl_items ())
774 : {
775 2924 : if (impl_item->get_impl_item_name ().compare (assoc_name)
776 1462 : != 0)
777 169 : continue;
778 :
779 1293 : TyTy::BaseType *result = nullptr;
780 1293 : if (query_type (impl_item->get_impl_mappings ().get_hirid (),
781 : &result))
782 : {
783 1293 : AssociatedImplTrait *associated = nullptr;
784 1293 : if (ctx->lookup_associated_trait_impl (
785 1293 : impl_block->get_mappings ().get_hirid (),
786 : &associated)
787 1293 : && associated != nullptr)
788 : {
789 1230 : auto mapping
790 : = associated->bind_impl_for_projection (*proj,
791 1230 : locus);
792 1230 : if (!mapping.is_error ())
793 1223 : result
794 1223 : = SubstMapperInternal::Resolve (result, mapping);
795 1230 : }
796 :
797 : // impl type aliases are stored as non-trait-position
798 : // ProjectionType; unwrap to base only when there are no
799 : // substitution params (non-GAT)
800 1293 : if (auto *p = result->try_as<TyTy::ProjectionType> ())
801 : {
802 1293 : if (!p->is_trait_position ())
803 : {
804 1293 : bool all_substs_bound = true;
805 1731 : for (auto &s : p->get_substs ())
806 : {
807 748 : auto *sp = s.get_param_ty ();
808 748 : if (sp == nullptr || !sp->can_resolve ()
809 1257 : || sp->resolve ()->get_kind ()
810 : == TyTy::TypeKind::PARAM)
811 : {
812 : all_substs_bound = false;
813 : break;
814 : }
815 : }
816 :
817 : // Also unwrap when the base is already concrete
818 1293 : bool base_is_concrete
819 1293 : = p->get () != nullptr
820 1293 : && p->get ()->is_concrete ();
821 1293 : if (!p->has_substitutions () || all_substs_bound
822 1293 : || base_is_concrete)
823 1260 : result = p->get ();
824 : }
825 : }
826 :
827 1293 : return result;
828 : }
829 0 : break;
830 : }
831 : }
832 1393 : }
833 :
834 : // special-case FnOnce::Output
835 1260 : if (proj->is_trait_position ())
836 : {
837 1260 : auto fn_once_lookup
838 1260 : = mappings.lookup_lang_item (LangItem::Kind::FN_ONCE);
839 1260 : auto fn_once_output_lookup
840 1260 : = mappings.lookup_lang_item (LangItem::Kind::FN_ONCE_OUTPUT);
841 1260 : if (!fn_once_lookup || !fn_once_output_lookup)
842 1188 : return proj;
843 :
844 172 : DefId &fn_once_trait_id = fn_once_lookup.value ();
845 172 : DefId &fn_once_output_id = fn_once_output_lookup.value ();
846 172 : DefId proj_trait_id = proj->get_trait_ref ()->get_defid ();
847 172 : DefId proj_trait_item_id = proj->get_item_defid ();
848 :
849 341 : if (proj_trait_id == fn_once_trait_id
850 241 : && proj_trait_item_id == fn_once_output_id)
851 : {
852 169 : auto pself = proj->get_self ();
853 241 : if (auto closure = pself->try_as<TyTy::ClosureType> ())
854 100 : return &closure->get_result_type ();
855 : }
856 : }
857 :
858 : return proj;
859 2628 : }
860 :
861 1280 : if (unify_self)
862 : {
863 1 : TyTy::BaseType *proj_self = proj->get_self ();
864 1 : bool proj_self_is_unresolved_trait_self = false;
865 1 : if (auto *param = proj_self->try_as<TyTy::ParamType> ())
866 : {
867 1 : proj_self_is_unresolved_trait_self
868 1 : = !param->can_resolve () && param->is_implicit_self_trait ();
869 : }
870 :
871 : if (!proj_self_is_unresolved_trait_self)
872 : {
873 0 : TyTy::BaseType *impl_self = frame.self;
874 0 : TyTy::BaseType *self = unify_site_and (
875 0 : /*id*/ 0, TyTy::TyWithLocation (proj_self, locus),
876 0 : TyTy::TyWithLocation (impl_self, locus), locus,
877 : /*emit_errors*/ false,
878 : /*commit*/ false,
879 : /*infer*/ false,
880 : /*cleanup*/ true,
881 : /*check_bounds*/ false);
882 :
883 0 : if (self->get_kind () == TyTy::TypeKind::ERROR)
884 : return self;
885 : }
886 : }
887 :
888 : // Lookup the trait item -> impl type mapping (key = trait item DefId).
889 1280 : const DefId item = proj->get_item_defid ();
890 1280 : auto it = frame.assoc_types_by_trait_item.find (item);
891 1280 : if (it == frame.assoc_types_by_trait_item.end ())
892 : {
893 : return proj;
894 : }
895 :
896 1280 : auto &entry = it->second;
897 1280 : auto impl_value = entry.value;
898 :
899 : // chase the impl body through any further projections it contains
900 1280 : TyTy::BaseType *normalized = impl_value;
901 2560 : for (size_t i = 0; i < kNormalizeProjectionLimit; i++)
902 : {
903 2560 : if (!normalized->is<TyTy::ProjectionType> ())
904 : break;
905 :
906 1329 : auto p = normalized->as<TyTy::ProjectionType> ();
907 1329 : if (p->is_trait_position ())
908 : {
909 49 : auto *n = normalize_projection (p, locus, emit_errors, unify_self);
910 49 : if (n == p)
911 : break;
912 :
913 : normalized = n;
914 : }
915 : else
916 : {
917 1280 : auto *v = p->get ();
918 1280 : if (v == nullptr || v == p)
919 : break;
920 :
921 : normalized = v;
922 : }
923 : }
924 :
925 : return normalized;
926 4425 : }
927 :
928 : } // namespace Resolver
929 : } // namespace Rust
|