]>
Commit | Line | Data |
---|---|---|
83ffe9cd | 1 | // Copyright (C) 2020-2023 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.h" | |
20 | #include "rust-hir-full.h" | |
21 | #include "rust-hir-type-check-toplevel.h" | |
22 | #include "rust-hir-type-check-item.h" | |
23 | #include "rust-hir-type-check-expr.h" | |
24 | #include "rust-hir-type-check-pattern.h" | |
25 | #include "rust-hir-type-check-struct-field.h" | |
26 | #include "rust-hir-inherent-impl-overlap.h" | |
27 | ||
28 | extern bool | |
29 | saw_errors (void); | |
30 | ||
31 | namespace Rust { | |
32 | namespace Resolver { | |
33 | ||
34 | void | |
35 | TypeResolution::Resolve (HIR::Crate &crate) | |
36 | { | |
37 | for (auto it = crate.items.begin (); it != crate.items.end (); it++) | |
38 | TypeCheckTopLevel::Resolve (*it->get ()); | |
39 | ||
40 | if (saw_errors ()) | |
41 | return; | |
42 | ||
43 | OverlappingImplItemPass::go (); | |
44 | if (saw_errors ()) | |
45 | return; | |
46 | ||
47 | for (auto it = crate.items.begin (); it != crate.items.end (); it++) | |
48 | TypeCheckItem::Resolve (*it->get ()); | |
49 | ||
50 | if (saw_errors ()) | |
51 | return; | |
52 | ||
53 | auto mappings = Analysis::Mappings::get (); | |
54 | auto context = TypeCheckContext::get (); | |
55 | ||
56 | // default inference variables if possible | |
57 | context->iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool { | |
58 | // nothing to do | |
59 | if (ty->get_kind () != TyTy::TypeKind::INFER) | |
60 | return true; | |
61 | ||
62 | TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty); | |
63 | TyTy::BaseType *default_type; | |
64 | bool ok = infer_var->default_type (&default_type); | |
65 | if (!ok) | |
66 | { | |
67 | rust_error_at (mappings->lookup_location (id), | |
68 | "type annotations needed"); | |
69 | return true; | |
70 | } | |
71 | else | |
72 | { | |
73 | auto result = ty->unify (default_type); | |
74 | result->set_ref (id); | |
75 | context->insert_type ( | |
76 | Analysis::NodeMapping (mappings->get_current_crate (), 0, id, | |
77 | UNKNOWN_LOCAL_DEFID), | |
78 | result); | |
79 | } | |
80 | ||
81 | return true; | |
82 | }); | |
83 | } | |
84 | ||
85 | // rust-hir-trait-ref.h | |
86 | ||
87 | TraitItemReference::TraitItemReference ( | |
88 | std::string identifier, bool optional, TraitItemType type, | |
89 | HIR::TraitItem *hir_trait_item, TyTy::BaseType *self, | |
90 | std::vector<TyTy::SubstitutionParamMapping> substitutions, Location locus) | |
91 | : identifier (identifier), optional_flag (optional), type (type), | |
92 | hir_trait_item (hir_trait_item), | |
93 | inherited_substitutions (std::move (substitutions)), locus (locus), | |
94 | self (self), context (TypeCheckContext::get ()) | |
95 | {} | |
96 | ||
97 | TraitItemReference::TraitItemReference (TraitItemReference const &other) | |
98 | : identifier (other.identifier), optional_flag (other.optional_flag), | |
99 | type (other.type), hir_trait_item (other.hir_trait_item), | |
100 | locus (other.locus), self (other.self), context (TypeCheckContext::get ()) | |
101 | { | |
102 | inherited_substitutions.clear (); | |
103 | inherited_substitutions.reserve (other.inherited_substitutions.size ()); | |
104 | for (size_t i = 0; i < other.inherited_substitutions.size (); i++) | |
105 | inherited_substitutions.push_back ( | |
106 | other.inherited_substitutions.at (i).clone ()); | |
107 | } | |
108 | ||
109 | TraitItemReference & | |
110 | TraitItemReference::operator= (TraitItemReference const &other) | |
111 | { | |
112 | identifier = other.identifier; | |
113 | optional_flag = other.optional_flag; | |
114 | type = other.type; | |
115 | hir_trait_item = other.hir_trait_item; | |
116 | self = other.self; | |
117 | locus = other.locus; | |
118 | context = other.context; | |
119 | ||
120 | inherited_substitutions.clear (); | |
121 | inherited_substitutions.reserve (other.inherited_substitutions.size ()); | |
122 | for (size_t i = 0; i < other.inherited_substitutions.size (); i++) | |
123 | inherited_substitutions.push_back ( | |
124 | other.inherited_substitutions.at (i).clone ()); | |
125 | ||
126 | return *this; | |
127 | } | |
128 | ||
129 | TyTy::BaseType * | |
130 | TraitItemReference::get_type_from_typealias (/*const*/ | |
131 | HIR::TraitItemType &type) const | |
132 | { | |
133 | TyTy::TyVar var (get_mappings ().get_hirid ()); | |
134 | return var.get_tyty (); | |
135 | } | |
136 | ||
137 | TyTy::BaseType * | |
138 | TraitItemReference::get_type_from_constant ( | |
139 | /*const*/ HIR::TraitItemConst &constant) const | |
140 | { | |
141 | TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ().get ()); | |
142 | if (constant.has_expr ()) | |
143 | { | |
144 | TyTy::BaseType *expr | |
145 | = TypeCheckExpr::Resolve (constant.get_expr ().get ()); | |
146 | ||
147 | return type->unify (expr); | |
148 | } | |
149 | return type; | |
150 | } | |
151 | ||
152 | TyTy::BaseType * | |
153 | TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const | |
154 | { | |
155 | std::vector<TyTy::SubstitutionParamMapping> substitutions | |
156 | = inherited_substitutions; | |
157 | ||
158 | HIR::TraitFunctionDecl &function = fn.get_decl (); | |
159 | if (function.has_generics ()) | |
160 | { | |
161 | for (auto &generic_param : function.get_generic_params ()) | |
162 | { | |
163 | switch (generic_param.get ()->get_kind ()) | |
164 | { | |
165 | case HIR::GenericParam::GenericKind::LIFETIME: | |
166 | case HIR::GenericParam::GenericKind::CONST: | |
167 | // FIXME: Skipping Lifetime and Const completely until better | |
168 | // handling. | |
169 | break; | |
170 | ||
171 | case HIR::GenericParam::GenericKind::TYPE: { | |
172 | auto param_type | |
173 | = TypeResolveGenericParam::Resolve (generic_param.get ()); | |
174 | context->insert_type (generic_param->get_mappings (), | |
175 | param_type); | |
176 | ||
177 | substitutions.push_back (TyTy::SubstitutionParamMapping ( | |
178 | static_cast<HIR::TypeParam &> (*generic_param), param_type)); | |
179 | } | |
180 | break; | |
181 | } | |
182 | } | |
183 | } | |
184 | ||
185 | TyTy::BaseType *ret_type = nullptr; | |
186 | if (!function.has_return_type ()) | |
187 | ret_type = TyTy::TupleType::get_unit_type (fn.get_mappings ().get_hirid ()); | |
188 | else | |
189 | { | |
190 | auto resolved | |
191 | = TypeCheckType::Resolve (function.get_return_type ().get ()); | |
192 | if (resolved->get_kind () == TyTy::TypeKind::ERROR) | |
193 | { | |
194 | rust_error_at (fn.get_locus (), "failed to resolve return type"); | |
195 | return get_error (); | |
196 | } | |
197 | ||
198 | ret_type = resolved->clone (); | |
199 | ret_type->set_ref ( | |
200 | function.get_return_type ()->get_mappings ().get_hirid ()); | |
201 | } | |
202 | ||
203 | std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params; | |
204 | if (function.is_method ()) | |
205 | { | |
206 | // these are implicit mappings and not used | |
207 | auto mappings = Analysis::Mappings::get (); | |
208 | auto crate_num = mappings->get_current_crate (); | |
209 | Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (), | |
210 | mappings->get_next_hir_id (crate_num), | |
211 | UNKNOWN_LOCAL_DEFID); | |
212 | ||
213 | // add the synthetic self param at the front, this is a placeholder | |
214 | // for compilation to know parameter names. The types are ignored | |
215 | // but we reuse the HIR identifier pattern which requires it | |
216 | HIR::SelfParam &self_param = function.get_self (); | |
217 | HIR::IdentifierPattern *self_pattern | |
218 | = new HIR::IdentifierPattern (mapping, "self", self_param.get_locus (), | |
219 | self_param.is_ref (), | |
220 | self_param.is_mut () ? Mutability::Mut | |
221 | : Mutability::Imm, | |
222 | std::unique_ptr<HIR::Pattern> (nullptr)); | |
223 | // might have a specified type | |
224 | TyTy::BaseType *self_type = nullptr; | |
225 | if (self_param.has_type ()) | |
226 | { | |
227 | std::unique_ptr<HIR::Type> &specified_type = self_param.get_type (); | |
228 | self_type = TypeCheckType::Resolve (specified_type.get ()); | |
229 | } | |
230 | else | |
231 | { | |
232 | switch (self_param.get_self_kind ()) | |
233 | { | |
234 | case HIR::SelfParam::IMM: | |
235 | case HIR::SelfParam::MUT: | |
236 | self_type = self->clone (); | |
237 | break; | |
238 | ||
239 | case HIR::SelfParam::IMM_REF: | |
240 | self_type = new TyTy::ReferenceType ( | |
241 | self_param.get_mappings ().get_hirid (), | |
242 | TyTy::TyVar (self->get_ref ()), Mutability::Imm); | |
243 | break; | |
244 | ||
245 | case HIR::SelfParam::MUT_REF: | |
246 | self_type = new TyTy::ReferenceType ( | |
247 | self_param.get_mappings ().get_hirid (), | |
248 | TyTy::TyVar (self->get_ref ()), Mutability::Mut); | |
249 | break; | |
250 | ||
251 | default: | |
252 | gcc_unreachable (); | |
253 | return nullptr; | |
254 | } | |
255 | } | |
256 | ||
257 | context->insert_type (self_param.get_mappings (), self_type); | |
258 | params.push_back ( | |
259 | std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, self_type)); | |
260 | } | |
261 | ||
262 | for (auto ¶m : function.get_function_params ()) | |
263 | { | |
264 | // get the name as well required for later on | |
265 | auto param_tyty = TypeCheckType::Resolve (param.get_type ()); | |
266 | params.push_back ( | |
267 | std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (), | |
268 | param_tyty)); | |
269 | ||
270 | context->insert_type (param.get_mappings (), param_tyty); | |
271 | TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); | |
272 | } | |
273 | ||
274 | auto mappings = Analysis::Mappings::get (); | |
275 | const CanonicalPath *canonical_path = nullptr; | |
276 | bool ok = mappings->lookup_canonical_path (fn.get_mappings ().get_nodeid (), | |
277 | &canonical_path); | |
278 | rust_assert (ok); | |
279 | ||
280 | RustIdent ident{*canonical_path, fn.get_locus ()}; | |
281 | auto resolved | |
282 | = new TyTy::FnType (fn.get_mappings ().get_hirid (), | |
283 | fn.get_mappings ().get_defid (), | |
284 | function.get_function_name (), ident, | |
285 | function.is_method () | |
286 | ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG | |
287 | : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, | |
288 | ABI::RUST, std::move (params), ret_type, substitutions); | |
289 | ||
290 | context->insert_type (fn.get_mappings (), resolved); | |
291 | return resolved; | |
292 | } | |
293 | ||
294 | } // namespace Resolver | |
295 | } // namespace Rust |