]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/typecheck/rust-hir-type-check.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / typecheck / rust-hir-type-check.cc
CommitLineData
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
28extern bool
29saw_errors (void);
30
31namespace Rust {
32namespace Resolver {
33
34void
35TypeResolution::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
87TraitItemReference::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
97TraitItemReference::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
109TraitItemReference &
110TraitItemReference::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
129TyTy::BaseType *
130TraitItemReference::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
137TyTy::BaseType *
138TraitItemReference::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
152TyTy::BaseType *
153TraitItemReference::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 &param : 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