1 // Copyright (C) 2020-2023 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-implitem.h"
20 #include "rust-hir-type-check-base.h"
21 #include "rust-hir-full.h"
22 #include "rust-hir-type-check-type.h"
23 #include "rust-hir-type-check-expr.h"
24 #include "rust-hir-type-check-pattern.h"
25 #include "rust-tyty.h"
30 TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
31 const HIR::ExternBlock
&parent
)
32 : TypeCheckBase (), parent (parent
)
36 TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem
*item
,
37 const HIR::ExternBlock
&parent
)
39 // is it already resolved?
40 auto context
= TypeCheckContext::get ();
41 TyTy::BaseType
*resolved
= nullptr;
43 = context
->lookup_type (item
->get_mappings ().get_hirid (), &resolved
);
47 TypeCheckTopLevelExternItem
resolver (parent
);
48 item
->accept_vis (resolver
);
49 return resolver
.resolved
;
53 TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem
&item
)
55 TyTy::BaseType
*actual_type
56 = TypeCheckType::Resolve (item
.get_item_type ().get ());
58 context
->insert_type (item
.get_mappings (), actual_type
);
59 resolved
= actual_type
;
63 TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem
&function
)
65 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
66 if (function
.has_generics ())
68 for (auto &generic_param
: function
.get_generic_params ())
70 switch (generic_param
.get ()->get_kind ())
72 case HIR::GenericParam::GenericKind::LIFETIME
:
73 case HIR::GenericParam::GenericKind::CONST
:
74 // FIXME: Skipping Lifetime and Const completely until better
78 case HIR::GenericParam::GenericKind::TYPE
: {
80 = TypeResolveGenericParam::Resolve (generic_param
.get ());
81 context
->insert_type (generic_param
->get_mappings (),
84 substitutions
.push_back (TyTy::SubstitutionParamMapping (
85 static_cast<HIR::TypeParam
&> (*generic_param
), param_type
));
92 TyTy::BaseType
*ret_type
= nullptr;
93 if (!function
.has_return_type ())
95 = TyTy::TupleType::get_unit_type (function
.get_mappings ().get_hirid ());
99 = TypeCheckType::Resolve (function
.get_return_type ().get ());
100 if (resolved
== nullptr)
102 rust_error_at (function
.get_locus (),
103 "failed to resolve return type");
107 ret_type
= resolved
->clone ();
109 function
.get_return_type ()->get_mappings ().get_hirid ());
112 std::vector
<std::pair
<HIR::Pattern
*, TyTy::BaseType
*> > params
;
113 for (auto ¶m
: function
.get_function_params ())
115 // get the name as well required for later on
116 auto param_tyty
= TypeCheckType::Resolve (param
.get_type ().get ());
118 // these are implicit mappings and not used
119 auto crate_num
= mappings
->get_current_crate ();
120 Analysis::NodeMapping
mapping (crate_num
, mappings
->get_next_node_id (),
121 mappings
->get_next_hir_id (crate_num
),
122 UNKNOWN_LOCAL_DEFID
);
124 HIR::IdentifierPattern
*param_pattern
125 = new HIR::IdentifierPattern (mapping
, param
.get_param_name (),
126 Location (), false, Mutability::Imm
,
127 std::unique_ptr
<HIR::Pattern
> (nullptr));
130 std::pair
<HIR::Pattern
*, TyTy::BaseType
*> (param_pattern
,
133 context
->insert_type (param
.get_mappings (), param_tyty
);
135 // FIXME do we need error checking for patterns here?
136 // see https://github.com/Rust-GCC/gccrs/issues/995
139 uint8_t flags
= TyTy::FnType::FNTYPE_IS_EXTERN_FLAG
;
140 if (function
.is_variadic ())
141 flags
|= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG
;
144 CanonicalPath::new_seg (function
.get_mappings ().get_nodeid (),
145 function
.get_item_name ()),
146 function
.get_locus ()};
148 auto fnType
= new TyTy::FnType (function
.get_mappings ().get_hirid (),
149 function
.get_mappings ().get_defid (),
150 function
.get_item_name (), ident
, flags
,
151 parent
.get_abi (), std::move (params
),
152 ret_type
, std::move (substitutions
));
154 context
->insert_type (function
.get_mappings (), fnType
);
158 TypeCheckImplItem::TypeCheckImplItem (
159 HIR::ImplBlock
*parent
, TyTy::BaseType
*self
,
160 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
)
161 : TypeCheckBase (), parent (parent
), self (self
),
162 substitutions (substitutions
)
166 TypeCheckImplItem::Resolve (
167 HIR::ImplBlock
*parent
, HIR::ImplItem
*item
, TyTy::BaseType
*self
,
168 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
)
170 // is it already resolved?
171 auto context
= TypeCheckContext::get ();
172 TyTy::BaseType
*resolved
= nullptr;
173 bool already_resolved
174 = context
->lookup_type (item
->get_impl_mappings ().get_hirid (), &resolved
);
175 if (already_resolved
)
179 TypeCheckImplItem
resolver (parent
, self
, substitutions
);
180 item
->accept_vis (resolver
);
181 return resolver
.result
;
185 TypeCheckImplItem::visit (HIR::Function
&function
)
187 if (function
.has_generics ())
188 resolve_generic_params (function
.get_generic_params (), substitutions
);
190 for (auto &where_clause_item
: function
.get_where_clause ().get_items ())
192 ResolveWhereClauseItem::Resolve (*where_clause_item
.get ());
195 TyTy::BaseType
*ret_type
= nullptr;
196 if (!function
.has_function_return_type ())
198 = TyTy::TupleType::get_unit_type (function
.get_mappings ().get_hirid ());
202 = TypeCheckType::Resolve (function
.get_return_type ().get ());
203 if (resolved
== nullptr)
205 rust_error_at (function
.get_locus (),
206 "failed to resolve return type");
210 ret_type
= resolved
->clone ();
212 function
.get_return_type ()->get_mappings ().get_hirid ());
215 std::vector
<std::pair
<HIR::Pattern
*, TyTy::BaseType
*> > params
;
216 if (function
.is_method ())
218 // these are implicit mappings and not used
219 auto crate_num
= mappings
->get_current_crate ();
220 Analysis::NodeMapping
mapping (crate_num
, mappings
->get_next_node_id (),
221 mappings
->get_next_hir_id (crate_num
),
222 UNKNOWN_LOCAL_DEFID
);
224 // add the synthetic self param at the front, this is a placeholder for
225 // compilation to know parameter names. The types are ignored but we
226 // reuse the HIR identifier pattern which requires it
227 HIR::SelfParam
&self_param
= function
.get_self_param ();
228 HIR::IdentifierPattern
*self_pattern
229 = new HIR::IdentifierPattern (mapping
, "self", self_param
.get_locus (),
230 self_param
.is_ref (),
231 self_param
.get_mut (),
232 std::unique_ptr
<HIR::Pattern
> (nullptr));
234 // might have a specified type
235 TyTy::BaseType
*self_type
= nullptr;
236 if (self_param
.has_type ())
238 std::unique_ptr
<HIR::Type
> &specified_type
= self_param
.get_type ();
239 self_type
= TypeCheckType::Resolve (specified_type
.get ());
243 switch (self_param
.get_self_kind ())
245 case HIR::SelfParam::IMM
:
246 case HIR::SelfParam::MUT
:
247 self_type
= self
->clone ();
250 case HIR::SelfParam::IMM_REF
:
251 self_type
= new TyTy::ReferenceType (
252 self_param
.get_mappings ().get_hirid (),
253 TyTy::TyVar (self
->get_ref ()), Mutability::Imm
);
256 case HIR::SelfParam::MUT_REF
:
257 self_type
= new TyTy::ReferenceType (
258 self_param
.get_mappings ().get_hirid (),
259 TyTy::TyVar (self
->get_ref ()), Mutability::Mut
);
268 context
->insert_type (self_param
.get_mappings (), self_type
);
270 std::pair
<HIR::Pattern
*, TyTy::BaseType
*> (self_pattern
, self_type
));
273 for (auto ¶m
: function
.get_function_params ())
275 // get the name as well required for later on
276 auto param_tyty
= TypeCheckType::Resolve (param
.get_type ());
278 std::pair
<HIR::Pattern
*, TyTy::BaseType
*> (param
.get_param_name (),
281 context
->insert_type (param
.get_mappings (), param_tyty
);
282 TypeCheckPattern::Resolve (param
.get_param_name (), param_tyty
);
285 const CanonicalPath
*canonical_path
= nullptr;
287 = mappings
->lookup_canonical_path (function
.get_mappings ().get_nodeid (),
291 RustIdent ident
{*canonical_path
, function
.get_locus ()};
292 auto fnType
= new TyTy::FnType (function
.get_mappings ().get_hirid (),
293 function
.get_mappings ().get_defid (),
294 function
.get_function_name (), ident
,
295 function
.is_method ()
296 ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
297 : TyTy::FnType::FNTYPE_DEFAULT_FLAGS
,
298 ABI::RUST
, std::move (params
), ret_type
,
299 std::move (substitutions
));
301 context
->insert_type (function
.get_mappings (), fnType
);
304 // need to get the return type from this
305 TyTy::FnType
*resolve_fn_type
= fnType
;
306 auto expected_ret_tyty
= resolve_fn_type
->get_return_type ();
307 context
->push_return_type (TypeCheckContextItem (parent
, &function
),
311 = TypeCheckExpr::Resolve (function
.get_definition ().get ());
313 Location fn_return_locus
= function
.has_function_return_type ()
314 ? function
.get_return_type ()->get_locus ()
315 : function
.get_locus ();
317 coercion_site (function
.get_definition ()->get_mappings ().get_hirid (),
318 TyTy::TyWithLocation (expected_ret_tyty
, fn_return_locus
),
319 TyTy::TyWithLocation (block_expr_ty
),
320 function
.get_definition ()->get_locus ());
322 context
->pop_return_type ();
326 TypeCheckImplItem::visit (HIR::ConstantItem
&constant
)
328 TyTy::BaseType
*type
= TypeCheckType::Resolve (constant
.get_type ());
329 TyTy::BaseType
*expr_type
= TypeCheckExpr::Resolve (constant
.get_expr ());
331 TyTy::BaseType
*unified
= unify_site (
332 constant
.get_mappings ().get_hirid (),
333 TyTy::TyWithLocation (type
, constant
.get_type ()->get_locus ()),
334 TyTy::TyWithLocation (expr_type
, constant
.get_expr ()->get_locus ()),
335 constant
.get_locus ());
336 context
->insert_type (constant
.get_mappings (), unified
);
341 TypeCheckImplItem::visit (HIR::TypeAlias
&alias
)
343 TyTy::BaseType
*actual_type
344 = TypeCheckType::Resolve (alias
.get_type_aliased ().get ());
346 context
->insert_type (alias
.get_mappings (), actual_type
);
347 result
= actual_type
;
348 for (auto &where_clause_item
: alias
.get_where_clause ().get_items ())
350 ResolveWhereClauseItem::Resolve (*where_clause_item
.get ());
354 TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
355 HIR::ImplBlock
*parent
, TyTy::BaseType
*self
,
356 TyTy::TypeBoundPredicate
&trait_reference
,
357 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
)
358 : TypeCheckBase (), trait_reference (trait_reference
),
359 resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
360 parent (parent
), self (self
), substitutions (substitutions
)
362 rust_assert (is_trait_impl_block ());
365 TyTy::TypeBoundPredicateItem
366 TypeCheckImplItemWithTrait::Resolve (
367 HIR::ImplBlock
*parent
, HIR::ImplItem
*item
, TyTy::BaseType
*self
,
368 TyTy::TypeBoundPredicate
&trait_reference
,
369 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
)
371 TypeCheckImplItemWithTrait
resolver (parent
, self
, trait_reference
,
373 item
->accept_vis (resolver
);
374 return resolver
.resolved_trait_item
;
378 TypeCheckImplItemWithTrait::visit (HIR::ConstantItem
&constant
)
380 // normal resolution of the item
381 TyTy::BaseType
*lookup
382 = TypeCheckImplItem::Resolve (parent
, &constant
, self
, substitutions
);
384 // map the impl item to the associated trait item
385 const auto tref
= trait_reference
.get ();
386 const TraitItemReference
*raw_trait_item
= nullptr;
388 = tref
->lookup_trait_item_by_type (constant
.get_identifier (),
389 TraitItemReference::TraitItemType::CONST
,
392 // unknown trait item
393 if (!found
|| raw_trait_item
->is_error ())
395 RichLocation
r (constant
.get_locus ());
396 r
.add_range (trait_reference
.get_locus ());
397 rust_error_at (r
, "constant %<%s%> is not a member of trait %<%s%>",
398 constant
.get_identifier ().c_str (),
399 trait_reference
.get_name ().c_str ());
403 // get the item from the predicate
404 resolved_trait_item
= trait_reference
.lookup_associated_item (raw_trait_item
);
405 rust_assert (!resolved_trait_item
.is_error ());
407 // merge the attributes
408 const HIR::TraitItem
*hir_trait_item
409 = resolved_trait_item
.get_raw_item ()->get_hir_trait_item ();
410 merge_attributes (constant
.get_outer_attrs (), *hir_trait_item
);
412 // check the types are compatible
413 auto trait_item_type
= resolved_trait_item
.get_tyty_for_receiver (self
);
414 if (!trait_item_type
->can_eq (lookup
, true))
416 RichLocation
r (constant
.get_locus ());
417 r
.add_range (resolved_trait_item
.get_locus ());
420 r
, "constant %<%s%> has an incompatible type for trait %<%s%>",
421 constant
.get_identifier ().c_str (),
422 trait_reference
.get_name ().c_str ());
427 TypeCheckImplItemWithTrait::visit (HIR::TypeAlias
&type
)
429 // normal resolution of the item
430 TyTy::BaseType
*lookup
431 = TypeCheckImplItem::Resolve (parent
, &type
, self
, substitutions
);
433 // map the impl item to the associated trait item
434 const auto tref
= trait_reference
.get ();
435 const TraitItemReference
*raw_trait_item
= nullptr;
437 = tref
->lookup_trait_item_by_type (type
.get_new_type_name (),
438 TraitItemReference::TraitItemType::TYPE
,
441 // unknown trait item
442 if (!found
|| raw_trait_item
->is_error ())
444 RichLocation
r (type
.get_locus ());
445 r
.add_range (trait_reference
.get_locus ());
446 rust_error_at (r
, "type alias %<%s%> is not a member of trait %<%s%>",
447 type
.get_new_type_name ().c_str (),
448 trait_reference
.get_name ().c_str ());
452 // get the item from the predicate
453 resolved_trait_item
= trait_reference
.lookup_associated_item (raw_trait_item
);
454 rust_assert (!resolved_trait_item
.is_error ());
456 // merge the attributes
457 const HIR::TraitItem
*hir_trait_item
458 = resolved_trait_item
.get_raw_item ()->get_hir_trait_item ();
459 merge_attributes (type
.get_outer_attrs (), *hir_trait_item
);
461 // check the types are compatible
462 auto trait_item_type
= resolved_trait_item
.get_tyty_for_receiver (self
);
463 if (!trait_item_type
->can_eq (lookup
, true))
465 RichLocation
r (type
.get_locus ());
466 r
.add_range (resolved_trait_item
.get_locus ());
469 r
, "type alias %<%s%> has an incompatible type for trait %<%s%>",
470 type
.get_new_type_name ().c_str (),
471 trait_reference
.get_name ().c_str ());
474 // its actually a projection, since we need a way to actually bind the
475 // generic substitutions to the type itself
476 TyTy::ProjectionType
*projection
477 = new TyTy::ProjectionType (type
.get_mappings ().get_hirid (), lookup
, tref
,
478 raw_trait_item
->get_mappings ().get_defid (),
481 context
->insert_type (type
.get_mappings (), projection
);
482 raw_trait_item
->associated_type_set (projection
);
486 TypeCheckImplItemWithTrait::visit (HIR::Function
&function
)
488 // normal resolution of the item
489 TyTy::BaseType
*lookup
490 = TypeCheckImplItem::Resolve (parent
, &function
, self
, substitutions
);
492 // map the impl item to the associated trait item
493 const auto tref
= trait_reference
.get ();
494 const TraitItemReference
*raw_trait_item
= nullptr;
496 = tref
->lookup_trait_item_by_type (function
.get_function_name (),
497 TraitItemReference::TraitItemType::FN
,
500 // unknown trait item
501 if (!found
|| raw_trait_item
->is_error ())
503 RichLocation
r (function
.get_locus ());
504 r
.add_range (trait_reference
.get_locus ());
505 rust_error_at (r
, "method %<%s%> is not a member of trait %<%s%>",
506 function
.get_function_name ().c_str (),
507 trait_reference
.get_name ().c_str ());
511 // get the item from the predicate
512 resolved_trait_item
= trait_reference
.lookup_associated_item (raw_trait_item
);
513 rust_assert (!resolved_trait_item
.is_error ());
515 // merge the attributes
516 const HIR::TraitItem
*hir_trait_item
517 = resolved_trait_item
.get_raw_item ()->get_hir_trait_item ();
518 merge_attributes (function
.get_outer_attrs (), *hir_trait_item
);
520 // check the types are compatible
521 auto trait_item_type
= resolved_trait_item
.get_tyty_for_receiver (self
);
522 if (!trait_item_type
->can_eq (lookup
, true))
524 RichLocation
r (function
.get_locus ());
525 r
.add_range (resolved_trait_item
.get_locus ());
528 "method %<%s%> has an incompatible type for trait %<%s%>",
529 function
.get_function_name ().c_str (),
530 trait_reference
.get_name ().c_str ());
535 TypeCheckImplItemWithTrait::merge_attributes (AST::AttrVec
&impl_item_attrs
,
536 const HIR::TraitItem
&trait_item
)
538 for (const auto &attr
: trait_item
.get_outer_attrs ())
540 impl_item_attrs
.push_back (attr
);
545 TypeCheckImplItemWithTrait::is_trait_impl_block () const
547 return !trait_reference
.is_error ();
550 } // namespace Resolver