Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : : #include "rust-hir-type-check.h"
20 : : #include "rust-hir-full.h"
21 : : #include "rust-hir-inherent-impl-overlap.h"
22 : : #include "rust-hir-type-check-expr.h"
23 : : #include "rust-hir-type-check-item.h"
24 : : #include "rust-hir-type-check-pattern.h"
25 : : #include "rust-hir-type-check-struct-field.h"
26 : :
27 : : extern bool
28 : : saw_errors (void);
29 : :
30 : : namespace Rust {
31 : : namespace Resolver {
32 : :
33 : : tl::optional<TyTy::Region>
34 : 6206 : TypeCheckContext::LifetimeResolver::resolve (const Lifetime &placeholder) const
35 : : {
36 : 6206 : if (placeholder.is_static ())
37 : 12 : return TyTy::Region::make_static ();
38 : :
39 : 6194 : if (placeholder == Lifetime::anonymous_lifetime ())
40 : 5977 : return TyTy::Region::make_anonymous ();
41 : :
42 : 247 : for (auto it = lifetime_lookup.rbegin (); it != lifetime_lookup.rend (); ++it)
43 : : {
44 : 247 : if (it->first == placeholder)
45 : : {
46 : 217 : if (it->second.scope <= ITEM_SCOPE)
47 : : {
48 : : // It is useful to have the static lifetime and named
49 : : // lifetimed disjoint so we add the +1 here.
50 : 181 : return (is_body)
51 : 181 : ? TyTy::Region::make_named (it->second.index + 1)
52 : 181 : : TyTy::Region::make_early_bound (it->second.index);
53 : : }
54 : : else
55 : : {
56 : 36 : return TyTy::Region::make_late_bound (get_current_scope ()
57 : 36 : - it->second.scope,
58 : 36 : it->second.index);
59 : : }
60 : : }
61 : : }
62 : :
63 : 0 : return tl::nullopt;
64 : : }
65 : :
66 : : void
67 : 3480 : TypeResolution::Resolve (HIR::Crate &crate)
68 : : {
69 : 16632 : for (auto &it : crate.get_items ())
70 : 13155 : TypeCheckItem::Resolve (*it);
71 : :
72 : 3477 : if (saw_errors ())
73 : : return;
74 : :
75 : 3373 : OverlappingImplItemPass::go ();
76 : 3373 : if (saw_errors ())
77 : : return;
78 : :
79 : 3372 : auto context = TypeCheckContext::get ();
80 : 3372 : context->compute_inference_variables (true);
81 : : }
82 : :
83 : : // rust-hir-trait-ref.h
84 : :
85 : 3167 : TraitItemReference::TraitItemReference (
86 : : std::string identifier, bool optional, TraitItemType type,
87 : : HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
88 : 3167 : std::vector<TyTy::SubstitutionParamMapping> substitutions, location_t locus)
89 : 3167 : : identifier (identifier), optional_flag (optional), type (type),
90 : 3167 : hir_trait_item (hir_trait_item),
91 : 3167 : inherited_substitutions (std::move (substitutions)), locus (locus),
92 : 3167 : self (self), context (TypeCheckContext::get ())
93 : 3167 : {}
94 : :
95 : 6813 : TraitItemReference::TraitItemReference (TraitItemReference const &other)
96 : 6813 : : identifier (other.identifier), optional_flag (other.optional_flag),
97 : 6813 : type (other.type), hir_trait_item (other.hir_trait_item),
98 : 6813 : locus (other.locus), self (other.self), context (TypeCheckContext::get ())
99 : : {
100 : 6813 : inherited_substitutions.clear ();
101 : 6813 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
102 : 16336 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
103 : 19046 : inherited_substitutions.push_back (
104 : 9523 : other.inherited_substitutions.at (i).clone ());
105 : 6813 : }
106 : :
107 : : TraitItemReference &
108 : 1521 : TraitItemReference::operator= (TraitItemReference const &other)
109 : : {
110 : 1521 : identifier = other.identifier;
111 : 1521 : optional_flag = other.optional_flag;
112 : 1521 : type = other.type;
113 : 1521 : hir_trait_item = other.hir_trait_item;
114 : 1521 : self = other.self;
115 : 1521 : locus = other.locus;
116 : 1521 : context = other.context;
117 : :
118 : 1521 : inherited_substitutions.clear ();
119 : 1521 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
120 : 3641 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
121 : 4240 : inherited_substitutions.push_back (
122 : 2120 : other.inherited_substitutions.at (i).clone ());
123 : :
124 : 1521 : return *this;
125 : : }
126 : :
127 : : TyTy::BaseType *
128 : 5986 : TraitItemReference::get_type_from_typealias (/*const*/
129 : : HIR::TraitItemType &type) const
130 : : {
131 : 5986 : TyTy::TyVar var (get_mappings ().get_hirid ());
132 : 5986 : return var.get_tyty ();
133 : : }
134 : :
135 : : TyTy::BaseType *
136 : 29 : TraitItemReference::get_type_from_constant (
137 : : /*const*/ HIR::TraitItemConst &constant) const
138 : : {
139 : 29 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ().get ());
140 : 29 : if (constant.has_expr ())
141 : : {
142 : 7 : TyTy::BaseType *expr
143 : 7 : = TypeCheckExpr::Resolve (constant.get_expr ().get ());
144 : :
145 : 14 : return unify_site (constant.get_mappings ().get_hirid (),
146 : 7 : TyTy::TyWithLocation (type),
147 : 7 : TyTy::TyWithLocation (expr), constant.get_locus ());
148 : : }
149 : : return type;
150 : : }
151 : :
152 : : TyTy::BaseType *
153 : 5321 : TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
154 : : {
155 : 5321 : auto binder_pin = context->push_clean_lifetime_resolver ();
156 : :
157 : 5321 : std::vector<TyTy::SubstitutionParamMapping> substitutions
158 : 5321 : = inherited_substitutions;
159 : :
160 : 5321 : TyTy::RegionConstraints region_constraints;
161 : 5321 : HIR::TraitFunctionDecl &function = fn.get_decl ();
162 : 5321 : if (function.has_generics ())
163 : : {
164 : 28 : for (auto &generic_param : function.get_generic_params ())
165 : : {
166 : 14 : switch (generic_param.get ()->get_kind ())
167 : : {
168 : 0 : case HIR::GenericParam::GenericKind::LIFETIME: {
169 : 0 : auto lifetime_param
170 : 0 : = static_cast<HIR::LifetimeParam &> (*generic_param);
171 : :
172 : 0 : context->intern_and_insert_lifetime (
173 : 0 : lifetime_param.get_lifetime ());
174 : : // TODO: Handle lifetime bounds
175 : 0 : }
176 : 0 : break;
177 : : case HIR::GenericParam::GenericKind::CONST:
178 : : // FIXME: Skipping Lifetime and Const completely until better
179 : : // handling.
180 : : break;
181 : :
182 : 14 : case HIR::GenericParam::GenericKind::TYPE: {
183 : 14 : auto param_type
184 : 14 : = TypeResolveGenericParam::Resolve (generic_param.get ());
185 : 14 : context->insert_type (generic_param->get_mappings (),
186 : : param_type);
187 : :
188 : 14 : substitutions.push_back (TyTy::SubstitutionParamMapping (
189 : 14 : static_cast<HIR::TypeParam &> (*generic_param), param_type));
190 : : }
191 : 14 : break;
192 : : }
193 : : }
194 : : }
195 : :
196 : 5321 : if (function.has_where_clause ())
197 : : {
198 : 0 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
199 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item,
200 : : region_constraints);
201 : : }
202 : :
203 : 5321 : TyTy::BaseType *ret_type = nullptr;
204 : 5321 : if (!function.has_return_type ())
205 : 560 : ret_type = TyTy::TupleType::get_unit_type (fn.get_mappings ().get_hirid ());
206 : : else
207 : : {
208 : 4761 : auto resolved
209 : 4761 : = TypeCheckType::Resolve (function.get_return_type ().get ());
210 : 4761 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
211 : : {
212 : 0 : rust_error_at (fn.get_locus (), "failed to resolve return type");
213 : 0 : return get_error ();
214 : : }
215 : :
216 : 4761 : ret_type = resolved->clone ();
217 : 4761 : ret_type->set_ref (
218 : 9522 : function.get_return_type ()->get_mappings ().get_hirid ());
219 : : }
220 : :
221 : 10642 : std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
222 : 5321 : if (function.is_method ())
223 : : {
224 : : // these are implicit mappings and not used
225 : 4743 : auto mappings = Analysis::Mappings::get ();
226 : 4743 : auto crate_num = mappings->get_current_crate ();
227 : 4743 : Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (),
228 : : mappings->get_next_hir_id (crate_num),
229 : 4743 : UNKNOWN_LOCAL_DEFID);
230 : :
231 : : // add the synthetic self param at the front, this is a placeholder
232 : : // for compilation to know parameter names. The types are ignored
233 : : // but we reuse the HIR identifier pattern which requires it
234 : 4743 : HIR::SelfParam &self_param = function.get_self ();
235 : 4743 : HIR::IdentifierPattern *self_pattern = new HIR::IdentifierPattern (
236 : 4743 : mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
237 : 4743 : self_param.is_mut () ? Mutability::Mut : Mutability::Imm,
238 : 9308 : std::unique_ptr<HIR::Pattern> (nullptr));
239 : : // might have a specified type
240 : 4743 : TyTy::BaseType *self_type = nullptr;
241 : 4743 : if (self_param.has_type ())
242 : : {
243 : 0 : std::unique_ptr<HIR::Type> &specified_type = self_param.get_type ();
244 : 0 : self_type = TypeCheckType::Resolve (specified_type.get ());
245 : : }
246 : : else
247 : : {
248 : 4743 : switch (self_param.get_self_kind ())
249 : : {
250 : 1577 : case HIR::SelfParam::IMM:
251 : 1577 : case HIR::SelfParam::MUT:
252 : 1577 : self_type = self->clone ();
253 : 1577 : break;
254 : :
255 : 3166 : case HIR::SelfParam::IMM_REF:
256 : 3166 : case HIR::SelfParam::MUT_REF: {
257 : 3166 : auto mutability
258 : 3166 : = self_param.get_self_kind () == HIR::SelfParam::IMM_REF
259 : 3166 : ? Mutability::Imm
260 : 3166 : : Mutability::Mut;
261 : 3166 : rust_assert (self_param.has_lifetime ());
262 : :
263 : 3166 : auto maybe_region = context->lookup_and_resolve_lifetime (
264 : 3166 : self_param.get_lifetime ());
265 : :
266 : 3166 : if (!maybe_region.has_value ())
267 : : {
268 : 0 : rust_error_at (self_param.get_locus (),
269 : : "failed to resolve lifetime");
270 : 0 : return get_error ();
271 : : }
272 : 6332 : self_type = new TyTy::ReferenceType (
273 : 6332 : self_param.get_mappings ().get_hirid (),
274 : 3166 : TyTy::TyVar (self->get_ref ()), mutability,
275 : 6332 : maybe_region.value ());
276 : : }
277 : 3166 : break;
278 : :
279 : 0 : default:
280 : 0 : rust_unreachable ();
281 : : return nullptr;
282 : : }
283 : : }
284 : :
285 : 4743 : context->insert_type (self_param.get_mappings (), self_type);
286 : 4743 : params.push_back (
287 : 4743 : std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, self_type));
288 : : }
289 : :
290 : 7286 : for (auto ¶m : function.get_function_params ())
291 : : {
292 : : // get the name as well required for later on
293 : 1965 : auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
294 : 1965 : params.push_back (std::pair<HIR::Pattern *, TyTy::BaseType *> (
295 : 1965 : param.get_param_name ().get (), param_tyty));
296 : :
297 : 1965 : context->insert_type (param.get_mappings (), param_tyty);
298 : 1965 : TypeCheckPattern::Resolve (param.get_param_name ().get (), param_tyty);
299 : : }
300 : :
301 : 5321 : auto mappings = Analysis::Mappings::get ();
302 : 5321 : const CanonicalPath *canonical_path = nullptr;
303 : 5321 : bool ok = mappings->lookup_canonical_path (fn.get_mappings ().get_nodeid (),
304 : : &canonical_path);
305 : 0 : rust_assert (ok);
306 : :
307 : 10642 : RustIdent ident{*canonical_path, fn.get_locus ()};
308 : 5321 : auto resolved = new TyTy::FnType (
309 : 10642 : fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (),
310 : 5321 : function.get_function_name ().as_string (), ident,
311 : 5321 : function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
312 : : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
313 : : ABI::RUST, std::move (params), ret_type, substitutions,
314 : 10642 : TyTy::SubstitutionArgumentMappings::empty (
315 : 5321 : context->get_lifetime_resolver ().get_num_bound_regions ()),
316 : 21284 : region_constraints);
317 : 5321 : context->insert_type (fn.get_mappings (), resolved);
318 : 5321 : return resolved;
319 : 5321 : }
320 : :
321 : : } // namespace Resolver
322 : : } // namespace Rust
|