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