1 // Copyright (C) 2020-2023 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 #ifndef RUST_HIR_TYPE_CHECK
20 #define RUST_HIR_TYPE_CHECK
21
22 #include "rust-type-util.h"
23 #include "rust-hir-full-decls.h"
24 #include "rust-hir-map.h"
25 #include "rust-tyty.h"
26 #include "rust-hir-trait-reference.h"
27 #include "rust-autoderef.h"
28
29 namespace Rust {
30 namespace Resolver {
31
32 class TypeCheckContextItem
33 {
34 public:
35 enum ItemType
36 {
37 ITEM,
38 IMPL_ITEM,
39 TRAIT_ITEM,
40 };
41
42 TypeCheckContextItem (HIR::Function *item);
43 TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item);
44 TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
45
46 ItemType get_type () const;
47
48 HIR::Function *get_item ();
49
50 std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
51
52 HIR::TraitItemFunc *get_trait_item ();
53
54 TyTy::FnType *get_context_type ();
55
56 private:
57 union Item
58 {
59 HIR::Function *item;
60 std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
61 HIR::TraitItemFunc *trait_item;
62
63 Item (HIR::Function *item);
64 Item (HIR::ImplBlock *impl_block, HIR::Function *item);
65 Item (HIR::TraitItemFunc *trait_item);
66 };
67
68 ItemType type;
69 Item item;
70 };
71
72 class TypeCheckContext
73 {
74 public:
75 static TypeCheckContext *get ();
76
77 ~TypeCheckContext ();
78
79 bool lookup_builtin (NodeId id, TyTy::BaseType **type);
80 bool lookup_builtin (std::string name, TyTy::BaseType **type);
81 void insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type);
82
83 void insert_type (const Analysis::NodeMapping &mappings,
84 TyTy::BaseType *type);
85 void insert_implicit_type (TyTy::BaseType *type);
86 bool lookup_type (HirId id, TyTy::BaseType **type) const;
87
88 void insert_implicit_type (HirId id, TyTy::BaseType *type);
89
90 void insert_type_by_node_id (NodeId ref, HirId id);
91 bool lookup_type_by_node_id (NodeId ref, HirId *id);
92
93 TyTy::BaseType *peek_return_type ();
94 TypeCheckContextItem &peek_context ();
95 void push_return_type (TypeCheckContextItem item,
96 TyTy::BaseType *return_type);
97 void pop_return_type ();
98 void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
99
100 bool have_loop_context () const;
101 void push_new_loop_context (HirId id, Location locus);
102 void push_new_while_loop_context (HirId id);
103 TyTy::BaseType *peek_loop_context ();
104 TyTy::BaseType *pop_loop_context ();
105
106 void swap_head_loop_context (TyTy::BaseType *val);
107
108 void insert_trait_reference (DefId id, TraitReference &&ref);
109 bool lookup_trait_reference (DefId id, TraitReference **ref);
110
111 void insert_receiver (HirId id, TyTy::BaseType *t);
112 bool lookup_receiver (HirId id, TyTy::BaseType **ref);
113
114 void insert_associated_trait_impl (HirId id,
115 AssociatedImplTrait &&associated);
116 bool lookup_associated_trait_impl (HirId id,
117 AssociatedImplTrait **associated);
118
119 void insert_associated_type_mapping (HirId id, HirId mapping);
120 void clear_associated_type_mapping (HirId id);
121
122 // lookup any associated type mappings, the out parameter of mapping is
123 // allowed to be nullptr which allows this interface to do a simple does exist
124 // check
125 bool lookup_associated_type_mapping (HirId id, HirId *mapping);
126
127 void insert_associated_impl_mapping (HirId trait_id,
128 const TyTy::BaseType *impl_type,
129 HirId impl_id);
130 bool lookup_associated_impl_mapping_for_self (HirId trait_id,
131 const TyTy::BaseType *self,
132 HirId *mapping);
133
134 void insert_autoderef_mappings (HirId id,
135 std::vector<Adjustment> &&adjustments);
136 bool lookup_autoderef_mappings (HirId id,
137 std::vector<Adjustment> **adjustments);
138
139 void insert_cast_autoderef_mappings (HirId id,
140 std::vector<Adjustment> &&adjustments);
141 bool lookup_cast_autoderef_mappings (HirId id,
142 std::vector<Adjustment> **adjustments);
143
144 void insert_variant_definition (HirId id, HirId variant);
145 bool lookup_variant_definition (HirId id, HirId *variant);
146
147 void insert_operator_overload (HirId id, TyTy::FnType *call_site);
148 bool lookup_operator_overload (HirId id, TyTy::FnType **call);
149
150 void insert_unconstrained_check_marker (HirId id, bool status);
151 bool have_checked_for_unconstrained (HirId id, bool *result);
152
153 void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
154 bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
155
156 void insert_query (HirId id);
157 void query_completed (HirId id);
158 bool query_in_progress (HirId id) const;
159
160 void insert_trait_query (DefId id);
161 void trait_query_completed (DefId id);
162 bool trait_query_in_progress (DefId id) const;
163
164 private:
165 TypeCheckContext ();
166
167 std::map<NodeId, HirId> node_id_refs;
168 std::map<HirId, TyTy::BaseType *> resolved;
169 std::vector<std::unique_ptr<TyTy::BaseType>> builtins;
170 std::vector<std::pair<TypeCheckContextItem, TyTy::BaseType *>>
171 return_type_stack;
172 std::vector<TyTy::BaseType *> loop_type_stack;
173 std::map<DefId, TraitReference> trait_context;
174 std::map<HirId, TyTy::BaseType *> receiver_context;
175 std::map<HirId, AssociatedImplTrait> associated_impl_traits;
176
177 // trait-id -> list of < self-tyty:impl-id>
178 std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>>
179 associated_traits_to_impls;
180
181 std::map<HirId, HirId> associated_type_mappings;
182
183 // adjustment mappings
184 std::map<HirId, std::vector<Adjustment>> autoderef_mappings;
185 std::map<HirId, std::vector<Adjustment>> cast_autoderef_mappings;
186
187 // operator overloads
188 std::map<HirId, TyTy::FnType *> operator_overloads;
189
190 // variants
191 std::map<HirId, HirId> variants;
192
193 // unconstrained type-params check
194 std::map<HirId, bool> unconstrained;
195
196 // predicates
197 std::map<HirId, TyTy::TypeBoundPredicate> predicates;
198
199 // query context lookups
200 std::set<HirId> querys_in_progress;
201 std::set<DefId> trait_queries_in_progress;
202 };
203
204 class TypeResolution
205 {
206 public:
207 static void Resolve (HIR::Crate &crate);
208 };
209
210 class TraitQueryGuard
211 {
212 public:
213 TraitQueryGuard (DefId id) : id (id), ctx (*TypeCheckContext::get ())
214 {
215 ctx.insert_trait_query (id);
216 }
217
218 ~TraitQueryGuard () { ctx.trait_query_completed (id); }
219
220 private:
221 DefId id;
222 TypeCheckContext &ctx;
223 };
224
225 } // namespace Resolver
226 } // namespace Rust
227
228 #endif // RUST_HIR_TYPE_CHECK