Daily bump.
[official-gcc.git] / gcc / rust / typecheck / rust-typecheck-context.cc
blob32e3a93b26a5824ad0a756668734d3e99549349d
1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
19 #include "rust-hir-type-check.h"
20 #include "rust-type-util.h"
22 namespace Rust {
23 namespace Resolver {
25 TypeCheckContext *
26 TypeCheckContext::get ()
28 static TypeCheckContext *instance;
29 if (instance == nullptr)
30 instance = new TypeCheckContext ();
32 return instance;
35 TypeCheckContext::TypeCheckContext () { lifetime_resolver_stack.emplace (); }
37 TypeCheckContext::~TypeCheckContext () {}
39 bool
40 TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
42 auto ref_it = node_id_refs.find (id);
43 if (ref_it == node_id_refs.end ())
44 return false;
46 auto it = resolved.find (ref_it->second);
47 if (it == resolved.end ())
48 return false;
50 *type = it->second;
51 return true;
54 bool
55 TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
57 for (auto &builtin : builtins)
59 if (name.compare (builtin->as_string ()) == 0)
61 *type = builtin.get ();
62 return true;
65 return false;
68 void
69 TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
71 node_id_refs[ref] = id;
72 resolved[id] = type;
73 builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
76 void
77 TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
78 TyTy::BaseType *type)
80 rust_assert (type != nullptr);
81 NodeId ref = mappings.get_nodeid ();
82 HirId id = mappings.get_hirid ();
83 node_id_refs[ref] = id;
84 resolved[id] = type;
87 void
88 TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
90 rust_assert (type != nullptr);
91 resolved[type->get_ref ()] = type;
94 void
95 TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
97 rust_assert (type != nullptr);
98 resolved[id] = type;
101 bool
102 TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
104 auto it = resolved.find (id);
105 if (it == resolved.end ())
106 return false;
108 *type = it->second;
109 return true;
112 void
113 TypeCheckContext::clear_type (TyTy::BaseType *ty)
115 auto it = resolved.find (ty->get_ref ());
116 if (it == resolved.end ())
117 return;
119 resolved.erase (it);
122 void
123 TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
125 rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
126 node_id_refs[ref] = id;
129 bool
130 TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
132 auto it = node_id_refs.find (ref);
133 if (it == node_id_refs.end ())
134 return false;
136 *id = it->second;
137 return true;
140 bool
141 TypeCheckContext::have_function_context () const
143 return !return_type_stack.empty ();
146 TyTy::BaseType *
147 TypeCheckContext::peek_return_type ()
149 rust_assert (!return_type_stack.empty ());
150 return return_type_stack.back ().second;
153 void
154 TypeCheckContext::push_return_type (TypeCheckContextItem item,
155 TyTy::BaseType *return_type)
157 return_type_stack.push_back ({std::move (item), return_type});
160 void
161 TypeCheckContext::pop_return_type ()
163 rust_assert (!return_type_stack.empty ());
164 return_type_stack.pop_back ();
167 TypeCheckContextItem
168 TypeCheckContext::peek_context ()
170 rust_assert (!return_type_stack.empty ());
171 return return_type_stack.back ().first;
174 void
175 TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
177 for (auto it = resolved.begin (); it != resolved.end (); it++)
179 if (!cb (it->first, it->second))
180 return;
184 bool
185 TypeCheckContext::have_loop_context () const
187 return !loop_type_stack.empty ();
190 void
191 TypeCheckContext::push_new_loop_context (HirId id, location_t locus)
193 TyTy::BaseType *infer_var
194 = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
195 TyTy::InferType::TypeHint::Default (), locus);
196 loop_type_stack.push_back (infer_var);
199 void
200 TypeCheckContext::push_new_while_loop_context (HirId id)
202 TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
203 loop_type_stack.push_back (infer_var);
206 TyTy::BaseType *
207 TypeCheckContext::peek_loop_context ()
209 return loop_type_stack.back ();
212 TyTy::BaseType *
213 TypeCheckContext::pop_loop_context ()
215 auto back = peek_loop_context ();
216 loop_type_stack.pop_back ();
217 return back;
220 void
221 TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
223 loop_type_stack.pop_back ();
224 loop_type_stack.push_back (val);
227 void
228 TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
230 rust_assert (trait_context.find (id) == trait_context.end ());
231 trait_context.emplace (id, std::move (ref));
234 bool
235 TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
237 auto it = trait_context.find (id);
238 if (it == trait_context.end ())
239 return false;
241 *ref = &it->second;
242 return true;
245 void
246 TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
248 receiver_context[id] = t;
251 bool
252 TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
254 auto it = receiver_context.find (id);
255 if (it == receiver_context.end ())
256 return false;
258 *ref = it->second;
259 return true;
262 void
263 TypeCheckContext::insert_associated_trait_impl (
264 HirId id, AssociatedImplTrait &&associated)
266 rust_assert (associated_impl_traits.find (id)
267 == associated_impl_traits.end ());
268 associated_impl_traits.emplace (id, std::move (associated));
271 bool
272 TypeCheckContext::lookup_associated_trait_impl (
273 HirId id, AssociatedImplTrait **associated)
275 auto it = associated_impl_traits.find (id);
276 if (it == associated_impl_traits.end ())
277 return false;
279 *associated = &it->second;
280 return true;
283 void
284 TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
286 associated_type_mappings[id] = mapping;
289 void
290 TypeCheckContext::clear_associated_type_mapping (HirId id)
292 auto it = associated_type_mappings.find (id);
293 if (it != associated_type_mappings.end ())
294 associated_type_mappings.erase (it);
297 // lookup any associated type mappings, the out parameter of mapping is
298 // allowed to be nullptr which allows this interface to do a simple does exist
299 // check
300 bool
301 TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
303 auto it = associated_type_mappings.find (id);
304 if (it == associated_type_mappings.end ())
305 return false;
307 if (mapping != nullptr)
308 *mapping = it->second;
310 return true;
313 void
314 TypeCheckContext::insert_associated_impl_mapping (
315 HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
317 auto it = associated_traits_to_impls.find (trait_id);
318 if (it == associated_traits_to_impls.end ())
320 associated_traits_to_impls[trait_id] = {};
323 associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
326 bool
327 TypeCheckContext::lookup_associated_impl_mapping_for_self (
328 HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
330 auto it = associated_traits_to_impls.find (trait_id);
331 if (it == associated_traits_to_impls.end ())
332 return false;
334 for (auto &item : it->second)
336 if (item.first->can_eq (self, false))
338 *mapping = item.second;
339 return true;
342 return false;
345 void
346 TypeCheckContext::insert_autoderef_mappings (
347 HirId id, std::vector<Adjustment> &&adjustments)
349 autoderef_mappings.emplace (id, std::move (adjustments));
352 bool
353 TypeCheckContext::lookup_autoderef_mappings (
354 HirId id, std::vector<Adjustment> **adjustments)
356 auto it = autoderef_mappings.find (id);
357 if (it == autoderef_mappings.end ())
358 return false;
360 *adjustments = &it->second;
361 return true;
364 void
365 TypeCheckContext::insert_cast_autoderef_mappings (
366 HirId id, std::vector<Adjustment> &&adjustments)
368 cast_autoderef_mappings.emplace (id, std::move (adjustments));
371 bool
372 TypeCheckContext::lookup_cast_autoderef_mappings (
373 HirId id, std::vector<Adjustment> **adjustments)
375 auto it = cast_autoderef_mappings.find (id);
376 if (it == cast_autoderef_mappings.end ())
377 return false;
379 *adjustments = &it->second;
380 return true;
383 void
384 TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
386 auto it = variants.find (id);
387 rust_assert (it == variants.end ());
389 variants[id] = variant;
392 bool
393 TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
395 auto it = variants.find (id);
396 if (it == variants.end ())
397 return false;
399 *variant = it->second;
400 return true;
403 void
404 TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
406 auto it = operator_overloads.find (id);
407 rust_assert (it == operator_overloads.end ());
409 operator_overloads[id] = call_site;
412 bool
413 TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
415 auto it = operator_overloads.find (id);
416 if (it == operator_overloads.end ())
417 return false;
419 *call = it->second;
420 return true;
423 void
424 TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
426 unconstrained[id] = status;
429 bool
430 TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
432 auto it = unconstrained.find (id);
433 bool found = it != unconstrained.end ();
434 if (!found)
435 return false;
437 *result = it->second;
438 return true;
441 void
442 TypeCheckContext::insert_resolved_predicate (HirId id,
443 TyTy::TypeBoundPredicate predicate)
445 // auto it = predicates.find (id);
446 // rust_assert (it == predicates.end ());
448 predicates.insert ({id, predicate});
451 bool
452 TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
454 auto it = predicates.find (id);
455 bool found = it != predicates.end ();
456 if (!found)
457 return false;
459 *result = it->second;
460 return true;
463 void
464 TypeCheckContext::insert_query (HirId id)
466 querys_in_progress.insert (id);
469 void
470 TypeCheckContext::query_completed (HirId id)
472 querys_in_progress.erase (id);
475 bool
476 TypeCheckContext::query_in_progress (HirId id) const
478 return querys_in_progress.find (id) != querys_in_progress.end ();
481 void
482 TypeCheckContext::insert_trait_query (DefId id)
484 trait_queries_in_progress.insert (id);
487 void
488 TypeCheckContext::trait_query_completed (DefId id)
490 trait_queries_in_progress.erase (id);
493 bool
494 TypeCheckContext::trait_query_in_progress (DefId id) const
496 return trait_queries_in_progress.find (id)
497 != trait_queries_in_progress.end ();
500 Lifetime
501 TypeCheckContext::intern_lifetime (const HIR::Lifetime &lifetime)
503 if (lifetime.get_lifetime_type () == AST::Lifetime::NAMED)
505 auto maybe_interned = lookup_lifetime (lifetime);
506 if (maybe_interned)
507 return *maybe_interned;
509 auto interned = next_lifetime_index.next ();
510 lifetime_name_interner[lifetime.get_name ()] = interned;
511 return interned;
513 if (lifetime.get_lifetime_type () == AST::Lifetime::WILDCARD)
515 return next_lifetime_index.next ();
517 if (lifetime.get_lifetime_type () == AST::Lifetime::STATIC)
519 return Lifetime::static_lifetime ();
521 rust_unreachable ();
524 tl::optional<Lifetime>
525 TypeCheckContext::lookup_lifetime (const HIR::Lifetime &lifetime) const
527 if (lifetime.get_lifetime_type () == AST::Lifetime::NAMED)
529 rust_assert (lifetime.get_name () != "static");
530 const auto name = lifetime.get_name ();
531 auto it = lifetime_name_interner.find (name);
532 if (it == lifetime_name_interner.end ())
533 return tl::nullopt;
534 return it->second;
536 if (lifetime.get_lifetime_type () == AST::Lifetime::WILDCARD)
538 return Lifetime::anonymous_lifetime ();
540 if (lifetime.get_lifetime_type () == AST::Lifetime::STATIC)
542 return Lifetime::static_lifetime ();
544 rust_unreachable ();
547 WARN_UNUSED_RESULT tl::optional<TyTy::Region>
548 TypeCheckContext::lookup_and_resolve_lifetime (
549 const HIR::Lifetime &lifetime) const
551 auto maybe_interned = lookup_lifetime (lifetime);
552 if (!maybe_interned)
553 return tl::nullopt;
555 return get_lifetime_resolver ().resolve (maybe_interned.value ());
557 void
558 TypeCheckContext::intern_and_insert_lifetime (const HIR::Lifetime &lifetime)
560 get_lifetime_resolver ().insert_mapping (intern_lifetime (lifetime));
563 WARN_UNUSED_RESULT std::vector<TyTy::Region>
564 TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const
566 std::vector<TyTy::Region> regions;
567 for (const auto &lifetime : args.get_lifetime_args ())
569 auto resolved = lookup_and_resolve_lifetime (lifetime);
570 if (!resolved)
572 rust_error_at (lifetime.get_locus (), "unresolved lifetime");
573 return {};
575 regions.push_back (*resolved);
577 return regions;
580 void
581 TypeCheckContext::compute_inference_variables (bool error)
583 auto mappings = Analysis::Mappings::get ();
585 // default inference variables if possible
586 iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool {
587 // nothing to do
588 if (ty->get_kind () != TyTy::TypeKind::INFER)
589 return true;
591 TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
592 TyTy::BaseType *default_type;
594 rust_debug_loc (mappings->lookup_location (id),
595 "trying to default infer-var: %s",
596 infer_var->as_string ().c_str ());
597 bool ok = infer_var->default_type (&default_type);
598 if (!ok)
600 if (error)
601 rust_error_at (mappings->lookup_location (id), ErrorCode::E0282,
602 "type annotations needed");
603 return true;
606 auto result
607 = unify_site (id, TyTy::TyWithLocation (ty),
608 TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
609 rust_assert (result);
610 rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
611 result->set_ref (id);
612 insert_type (Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
613 UNKNOWN_LOCAL_DEFID),
614 result);
616 return true;
620 TyTy::VarianceAnalysis::CrateCtx &
621 TypeCheckContext::get_variance_analysis_ctx ()
623 return variance_analysis_ctx;
626 // TypeCheckContextItem
628 TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
630 TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
631 HIR::Function *item)
632 : impl_item ({impl_block, item})
635 TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
636 : trait_item (trait_item)
639 TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
640 : type (ItemType::ITEM), item (item)
643 TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
644 HIR::Function *item)
645 : type (ItemType::IMPL_ITEM), item (impl_block, item)
648 TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
649 : type (ItemType::TRAIT_ITEM), item (trait_item)
652 TypeCheckContextItem::TypeCheckContextItem (const TypeCheckContextItem &other)
653 : type (other.type), item (other.item)
655 switch (other.type)
657 case ITEM:
658 item.item = other.item.item;
659 break;
661 case IMPL_ITEM:
662 item.impl_item = other.item.impl_item;
663 break;
665 case TRAIT_ITEM:
666 item.trait_item = other.item.trait_item;
667 break;
669 case ERROR:
670 item.item = nullptr;
671 break;
675 TypeCheckContextItem::TypeCheckContextItem ()
676 : type (ItemType::ERROR), item (static_cast<HIR::Function *> (nullptr))
679 TypeCheckContextItem &
680 TypeCheckContextItem::operator= (const TypeCheckContextItem &other)
682 type = other.type;
683 switch (other.type)
685 case ITEM:
686 item.item = other.item.item;
687 break;
689 case IMPL_ITEM:
690 item.impl_item = other.item.impl_item;
691 break;
693 case TRAIT_ITEM:
694 item.trait_item = other.item.trait_item;
695 break;
697 case ERROR:
698 item.item = nullptr;
699 break;
702 return *this;
705 TypeCheckContextItem
706 TypeCheckContextItem::get_error ()
708 return TypeCheckContextItem ();
711 bool
712 TypeCheckContextItem::is_error () const
714 return type == ERROR;
717 HIR::Function *
718 TypeCheckContextItem::get_item ()
720 rust_assert (get_type () == ItemType::ITEM);
721 return item.item;
724 std::pair<HIR::ImplBlock *, HIR::Function *> &
725 TypeCheckContextItem::get_impl_item ()
727 rust_assert (get_type () == ItemType::IMPL_ITEM);
728 return item.impl_item;
731 HIR::TraitItemFunc *
732 TypeCheckContextItem::get_trait_item ()
734 rust_assert (get_type () == ItemType::TRAIT_ITEM);
735 return item.trait_item;
738 TypeCheckContextItem::ItemType
739 TypeCheckContextItem::get_type () const
741 return type;
744 TyTy::FnType *
745 TypeCheckContextItem::get_context_type ()
747 auto &context = *TypeCheckContext::get ();
749 HirId reference = UNKNOWN_HIRID;
750 switch (get_type ())
752 case ITEM:
753 reference = get_item ()->get_mappings ().get_hirid ();
754 break;
756 case IMPL_ITEM:
757 reference = get_impl_item ().second->get_mappings ().get_hirid ();
758 break;
760 case TRAIT_ITEM:
761 reference = get_trait_item ()->get_mappings ().get_hirid ();
762 break;
764 case ERROR:
765 rust_unreachable ();
766 return nullptr;
769 rust_assert (reference != UNKNOWN_HIRID);
771 TyTy::BaseType *lookup = nullptr;
772 bool ok = context.lookup_type (reference, &lookup);
773 rust_assert (ok);
774 rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
775 return static_cast<TyTy::FnType *> (lookup);
778 DefId
779 TypeCheckContextItem::get_defid () const
781 switch (get_type ())
783 case ITEM:
784 return item.item->get_mappings ().get_defid ();
786 case IMPL_ITEM:
787 return item.impl_item.second->get_mappings ().get_defid ();
789 case TRAIT_ITEM:
790 return item.trait_item->get_mappings ().get_defid ();
792 case ERROR:
793 return UNKNOWN_DEFID;
796 return UNKNOWN_DEFID;
799 } // namespace Resolver
800 } // namespace Rust