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