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
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
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"
26 TypeCheckContext::get ()
28 static TypeCheckContext
*instance
;
29 if (instance
== nullptr)
30 instance
= new TypeCheckContext ();
35 TypeCheckContext::TypeCheckContext () { lifetime_resolver_stack
.emplace (); }
37 TypeCheckContext::~TypeCheckContext () {}
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 ())
46 auto it
= resolved
.find (ref_it
->second
);
47 if (it
== resolved
.end ())
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 ();
69 TypeCheckContext::insert_builtin (HirId id
, NodeId ref
, TyTy::BaseType
*type
)
71 node_id_refs
[ref
] = id
;
73 builtins
.push_back (std::unique_ptr
<TyTy::BaseType
> (type
));
77 TypeCheckContext::insert_type (const Analysis::NodeMapping
&mappings
,
80 rust_assert (type
!= nullptr);
81 NodeId ref
= mappings
.get_nodeid ();
82 HirId id
= mappings
.get_hirid ();
83 node_id_refs
[ref
] = id
;
88 TypeCheckContext::insert_implicit_type (TyTy::BaseType
*type
)
90 rust_assert (type
!= nullptr);
91 resolved
[type
->get_ref ()] = type
;
95 TypeCheckContext::insert_implicit_type (HirId id
, TyTy::BaseType
*type
)
97 rust_assert (type
!= nullptr);
102 TypeCheckContext::lookup_type (HirId id
, TyTy::BaseType
**type
) const
104 auto it
= resolved
.find (id
);
105 if (it
== resolved
.end ())
113 TypeCheckContext::clear_type (TyTy::BaseType
*ty
)
115 auto it
= resolved
.find (ty
->get_ref ());
116 if (it
== resolved
.end ())
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
;
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 ())
141 TypeCheckContext::have_function_context () const
143 return !return_type_stack
.empty ();
147 TypeCheckContext::peek_return_type ()
149 rust_assert (!return_type_stack
.empty ());
150 return return_type_stack
.back ().second
;
154 TypeCheckContext::push_return_type (TypeCheckContextItem item
,
155 TyTy::BaseType
*return_type
)
157 return_type_stack
.push_back ({std::move (item
), return_type
});
161 TypeCheckContext::pop_return_type ()
163 rust_assert (!return_type_stack
.empty ());
164 return_type_stack
.pop_back ();
168 TypeCheckContext::peek_context ()
170 rust_assert (!return_type_stack
.empty ());
171 return return_type_stack
.back ().first
;
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
))
185 TypeCheckContext::have_loop_context () const
187 return !loop_type_stack
.empty ();
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
);
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
);
207 TypeCheckContext::peek_loop_context ()
209 return loop_type_stack
.back ();
213 TypeCheckContext::pop_loop_context ()
215 auto back
= peek_loop_context ();
216 loop_type_stack
.pop_back ();
221 TypeCheckContext::swap_head_loop_context (TyTy::BaseType
*val
)
223 loop_type_stack
.pop_back ();
224 loop_type_stack
.push_back (val
);
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
));
235 TypeCheckContext::lookup_trait_reference (DefId id
, TraitReference
**ref
)
237 auto it
= trait_context
.find (id
);
238 if (it
== trait_context
.end ())
246 TypeCheckContext::insert_receiver (HirId id
, TyTy::BaseType
*t
)
248 receiver_context
[id
] = t
;
252 TypeCheckContext::lookup_receiver (HirId id
, TyTy::BaseType
**ref
)
254 auto it
= receiver_context
.find (id
);
255 if (it
== receiver_context
.end ())
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
));
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 ())
279 *associated
= &it
->second
;
284 TypeCheckContext::insert_associated_type_mapping (HirId id
, HirId mapping
)
286 associated_type_mappings
[id
] = mapping
;
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
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 ())
307 if (mapping
!= nullptr)
308 *mapping
= it
->second
;
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
});
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 ())
334 for (auto &item
: it
->second
)
336 if (item
.first
->can_eq (self
, false))
338 *mapping
= item
.second
;
346 TypeCheckContext::insert_autoderef_mappings (
347 HirId id
, std::vector
<Adjustment
> &&adjustments
)
349 autoderef_mappings
.emplace (id
, std::move (adjustments
));
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 ())
360 *adjustments
= &it
->second
;
365 TypeCheckContext::insert_cast_autoderef_mappings (
366 HirId id
, std::vector
<Adjustment
> &&adjustments
)
368 cast_autoderef_mappings
.emplace (id
, std::move (adjustments
));
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 ())
379 *adjustments
= &it
->second
;
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
;
393 TypeCheckContext::lookup_variant_definition (HirId id
, HirId
*variant
)
395 auto it
= variants
.find (id
);
396 if (it
== variants
.end ())
399 *variant
= it
->second
;
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
;
413 TypeCheckContext::lookup_operator_overload (HirId id
, TyTy::FnType
**call
)
415 auto it
= operator_overloads
.find (id
);
416 if (it
== operator_overloads
.end ())
424 TypeCheckContext::insert_unconstrained_check_marker (HirId id
, bool status
)
426 unconstrained
[id
] = status
;
430 TypeCheckContext::have_checked_for_unconstrained (HirId id
, bool *result
)
432 auto it
= unconstrained
.find (id
);
433 bool found
= it
!= unconstrained
.end ();
437 *result
= it
->second
;
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
});
452 TypeCheckContext::lookup_predicate (HirId id
, TyTy::TypeBoundPredicate
*result
)
454 auto it
= predicates
.find (id
);
455 bool found
= it
!= predicates
.end ();
459 *result
= it
->second
;
464 TypeCheckContext::insert_query (HirId id
)
466 querys_in_progress
.insert (id
);
470 TypeCheckContext::query_completed (HirId id
)
472 querys_in_progress
.erase (id
);
476 TypeCheckContext::query_in_progress (HirId id
) const
478 return querys_in_progress
.find (id
) != querys_in_progress
.end ();
482 TypeCheckContext::insert_trait_query (DefId id
)
484 trait_queries_in_progress
.insert (id
);
488 TypeCheckContext::trait_query_completed (DefId id
)
490 trait_queries_in_progress
.erase (id
);
494 TypeCheckContext::trait_query_in_progress (DefId id
) const
496 return trait_queries_in_progress
.find (id
)
497 != trait_queries_in_progress
.end ();
501 TypeCheckContext::intern_lifetime (const HIR::Lifetime
&lifetime
)
503 if (lifetime
.get_lifetime_type () == AST::Lifetime::NAMED
)
505 auto maybe_interned
= lookup_lifetime (lifetime
);
507 return *maybe_interned
;
509 auto interned
= next_lifetime_index
.next ();
510 lifetime_name_interner
[lifetime
.get_name ()] = 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 ();
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 ())
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 ();
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
);
555 return get_lifetime_resolver ().resolve (maybe_interned
.value ());
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
);
572 rust_error_at (lifetime
.get_locus (), "unresolved lifetime");
575 regions
.push_back (*resolved
);
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 {
588 if (ty
->get_kind () != TyTy::TypeKind::INFER
)
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
);
601 rust_error_at (mappings
->lookup_location (id
), ErrorCode::E0282
,
602 "type annotations needed");
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
),
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
,
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
,
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
)
658 item
.item
= other
.item
.item
;
662 item
.impl_item
= other
.item
.impl_item
;
666 item
.trait_item
= other
.item
.trait_item
;
675 TypeCheckContextItem::TypeCheckContextItem ()
676 : type (ItemType::ERROR
), item (static_cast<HIR::Function
*> (nullptr))
679 TypeCheckContextItem
&
680 TypeCheckContextItem::operator= (const TypeCheckContextItem
&other
)
686 item
.item
= other
.item
.item
;
690 item
.impl_item
= other
.item
.impl_item
;
694 item
.trait_item
= other
.item
.trait_item
;
706 TypeCheckContextItem::get_error ()
708 return TypeCheckContextItem ();
712 TypeCheckContextItem::is_error () const
714 return type
== ERROR
;
718 TypeCheckContextItem::get_item ()
720 rust_assert (get_type () == ItemType::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
;
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
745 TypeCheckContextItem::get_context_type ()
747 auto &context
= *TypeCheckContext::get ();
749 HirId reference
= UNKNOWN_HIRID
;
753 reference
= get_item ()->get_mappings ().get_hirid ();
757 reference
= get_impl_item ().second
->get_mappings ().get_hirid ();
761 reference
= get_trait_item ()->get_mappings ().get_hirid ();
769 rust_assert (reference
!= UNKNOWN_HIRID
);
771 TyTy::BaseType
*lookup
= nullptr;
772 bool ok
= context
.lookup_type (reference
, &lookup
);
774 rust_assert (lookup
->get_kind () == TyTy::TypeKind::FNDEF
);
775 return static_cast<TyTy::FnType
*> (lookup
);
779 TypeCheckContextItem::get_defid () const
784 return item
.item
->get_mappings ().get_defid ();
787 return item
.impl_item
.second
->get_mappings ().get_defid ();
790 return item
.trait_item
->get_mappings ().get_defid ();
793 return UNKNOWN_DEFID
;
796 return UNKNOWN_DEFID
;
799 } // namespace Resolver