1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
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"
33 tl::optional
<TyTy::Region
>
34 TypeCheckContext::LifetimeResolver::resolve (const Lifetime
&placeholder
) const
36 if (placeholder
.is_static ())
37 return TyTy::Region::make_static ();
39 if (placeholder
== Lifetime::anonymous_lifetime ())
40 return TyTy::Region::make_anonymous ();
42 for (auto it
= lifetime_lookup
.rbegin (); it
!= lifetime_lookup
.rend (); ++it
)
44 if (it
->first
== placeholder
)
46 if (it
->second
.scope
<= ITEM_SCOPE
)
48 // It is useful to have the static lifetime and named
49 // lifetimed disjoint so we add the +1 here.
51 ? TyTy::Region::make_named (it
->second
.index
+ 1)
52 : TyTy::Region::make_early_bound (it
->second
.index
);
56 return TyTy::Region::make_late_bound (get_current_scope ()
67 TypeResolution::Resolve (HIR::Crate
&crate
)
69 for (auto &it
: crate
.get_items ())
70 TypeCheckItem::Resolve (*it
);
75 OverlappingImplItemPass::go ();
79 auto context
= TypeCheckContext::get ();
80 context
->compute_inference_variables (true);
83 // rust-hir-trait-ref.h
85 TraitItemReference::TraitItemReference (
86 std::string identifier
, bool optional
, TraitItemType type
,
87 HIR::TraitItem
*hir_trait_item
, TyTy::BaseType
*self
,
88 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
, location_t locus
)
89 : identifier (identifier
), optional_flag (optional
), type (type
),
90 hir_trait_item (hir_trait_item
),
91 inherited_substitutions (std::move (substitutions
)), locus (locus
),
92 self (self
), context (TypeCheckContext::get ())
95 TraitItemReference::TraitItemReference (TraitItemReference
const &other
)
96 : identifier (other
.identifier
), optional_flag (other
.optional_flag
),
97 type (other
.type
), hir_trait_item (other
.hir_trait_item
),
98 locus (other
.locus
), self (other
.self
), context (TypeCheckContext::get ())
100 inherited_substitutions
.clear ();
101 inherited_substitutions
.reserve (other
.inherited_substitutions
.size ());
102 for (size_t i
= 0; i
< other
.inherited_substitutions
.size (); i
++)
103 inherited_substitutions
.push_back (
104 other
.inherited_substitutions
.at (i
).clone ());
108 TraitItemReference::operator= (TraitItemReference
const &other
)
110 identifier
= other
.identifier
;
111 optional_flag
= other
.optional_flag
;
113 hir_trait_item
= other
.hir_trait_item
;
116 context
= other
.context
;
118 inherited_substitutions
.clear ();
119 inherited_substitutions
.reserve (other
.inherited_substitutions
.size ());
120 for (size_t i
= 0; i
< other
.inherited_substitutions
.size (); i
++)
121 inherited_substitutions
.push_back (
122 other
.inherited_substitutions
.at (i
).clone ());
128 TraitItemReference::get_type_from_typealias (/*const*/
129 HIR::TraitItemType
&type
) const
131 TyTy::TyVar
var (get_mappings ().get_hirid ());
132 return var
.get_tyty ();
136 TraitItemReference::get_type_from_constant (
137 /*const*/ HIR::TraitItemConst
&constant
) const
139 TyTy::BaseType
*type
= TypeCheckType::Resolve (constant
.get_type ().get ());
140 if (constant
.has_expr ())
143 = TypeCheckExpr::Resolve (constant
.get_expr ().get ());
145 return unify_site (constant
.get_mappings ().get_hirid (),
146 TyTy::TyWithLocation (type
),
147 TyTy::TyWithLocation (expr
), constant
.get_locus ());
153 TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc
&fn
) const
155 auto binder_pin
= context
->push_clean_lifetime_resolver ();
157 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
158 = inherited_substitutions
;
160 TyTy::RegionConstraints region_constraints
;
161 HIR::TraitFunctionDecl
&function
= fn
.get_decl ();
162 if (function
.has_generics ())
164 for (auto &generic_param
: function
.get_generic_params ())
166 switch (generic_param
.get ()->get_kind ())
168 case HIR::GenericParam::GenericKind::LIFETIME
: {
170 = static_cast<HIR::LifetimeParam
&> (*generic_param
);
172 context
->intern_and_insert_lifetime (
173 lifetime_param
.get_lifetime ());
174 // TODO: Handle lifetime bounds
177 case HIR::GenericParam::GenericKind::CONST
:
178 // FIXME: Skipping Lifetime and Const completely until better
182 case HIR::GenericParam::GenericKind::TYPE
: {
184 = TypeResolveGenericParam::Resolve (generic_param
.get ());
185 context
->insert_type (generic_param
->get_mappings (),
188 substitutions
.push_back (TyTy::SubstitutionParamMapping (
189 static_cast<HIR::TypeParam
&> (*generic_param
), param_type
));
196 if (function
.has_where_clause ())
198 for (auto &where_clause_item
: function
.get_where_clause ().get_items ())
199 ResolveWhereClauseItem::Resolve (*where_clause_item
,
203 TyTy::BaseType
*ret_type
= nullptr;
204 if (!function
.has_return_type ())
205 ret_type
= TyTy::TupleType::get_unit_type (fn
.get_mappings ().get_hirid ());
209 = TypeCheckType::Resolve (function
.get_return_type ().get ());
210 if (resolved
->get_kind () == TyTy::TypeKind::ERROR
)
212 rust_error_at (fn
.get_locus (), "failed to resolve return type");
216 ret_type
= resolved
->clone ();
218 function
.get_return_type ()->get_mappings ().get_hirid ());
221 std::vector
<std::pair
<HIR::Pattern
*, TyTy::BaseType
*> > params
;
222 if (function
.is_method ())
224 // these are implicit mappings and not used
225 auto mappings
= Analysis::Mappings::get ();
226 auto crate_num
= mappings
->get_current_crate ();
227 Analysis::NodeMapping
mapping (crate_num
, mappings
->get_next_node_id (),
228 mappings
->get_next_hir_id (crate_num
),
229 UNKNOWN_LOCAL_DEFID
);
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 HIR::SelfParam
&self_param
= function
.get_self ();
235 HIR::IdentifierPattern
*self_pattern
= new HIR::IdentifierPattern (
236 mapping
, {"self"}, self_param
.get_locus (), self_param
.is_ref (),
237 self_param
.is_mut () ? Mutability::Mut
: Mutability::Imm
,
238 std::unique_ptr
<HIR::Pattern
> (nullptr));
239 // might have a specified type
240 TyTy::BaseType
*self_type
= nullptr;
241 if (self_param
.has_type ())
243 std::unique_ptr
<HIR::Type
> &specified_type
= self_param
.get_type ();
244 self_type
= TypeCheckType::Resolve (specified_type
.get ());
248 switch (self_param
.get_self_kind ())
250 case HIR::SelfParam::IMM
:
251 case HIR::SelfParam::MUT
:
252 self_type
= self
->clone ();
255 case HIR::SelfParam::IMM_REF
:
256 case HIR::SelfParam::MUT_REF
: {
258 = self_param
.get_self_kind () == HIR::SelfParam::IMM_REF
261 rust_assert (self_param
.has_lifetime ());
263 auto maybe_region
= context
->lookup_and_resolve_lifetime (
264 self_param
.get_lifetime ());
266 if (!maybe_region
.has_value ())
268 rust_error_at (self_param
.get_locus (),
269 "failed to resolve lifetime");
272 self_type
= new TyTy::ReferenceType (
273 self_param
.get_mappings ().get_hirid (),
274 TyTy::TyVar (self
->get_ref ()), mutability
,
275 maybe_region
.value ());
285 context
->insert_type (self_param
.get_mappings (), self_type
);
287 std::pair
<HIR::Pattern
*, TyTy::BaseType
*> (self_pattern
, self_type
));
290 for (auto ¶m
: function
.get_function_params ())
292 // get the name as well required for later on
293 auto param_tyty
= TypeCheckType::Resolve (param
.get_type ().get ());
294 params
.push_back (std::pair
<HIR::Pattern
*, TyTy::BaseType
*> (
295 param
.get_param_name ().get (), param_tyty
));
297 context
->insert_type (param
.get_mappings (), param_tyty
);
298 TypeCheckPattern::Resolve (param
.get_param_name ().get (), param_tyty
);
301 auto mappings
= Analysis::Mappings::get ();
302 const CanonicalPath
*canonical_path
= nullptr;
303 bool ok
= mappings
->lookup_canonical_path (fn
.get_mappings ().get_nodeid (),
307 RustIdent ident
{*canonical_path
, fn
.get_locus ()};
308 auto resolved
= new TyTy::FnType (
309 fn
.get_mappings ().get_hirid (), fn
.get_mappings ().get_defid (),
310 function
.get_function_name ().as_string (), ident
,
311 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 TyTy::SubstitutionArgumentMappings::empty (
315 context
->get_lifetime_resolver ().get_num_bound_regions ()),
317 context
->insert_type (fn
.get_mappings (), resolved
);
321 } // namespace Resolver