]>
Commit | Line | Data |
---|---|---|
a945c346 | 1 | // Copyright (C) 2020-2024 Free Software Foundation, Inc. |
c6c3db21 PH |
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-type-check-toplevel.h" | |
20 | #include "rust-hir-type-check-enumitem.h" | |
21 | #include "rust-hir-type-check-type.h" | |
22 | #include "rust-hir-type-check-expr.h" | |
23 | #include "rust-hir-type-check-pattern.h" | |
24 | #include "rust-hir-type-check-implitem.h" | |
25 | ||
26 | namespace Rust { | |
27 | namespace Resolver { | |
28 | ||
29 | TypeCheckTopLevel::TypeCheckTopLevel () : TypeCheckBase () {} | |
30 | ||
31 | void | |
32 | TypeCheckTopLevel::Resolve (HIR::Item &item) | |
33 | { | |
34 | rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM); | |
35 | HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item); | |
36 | ||
37 | TypeCheckTopLevel resolver; | |
38 | vis_item.accept_vis (resolver); | |
39 | } | |
40 | ||
41 | void | |
42 | TypeCheckTopLevel::visit (HIR::TypeAlias &alias) | |
43 | { | |
44 | TyTy::BaseType *actual_type | |
45 | = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); | |
46 | ||
47 | context->insert_type (alias.get_mappings (), actual_type); | |
48 | ||
49 | for (auto &where_clause_item : alias.get_where_clause ().get_items ()) | |
50 | { | |
51 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
52 | } | |
53 | } | |
54 | ||
55 | void | |
56 | TypeCheckTopLevel::visit (HIR::TupleStruct &struct_decl) | |
57 | { | |
58 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
59 | if (struct_decl.has_generics ()) | |
60 | resolve_generic_params (struct_decl.get_generic_params (), substitutions); | |
61 | ||
62 | for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) | |
63 | { | |
64 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
65 | } | |
66 | ||
67 | std::vector<TyTy::StructFieldType *> fields; | |
68 | size_t idx = 0; | |
69 | for (auto &field : struct_decl.get_fields ()) | |
70 | { | |
71 | TyTy::BaseType *field_type | |
72 | = TypeCheckType::Resolve (field.get_field_type ().get ()); | |
73 | TyTy::StructFieldType *ty_field | |
74 | = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), | |
af22b54a PH |
75 | std::to_string (idx), field_type, |
76 | field.get_locus ()); | |
c6c3db21 PH |
77 | fields.push_back (ty_field); |
78 | context->insert_type (field.get_mappings (), ty_field->get_field_type ()); | |
79 | idx++; | |
80 | } | |
81 | ||
82 | // get the path | |
83 | const CanonicalPath *canonical_path = nullptr; | |
84 | bool ok = mappings->lookup_canonical_path ( | |
85 | struct_decl.get_mappings ().get_nodeid (), &canonical_path); | |
86 | rust_assert (ok); | |
87 | RustIdent ident{*canonical_path, struct_decl.get_locus ()}; | |
88 | ||
89 | // its a single variant ADT | |
90 | std::vector<TyTy::VariantDef *> variants; | |
91 | variants.push_back (new TyTy::VariantDef ( | |
92 | struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), | |
93 | ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields))); | |
94 | ||
95 | // Process #[repr(X)] attribute, if any | |
96 | const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); | |
97 | TyTy::ADTType::ReprOptions repr | |
98 | = parse_repr_options (attrs, struct_decl.get_locus ()); | |
99 | ||
100 | TyTy::BaseType *type | |
101 | = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), | |
102 | mappings->get_next_hir_id (), | |
103 | struct_decl.get_identifier (), ident, | |
104 | TyTy::ADTType::ADTKind::TUPLE_STRUCT, | |
105 | std::move (variants), std::move (substitutions), repr); | |
106 | ||
107 | context->insert_type (struct_decl.get_mappings (), type); | |
108 | } | |
109 | ||
110 | void | |
111 | TypeCheckTopLevel::visit (HIR::Module &module) | |
112 | { | |
113 | for (auto &item : module.get_items ()) | |
114 | TypeCheckTopLevel::Resolve (*item.get ()); | |
115 | } | |
116 | ||
117 | void | |
118 | TypeCheckTopLevel::visit (HIR::StructStruct &struct_decl) | |
119 | { | |
120 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
121 | if (struct_decl.has_generics ()) | |
122 | resolve_generic_params (struct_decl.get_generic_params (), substitutions); | |
123 | ||
124 | for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) | |
125 | { | |
126 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
127 | } | |
128 | ||
129 | std::vector<TyTy::StructFieldType *> fields; | |
130 | for (auto &field : struct_decl.get_fields ()) | |
131 | { | |
132 | TyTy::BaseType *field_type | |
133 | = TypeCheckType::Resolve (field.get_field_type ().get ()); | |
134 | TyTy::StructFieldType *ty_field | |
135 | = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), | |
af22b54a PH |
136 | field.get_field_name (), field_type, |
137 | field.get_locus ()); | |
c6c3db21 PH |
138 | fields.push_back (ty_field); |
139 | context->insert_type (field.get_mappings (), ty_field->get_field_type ()); | |
140 | } | |
141 | ||
142 | // get the path | |
143 | const CanonicalPath *canonical_path = nullptr; | |
144 | bool ok = mappings->lookup_canonical_path ( | |
145 | struct_decl.get_mappings ().get_nodeid (), &canonical_path); | |
146 | rust_assert (ok); | |
147 | RustIdent ident{*canonical_path, struct_decl.get_locus ()}; | |
148 | ||
149 | // its a single variant ADT | |
150 | std::vector<TyTy::VariantDef *> variants; | |
151 | variants.push_back (new TyTy::VariantDef ( | |
152 | struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), | |
153 | ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); | |
154 | ||
155 | // Process #[repr(X)] attribute, if any | |
156 | const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); | |
157 | TyTy::ADTType::ReprOptions repr | |
158 | = parse_repr_options (attrs, struct_decl.get_locus ()); | |
159 | ||
160 | TyTy::BaseType *type | |
161 | = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), | |
162 | mappings->get_next_hir_id (), | |
163 | struct_decl.get_identifier (), ident, | |
164 | TyTy::ADTType::ADTKind::STRUCT_STRUCT, | |
165 | std::move (variants), std::move (substitutions), repr); | |
166 | ||
167 | context->insert_type (struct_decl.get_mappings (), type); | |
168 | } | |
169 | ||
170 | void | |
171 | TypeCheckTopLevel::visit (HIR::Enum &enum_decl) | |
172 | { | |
173 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
174 | if (enum_decl.has_generics ()) | |
175 | resolve_generic_params (enum_decl.get_generic_params (), substitutions); | |
176 | ||
177 | std::vector<TyTy::VariantDef *> variants; | |
178 | int64_t discriminant_value = 0; | |
179 | for (auto &variant : enum_decl.get_variants ()) | |
180 | { | |
181 | TyTy::VariantDef *field_type | |
182 | = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value); | |
183 | ||
184 | discriminant_value++; | |
185 | variants.push_back (field_type); | |
186 | } | |
187 | ||
188 | // get the path | |
189 | const CanonicalPath *canonical_path = nullptr; | |
190 | bool ok | |
191 | = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (), | |
192 | &canonical_path); | |
193 | rust_assert (ok); | |
194 | RustIdent ident{*canonical_path, enum_decl.get_locus ()}; | |
195 | ||
196 | // multi variant ADT | |
197 | TyTy::BaseType *type | |
198 | = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (), | |
199 | mappings->get_next_hir_id (), | |
200 | enum_decl.get_identifier (), ident, | |
201 | TyTy::ADTType::ADTKind::ENUM, std::move (variants), | |
202 | std::move (substitutions)); | |
203 | ||
204 | context->insert_type (enum_decl.get_mappings (), type); | |
205 | } | |
206 | ||
207 | void | |
208 | TypeCheckTopLevel::visit (HIR::Union &union_decl) | |
209 | { | |
210 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
211 | if (union_decl.has_generics ()) | |
212 | resolve_generic_params (union_decl.get_generic_params (), substitutions); | |
213 | ||
214 | for (auto &where_clause_item : union_decl.get_where_clause ().get_items ()) | |
215 | { | |
216 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
217 | } | |
218 | ||
219 | std::vector<TyTy::StructFieldType *> fields; | |
220 | for (auto &variant : union_decl.get_variants ()) | |
221 | { | |
222 | TyTy::BaseType *variant_type | |
223 | = TypeCheckType::Resolve (variant.get_field_type ().get ()); | |
224 | TyTy::StructFieldType *ty_variant | |
225 | = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (), | |
af22b54a PH |
226 | variant.get_field_name (), variant_type, |
227 | variant.get_locus ()); | |
c6c3db21 PH |
228 | fields.push_back (ty_variant); |
229 | context->insert_type (variant.get_mappings (), | |
230 | ty_variant->get_field_type ()); | |
231 | } | |
232 | ||
233 | // get the path | |
234 | const CanonicalPath *canonical_path = nullptr; | |
235 | bool ok | |
236 | = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (), | |
237 | &canonical_path); | |
238 | rust_assert (ok); | |
239 | RustIdent ident{*canonical_path, union_decl.get_locus ()}; | |
240 | ||
241 | // there is only a single variant | |
242 | std::vector<TyTy::VariantDef *> variants; | |
243 | variants.push_back (new TyTy::VariantDef ( | |
244 | union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (), | |
245 | ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); | |
246 | ||
247 | TyTy::BaseType *type | |
248 | = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (), | |
249 | mappings->get_next_hir_id (), | |
250 | union_decl.get_identifier (), ident, | |
251 | TyTy::ADTType::ADTKind::UNION, std::move (variants), | |
252 | std::move (substitutions)); | |
253 | ||
254 | context->insert_type (union_decl.get_mappings (), type); | |
255 | } | |
256 | ||
257 | void | |
258 | TypeCheckTopLevel::visit (HIR::StaticItem &var) | |
259 | { | |
260 | TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ()); | |
261 | TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); | |
262 | ||
7ad24d80 | 263 | TyTy::BaseType *unified |
408ab8a6 PH |
264 | = coercion_site (var.get_mappings ().get_hirid (), |
265 | TyTy::TyWithLocation (type, var.get_type ()->get_locus ()), | |
266 | TyTy::TyWithLocation (expr_type, | |
267 | var.get_expr ()->get_locus ()), | |
268 | var.get_locus ()); | |
7ad24d80 | 269 | context->insert_type (var.get_mappings (), unified); |
c6c3db21 PH |
270 | } |
271 | ||
272 | void | |
273 | TypeCheckTopLevel::visit (HIR::ConstantItem &constant) | |
274 | { | |
275 | TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); | |
276 | TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); | |
277 | ||
7ad24d80 PH |
278 | TyTy::BaseType *unified = unify_site ( |
279 | constant.get_mappings ().get_hirid (), | |
280 | TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()), | |
281 | TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()), | |
282 | constant.get_locus ()); | |
283 | context->insert_type (constant.get_mappings (), unified); | |
c6c3db21 PH |
284 | } |
285 | ||
286 | void | |
287 | TypeCheckTopLevel::visit (HIR::Function &function) | |
288 | { | |
289 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
290 | if (function.has_generics ()) | |
291 | resolve_generic_params (function.get_generic_params (), substitutions); | |
292 | ||
293 | for (auto &where_clause_item : function.get_where_clause ().get_items ()) | |
294 | { | |
295 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
296 | } | |
297 | ||
298 | TyTy::BaseType *ret_type = nullptr; | |
299 | if (!function.has_function_return_type ()) | |
300 | ret_type | |
301 | = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ()); | |
302 | else | |
303 | { | |
304 | auto resolved | |
305 | = TypeCheckType::Resolve (function.get_return_type ().get ()); | |
306 | if (resolved->get_kind () == TyTy::TypeKind::ERROR) | |
307 | { | |
308 | rust_error_at (function.get_locus (), | |
309 | "failed to resolve return type"); | |
310 | return; | |
311 | } | |
312 | ||
313 | ret_type = resolved->clone (); | |
314 | ret_type->set_ref ( | |
315 | function.get_return_type ()->get_mappings ().get_hirid ()); | |
316 | } | |
317 | ||
318 | std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params; | |
319 | for (auto ¶m : function.get_function_params ()) | |
320 | { | |
321 | // get the name as well required for later on | |
322 | auto param_tyty = TypeCheckType::Resolve (param.get_type ()); | |
323 | params.push_back ( | |
324 | std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (), | |
325 | param_tyty)); | |
326 | ||
327 | context->insert_type (param.get_mappings (), param_tyty); | |
328 | TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); | |
329 | } | |
330 | ||
331 | const CanonicalPath *canonical_path = nullptr; | |
332 | bool ok | |
333 | = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (), | |
334 | &canonical_path); | |
335 | rust_assert (ok); | |
336 | ||
337 | RustIdent ident{*canonical_path, function.get_locus ()}; | |
338 | auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), | |
339 | function.get_mappings ().get_defid (), | |
340 | function.get_function_name (), ident, | |
341 | TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, | |
342 | std::move (params), ret_type, | |
343 | std::move (substitutions)); | |
344 | ||
345 | context->insert_type (function.get_mappings (), fnType); | |
346 | } | |
347 | ||
348 | void | |
349 | TypeCheckTopLevel::visit (HIR::ImplBlock &impl_block) | |
350 | { | |
351 | std::vector<TyTy::SubstitutionParamMapping> substitutions; | |
352 | if (impl_block.has_generics ()) | |
353 | resolve_generic_params (impl_block.get_generic_params (), substitutions); | |
354 | ||
355 | for (auto &where_clause_item : impl_block.get_where_clause ().get_items ()) | |
356 | { | |
357 | ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); | |
358 | } | |
359 | ||
360 | auto self = TypeCheckType::Resolve (impl_block.get_type ().get ()); | |
361 | if (self->get_kind () == TyTy::TypeKind::ERROR) | |
362 | return; | |
363 | ||
364 | for (auto &impl_item : impl_block.get_impl_items ()) | |
365 | TypeCheckTopLevelImplItem::Resolve (impl_item.get (), self, substitutions); | |
366 | } | |
367 | ||
368 | void | |
369 | TypeCheckTopLevel::visit (HIR::ExternBlock &extern_block) | |
370 | { | |
371 | for (auto &item : extern_block.get_extern_items ()) | |
372 | { | |
373 | TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block); | |
374 | } | |
375 | } | |
376 | ||
377 | } // namespace Resolver | |
378 | } // namespace Rust |