Line data Source code
1 : // Copyright (C) 2020-2026 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-pattern.h"
23 : #include "rust-hir-type-check-expr.h"
24 : #include "rust-hir-type-check-item.h"
25 : #include "rust-hir-type-check-pattern.h"
26 : #include "rust-hir-type-check-struct-field.h"
27 : #include "rust-finalized-name-resolution-context.h"
28 : #include "rust-rib.h"
29 :
30 : extern bool saw_errors (void);
31 :
32 : namespace Rust {
33 : namespace Resolver {
34 :
35 : tl::optional<TyTy::Region>
36 29721 : TypeCheckContext::LifetimeResolver::resolve (const Lifetime &placeholder) const
37 : {
38 29721 : if (placeholder.is_static ())
39 89 : return TyTy::Region::make_static ();
40 :
41 29632 : if (placeholder == Lifetime::anonymous_lifetime ())
42 29360 : return TyTy::Region::make_anonymous ();
43 :
44 314 : for (auto it = lifetime_lookup.rbegin (); it != lifetime_lookup.rend (); ++it)
45 : {
46 314 : if (it->first == placeholder)
47 : {
48 272 : if (it->second.scope <= ITEM_SCOPE)
49 : {
50 : // It is useful to have the static lifetime and named
51 : // lifetimed disjoint so we add the +1 here.
52 205 : return (is_body)
53 205 : ? TyTy::Region::make_named (it->second.index + 1)
54 205 : : TyTy::Region::make_early_bound (it->second.index);
55 : }
56 : else
57 : {
58 67 : return TyTy::Region::make_late_bound (get_current_scope ()
59 67 : - it->second.scope,
60 67 : it->second.index);
61 : }
62 : }
63 : }
64 :
65 0 : return tl::nullopt;
66 : }
67 :
68 : void
69 4538 : TypeResolution::Resolve (HIR::Crate &crate)
70 : {
71 22931 : for (auto &it : crate.get_items ())
72 18393 : TypeCheckItem::Resolve (*it);
73 :
74 4538 : if (saw_errors ())
75 : return;
76 :
77 4347 : OverlappingImplItemPass::go ();
78 4347 : if (saw_errors ())
79 : return;
80 :
81 4346 : auto context = TypeCheckContext::get ();
82 4346 : context->compute_inference_variables (true);
83 : }
84 :
85 : // rust-hir-trait-ref.h
86 :
87 7031 : TraitItemReference::TraitItemReference (
88 : std::string identifier, bool optional, TraitItemType type,
89 : HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
90 7031 : std::vector<TyTy::SubstitutionParamMapping> substitutions, location_t locus)
91 7031 : : identifier (identifier), optional_flag (optional), type (type),
92 7031 : hir_trait_item (hir_trait_item),
93 7031 : inherited_substitutions (std::move (substitutions)), locus (locus),
94 7031 : self (self), context (TypeCheckContext::get ())
95 7031 : {}
96 :
97 15340 : TraitItemReference::TraitItemReference (TraitItemReference const &other)
98 15340 : : identifier (other.identifier), optional_flag (other.optional_flag),
99 15340 : type (other.type), hir_trait_item (other.hir_trait_item),
100 15340 : locus (other.locus), self (other.self), context (TypeCheckContext::get ())
101 : {
102 15340 : inherited_substitutions.clear ();
103 15340 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
104 37396 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
105 44112 : inherited_substitutions.push_back (
106 22056 : other.inherited_substitutions.at (i).clone ());
107 15340 : }
108 :
109 : TraitItemReference &
110 3355 : TraitItemReference::operator= (TraitItemReference const &other)
111 : {
112 3355 : identifier = other.identifier;
113 3355 : optional_flag = other.optional_flag;
114 3355 : type = other.type;
115 3355 : hir_trait_item = other.hir_trait_item;
116 3355 : self = other.self;
117 3355 : locus = other.locus;
118 3355 : context = other.context;
119 :
120 3355 : inherited_substitutions.clear ();
121 3355 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
122 8136 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
123 9562 : inherited_substitutions.push_back (
124 4781 : other.inherited_substitutions.at (i).clone ());
125 :
126 3355 : return *this;
127 : }
128 :
129 : TyTy::BaseType *
130 18639 : TraitItemReference::get_type_from_typealias (/*const*/
131 : HIR::TraitItemType &type) const
132 : {
133 18639 : TyTy::TyVar var (get_mappings ().get_hirid ());
134 18639 : return var.get_tyty ();
135 : }
136 :
137 : TyTy::BaseType *
138 31 : TraitItemReference::get_type_from_constant (
139 : /*const*/ HIR::TraitItemConst &constant) const
140 : {
141 31 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
142 31 : if (constant.has_expr ())
143 : {
144 7 : TyTy::BaseType *expr = TypeCheckExpr::Resolve (constant.get_expr ());
145 :
146 14 : return unify_site (constant.get_mappings ().get_hirid (),
147 7 : TyTy::TyWithLocation (type),
148 7 : TyTy::TyWithLocation (expr), constant.get_locus ());
149 : }
150 : return type;
151 : }
152 :
153 : TyTy::BaseType *
154 24954 : TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
155 : {
156 24954 : auto binder_pin = context->push_clean_lifetime_resolver ();
157 :
158 24954 : std::vector<TyTy::SubstitutionParamMapping> substitutions
159 24954 : = inherited_substitutions;
160 :
161 24954 : TyTy::RegionConstraints region_constraints;
162 24954 : HIR::TraitFunctionDecl &function = fn.get_decl ();
163 24954 : if (function.has_generics ())
164 : {
165 64 : TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
166 : fn.get_locus (),
167 64 : function.get_generic_params (),
168 : substitutions, false /*is_foreign*/,
169 : ABI::RUST);
170 : }
171 :
172 24954 : if (function.has_where_clause ())
173 : {
174 0 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
175 0 : ResolveWhereClauseItem::Resolve (*where_clause_item,
176 : region_constraints);
177 : }
178 :
179 24954 : TyTy::BaseType *ret_type = nullptr;
180 24954 : if (!function.has_return_type ())
181 1411 : ret_type = TyTy::TupleType::get_unit_type ();
182 : else
183 : {
184 23543 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
185 23543 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
186 : {
187 2 : rust_error_at (fn.get_locus (), "failed to resolve return type");
188 2 : return get_error ();
189 : }
190 :
191 23541 : ret_type = resolved->clone ();
192 23541 : ret_type->set_ref (
193 23541 : function.get_return_type ().get_mappings ().get_hirid ());
194 : }
195 :
196 24952 : std::vector<TyTy::FnParam> params;
197 :
198 24952 : if (function.is_method ())
199 : {
200 : // these are implicit mappings and not used
201 24002 : auto &mappings = Analysis::Mappings::get ();
202 24002 : auto crate_num = mappings.get_current_crate ();
203 24002 : Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
204 : mappings.get_next_hir_id (crate_num),
205 24002 : UNKNOWN_LOCAL_DEFID);
206 :
207 : // add the synthetic self param at the front, this is a placeholder
208 : // for compilation to know parameter names. The types are ignored
209 : // but we reuse the HIR identifier pattern which requires it
210 24002 : HIR::SelfParam &self_param = function.get_self_unchecked ();
211 24002 : std::unique_ptr<HIR::Pattern> self_pattern
212 24002 : = std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern (
213 24002 : mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
214 24002 : self_param.is_mut () ? Mutability::Mut : Mutability::Imm,
215 120010 : std::unique_ptr<HIR::Pattern> (nullptr)));
216 : // might have a specified type
217 24002 : TyTy::BaseType *self_type = nullptr;
218 24002 : if (self_param.has_type ())
219 : {
220 0 : HIR::Type &specified_type = self_param.get_type ();
221 0 : self_type = TypeCheckType::Resolve (specified_type);
222 : }
223 : else
224 : {
225 24002 : switch (self_param.get_self_kind ())
226 : {
227 1742 : case HIR::SelfParam::IMM:
228 1742 : case HIR::SelfParam::MUT:
229 1742 : self_type = self->clone ();
230 1742 : break;
231 :
232 22260 : case HIR::SelfParam::IMM_REF:
233 22260 : case HIR::SelfParam::MUT_REF:
234 22260 : {
235 22260 : auto mutability
236 22260 : = self_param.get_self_kind () == HIR::SelfParam::IMM_REF
237 22260 : ? Mutability::Imm
238 22260 : : Mutability::Mut;
239 22260 : rust_assert (self_param.has_lifetime ());
240 :
241 22260 : auto region = TyTy::Region::make_anonymous ();
242 22260 : auto maybe_region = context->lookup_and_resolve_lifetime (
243 22260 : self_param.get_lifetime ());
244 22260 : if (maybe_region.has_value ())
245 22259 : region = maybe_region.value ();
246 : else
247 : {
248 1 : rust_error_at (self_param.get_locus (),
249 : "failed to resolve lifetime");
250 : }
251 :
252 44520 : self_type = new TyTy::ReferenceType (
253 22260 : self_param.get_mappings ().get_hirid (),
254 22260 : TyTy::TyVar (self->get_ref ()), mutability, region);
255 : }
256 22260 : break;
257 :
258 0 : default:
259 0 : rust_unreachable ();
260 : return nullptr;
261 : }
262 : }
263 :
264 24002 : context->insert_type (self_param.get_mappings (), self_type);
265 24002 : params.emplace_back (std::move (self_pattern), self_type);
266 24002 : }
267 :
268 44464 : for (auto ¶m : function.get_function_params ())
269 : {
270 : // get the name as well required for later on
271 19512 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
272 19512 : context->insert_type (param.get_mappings (), param_tyty);
273 19512 : TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
274 : // FIXME: Should we take the name ? Use a shared pointer instead ?
275 19512 : params.emplace_back (param.get_param_name ().clone_pattern (),
276 : param_tyty);
277 : }
278 :
279 24952 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
280 :
281 24952 : CanonicalPath canonical_path
282 24952 : = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid (),
283 24952 : Resolver2_0::Namespace::Types);
284 :
285 49904 : RustIdent ident{canonical_path, fn.get_locus ()};
286 24952 : auto resolved = new TyTy::FnType (
287 49904 : fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (),
288 24952 : function.get_function_name ().as_string (), ident,
289 24952 : function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
290 : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
291 : ABI::RUST, std::move (params), ret_type, substitutions,
292 49904 : TyTy::SubstitutionArgumentMappings::empty (
293 24952 : context->get_lifetime_resolver ().get_num_bound_regions ()),
294 124760 : region_constraints);
295 24952 : context->insert_type (fn.get_mappings (), resolved);
296 24952 : return resolved;
297 49906 : }
298 :
299 : } // namespace Resolver
300 : } // namespace Rust
|