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 9802 : TypeCheckContext::LifetimeResolver::resolve (const Lifetime &placeholder) const
37 : {
38 9802 : if (placeholder.is_static ())
39 91 : return TyTy::Region::make_static ();
40 :
41 9711 : if (placeholder == Lifetime::anonymous_lifetime ())
42 9428 : return TyTy::Region::make_anonymous ();
43 :
44 327 : for (auto it = lifetime_lookup.rbegin (); it != lifetime_lookup.rend (); ++it)
45 : {
46 327 : if (it->first == placeholder)
47 : {
48 283 : 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 253 : return (is_body)
53 253 : ? TyTy::Region::make_named (it->second.index + 1)
54 253 : : TyTy::Region::make_early_bound (it->second.index);
55 : }
56 : else
57 : {
58 30 : return TyTy::Region::make_late_bound (get_current_scope ()
59 30 : - it->second.scope,
60 30 : it->second.index);
61 : }
62 : }
63 : }
64 :
65 0 : return tl::nullopt;
66 : }
67 :
68 : void
69 4707 : TypeResolution::Resolve (HIR::Crate &crate)
70 : {
71 24489 : for (auto &it : crate.get_items ())
72 19783 : TypeCheckItem::Resolve (*it);
73 :
74 4706 : if (saw_errors ())
75 : return;
76 :
77 4506 : OverlappingImplItemPass::go ();
78 4506 : if (saw_errors ())
79 : return;
80 :
81 4505 : auto context = TypeCheckContext::get ();
82 4505 : context->compute_inference_variables (true);
83 : }
84 :
85 : // rust-hir-trait-ref.h
86 :
87 7218 : 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_t locus)
91 7218 : : identifier (identifier), optional_flag (optional), type (type),
92 7218 : hir_trait_item (hir_trait_item),
93 7218 : inherited_substitutions (std::move (substitutions)), locus (locus),
94 7218 : self (self), context (TypeCheckContext::get ())
95 7218 : {}
96 :
97 16469 : TraitItemReference::TraitItemReference (TraitItemReference const &other)
98 16469 : : identifier (other.identifier), optional_flag (other.optional_flag),
99 16469 : type (other.type), hir_trait_item (other.hir_trait_item),
100 16469 : locus (other.locus), self (other.self), context (TypeCheckContext::get ())
101 : {
102 16469 : inherited_substitutions.clear ();
103 16469 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
104 56529 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
105 47182 : inherited_substitutions.push_back (
106 23591 : other.inherited_substitutions.at (i).clone ());
107 16469 : }
108 :
109 : TraitItemReference &
110 3602 : TraitItemReference::operator= (TraitItemReference const &other)
111 : {
112 3602 : identifier = other.identifier;
113 3602 : optional_flag = other.optional_flag;
114 3602 : type = other.type;
115 3602 : hir_trait_item = other.hir_trait_item;
116 3602 : self = other.self;
117 3602 : locus = other.locus;
118 3602 : context = other.context;
119 :
120 3602 : inherited_substitutions.clear ();
121 3602 : inherited_substitutions.reserve (other.inherited_substitutions.size ());
122 12325 : for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
123 10242 : inherited_substitutions.push_back (
124 5121 : other.inherited_substitutions.at (i).clone ());
125 :
126 3602 : return *this;
127 : }
128 :
129 : TyTy::BaseType *
130 8437 : TraitItemReference::get_type_from_typealias (/*const*/
131 : HIR::TraitItemType &type) const
132 : {
133 8437 : TyTy::TyVar var (get_mappings ().get_hirid ());
134 8437 : return var.get_tyty ();
135 : }
136 :
137 : TyTy::BaseType *
138 32 : TraitItemReference::get_type_from_constant (
139 : /*const*/ HIR::TraitItemConst &constant) const
140 : {
141 32 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
142 32 : 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 2748 : TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
155 : {
156 2748 : auto binder_pin = context->push_clean_lifetime_resolver ();
157 :
158 2748 : auto &mappings = Analysis::Mappings::get ();
159 2748 : auto *trait
160 2748 : = mappings.lookup_trait_item_mapping (get_mappings ().get_hirid ());
161 2748 : rust_assert (trait != nullptr);
162 6678 : for (auto ¶m : trait->get_generic_params ())
163 3930 : if (param->get_kind () == HIR::GenericParam::GenericKind::LIFETIME)
164 : {
165 9 : auto &lifetime_param = static_cast<HIR::LifetimeParam &> (*param);
166 9 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
167 : }
168 :
169 2748 : std::vector<TyTy::SubstitutionParamMapping> substitutions
170 2748 : = inherited_substitutions;
171 :
172 2748 : HIR::TraitFunctionDecl &function = fn.get_decl ();
173 2748 : if (function.has_generics ())
174 : {
175 29 : TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
176 : fn.get_locus (),
177 29 : function.get_generic_params (),
178 : substitutions, false /*is_foreign*/,
179 : ABI::RUST);
180 : }
181 :
182 2748 : TyTy::RegionConstraints region_constraints;
183 2748 : ResolveWhereClauseItem::Resolve (function.get_where_clause (),
184 : region_constraints);
185 :
186 2748 : TyTy::BaseType *ret_type = nullptr;
187 2748 : if (!function.has_return_type ())
188 465 : ret_type = TyTy::TupleType::get_unit_type ();
189 : else
190 : {
191 2283 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
192 2283 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
193 : {
194 2 : rust_error_at (fn.get_locus (), "failed to resolve return type");
195 2 : return get_error ();
196 : }
197 :
198 2281 : ret_type = resolved->clone ();
199 2281 : ret_type->set_ref (
200 2281 : function.get_return_type ().get_mappings ().get_hirid ());
201 : }
202 :
203 2746 : std::vector<TyTy::FnParam> params;
204 :
205 2746 : if (function.is_method ())
206 : {
207 : // these are implicit mappings and not used
208 2409 : auto &mappings = Analysis::Mappings::get ();
209 2409 : auto crate_num = mappings.get_current_crate ();
210 2409 : Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
211 : mappings.get_next_hir_id (crate_num),
212 2409 : UNKNOWN_LOCAL_DEFID);
213 :
214 : // add the synthetic self param at the front, this is a placeholder
215 : // for compilation to know parameter names. The types are ignored
216 : // but we reuse the HIR identifier pattern which requires it
217 2409 : HIR::SelfParam &self_param = function.get_self_unchecked ();
218 2409 : std::unique_ptr<HIR::Pattern> self_pattern
219 2409 : = std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern (
220 2409 : mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
221 2409 : self_param.is_mut () ? Mutability::Mut : Mutability::Imm,
222 11806 : std::unique_ptr<HIR::Pattern> (nullptr)));
223 : // might have a specified type
224 2409 : TyTy::BaseType *self_type = nullptr;
225 2409 : if (self_param.has_type ())
226 : {
227 1 : HIR::Type &specified_type = self_param.get_type ();
228 1 : self_type = TypeCheckType::Resolve (specified_type);
229 : }
230 : else
231 : {
232 2408 : switch (self_param.get_self_kind ())
233 : {
234 615 : case HIR::SelfParam::IMM:
235 615 : case HIR::SelfParam::MUT:
236 615 : self_type = self->clone ();
237 615 : break;
238 :
239 1793 : case HIR::SelfParam::IMM_REF:
240 1793 : case HIR::SelfParam::MUT_REF:
241 1793 : {
242 1793 : auto mutability
243 1793 : = self_param.get_self_kind () == HIR::SelfParam::IMM_REF
244 1793 : ? Mutability::Imm
245 1793 : : Mutability::Mut;
246 1793 : rust_assert (self_param.has_lifetime ());
247 :
248 1793 : auto region = TyTy::Region::make_anonymous ();
249 1793 : auto maybe_region = context->lookup_and_resolve_lifetime (
250 1793 : self_param.get_lifetime ());
251 1793 : if (maybe_region.has_value ())
252 1792 : region = maybe_region.value ();
253 : else
254 : {
255 1 : rust_error_at (self_param.get_locus (),
256 : "failed to resolve lifetime");
257 : }
258 :
259 3586 : self_type = new TyTy::ReferenceType (
260 1793 : self_param.get_mappings ().get_hirid (),
261 1793 : TyTy::TyVar (self->get_ref ()), mutability, region);
262 : }
263 1793 : break;
264 :
265 0 : default:
266 0 : rust_unreachable ();
267 : return nullptr;
268 : }
269 : }
270 :
271 2409 : context->insert_type (self_param.get_mappings (), self_type);
272 2409 : params.emplace_back (std::move (self_pattern), self_type);
273 2409 : }
274 :
275 4484 : for (auto ¶m : function.get_function_params ())
276 : {
277 : // get the name as well required for later on
278 1738 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
279 1738 : context->insert_type (param.get_mappings (), param_tyty);
280 1738 : TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
281 : // FIXME: Should we take the name ? Use a shared pointer instead ?
282 1738 : params.emplace_back (param.get_param_name ().clone_pattern (),
283 : param_tyty);
284 : }
285 :
286 2746 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
287 :
288 2746 : CanonicalPath canonical_path
289 2746 : = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid (),
290 2746 : Resolver2_0::Namespace::Types);
291 :
292 5492 : RustIdent ident{canonical_path, fn.get_locus ()};
293 2746 : auto resolved = new TyTy::FnType (
294 5492 : fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (),
295 2746 : function.get_function_name ().as_string (), ident,
296 2746 : function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
297 : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
298 : ABI::RUST, std::move (params), ret_type, substitutions,
299 5492 : TyTy::SubstitutionArgumentMappings::empty (
300 2746 : context->get_lifetime_resolver ().get_num_bound_regions ()),
301 13730 : region_constraints);
302 2746 : context->insert_type (fn.get_mappings (), resolved);
303 2746 : return resolved;
304 5494 : }
305 :
306 : } // namespace Resolver
307 : } // namespace Rust
|