1 // Copyright (C) 2020-2024 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-item.h"
20 #include "rust-canonical-path.h"
21 #include "rust-diagnostics.h"
22 #include "rust-hir-type-check-enumitem.h"
23 #include "rust-hir-type-check-implitem.h"
24 #include "rust-hir-type-check-type.h"
25 #include "rust-hir-type-check-expr.h"
26 #include "rust-hir-type-check-pattern.h"
27 #include "rust-hir-trait-resolve.h"
28 #include "rust-identifier.h"
29 #include "rust-session-manager.h"
30 #include "rust-immutable-name-resolution-context.h"
31 #include "rust-substitution-mapper.h"
32 #include "rust-type-util.h"
33 #include "rust-tyty-variance-analysis.h"
38 TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
41 TypeCheckItem::Resolve (HIR::Item
&item
)
43 // is it already resolved?
44 auto context
= TypeCheckContext::get ();
45 TyTy::BaseType
*resolved
= nullptr;
47 = context
->lookup_type (item
.get_mappings ().get_hirid (), &resolved
);
51 rust_assert (item
.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM
);
52 HIR::VisItem
&vis_item
= static_cast<HIR::VisItem
&> (item
);
54 TypeCheckItem resolver
;
55 vis_item
.accept_vis (resolver
);
56 return resolver
.infered
;
60 TypeCheckItem::ResolveImplItem (HIR::ImplBlock
&impl_block
, HIR::ImplItem
&item
)
62 TypeCheckItem resolver
;
63 return resolver
.resolve_impl_item (impl_block
, item
);
67 TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock
&impl_block
)
69 TypeCheckItem resolver
;
71 bool failed_flag
= false;
73 = resolver
.resolve_impl_block_substitutions (impl_block
, failed_flag
);
76 return new TyTy::ErrorType (impl_block
.get_mappings ().get_hirid ());
78 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
79 = std::move (result
.first
);
80 TyTy::RegionConstraints region_constraints
= std::move (result
.second
);
82 return resolver
.resolve_impl_block_self (impl_block
);
86 TypeCheckItem::ResolveImplBlockSelfWithInference (
87 HIR::ImplBlock
&impl
, location_t locus
,
88 TyTy::SubstitutionArgumentMappings
*infer_arguments
)
90 TypeCheckItem resolver
;
92 bool failed_flag
= false;
93 auto result
= resolver
.resolve_impl_block_substitutions (impl
, failed_flag
);
96 return new TyTy::ErrorType (impl
.get_mappings ().get_hirid ());
98 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
99 = std::move (result
.first
);
100 TyTy::RegionConstraints region_constraints
= std::move (result
.second
);
102 // now that we have the param mappings we need to query the self type
103 TyTy::BaseType
*self
= resolver
.resolve_impl_block_self (impl
);
106 if (substitutions
.empty () || self
->is_concrete ())
109 // generate inference variables for the subst-param-mappings
110 std::vector
<TyTy::SubstitutionArg
> args
;
111 for (auto &p
: substitutions
)
113 if (p
.needs_substitution ())
115 TyTy::TyVar infer_var
= TyTy::TyVar::get_implicit_infer_var (locus
);
116 args
.push_back (TyTy::SubstitutionArg (&p
, infer_var
.get_tyty ()));
120 TyTy::ParamType
*param
= p
.get_param_ty ();
121 TyTy::BaseType
*resolved
= param
->destructure ();
122 args
.push_back (TyTy::SubstitutionArg (&p
, resolved
));
126 // create argument mappings
127 *infer_arguments
= TyTy::SubstitutionArgumentMappings (
128 std::move (args
), {},
129 TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (
133 TyTy::BaseType
*infer
= SubstMapperInternal::Resolve (self
, *infer_arguments
);
135 // we only need to apply to the bounds manually on types which dont bind
137 if (!infer
->has_substitutions_defined ())
139 for (auto &bound
: infer
->get_specified_bounds ())
140 bound
.handle_substitions (*infer_arguments
);
147 TypeCheckItem::visit (HIR::TypeAlias
&alias
)
149 TyTy::BaseType
*actual_type
150 = TypeCheckType::Resolve (alias
.get_type_aliased ().get ());
152 context
->insert_type (alias
.get_mappings (), actual_type
);
154 TyTy::RegionConstraints region_constraints
;
155 for (auto &where_clause_item
: alias
.get_where_clause ().get_items ())
157 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
159 infered
= actual_type
;
163 TypeCheckItem::visit (HIR::TupleStruct
&struct_decl
)
165 auto lifetime_pin
= context
->push_clean_lifetime_resolver ();
167 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
168 if (struct_decl
.has_generics ())
169 resolve_generic_params (struct_decl
.get_generic_params (), substitutions
);
171 TyTy::RegionConstraints region_constraints
;
172 for (auto &where_clause_item
: struct_decl
.get_where_clause ().get_items ())
174 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
177 std::vector
<TyTy::StructFieldType
*> fields
;
179 for (auto &field
: struct_decl
.get_fields ())
181 TyTy::BaseType
*field_type
182 = TypeCheckType::Resolve (field
.get_field_type ().get ());
184 = new TyTy::StructFieldType (field
.get_mappings ().get_hirid (),
185 std::to_string (idx
), field_type
,
187 fields
.push_back (ty_field
);
188 context
->insert_type (field
.get_mappings (), ty_field
->get_field_type ());
194 auto path
= CanonicalPath::create_empty ();
196 // FIXME: HACK: ARTHUR: Disgusting
197 if (flag_name_resolution_2_0
)
200 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
201 auto canonical_path
= nr_ctx
.values
.to_canonical_path (
202 struct_decl
.get_mappings ().get_nodeid ());
204 path
= canonical_path
.value ();
208 const CanonicalPath
*canonical_path
= nullptr;
209 bool ok
= mappings
->lookup_canonical_path (
210 struct_decl
.get_mappings ().get_nodeid (), &canonical_path
);
213 path
= *canonical_path
;
216 RustIdent ident
{path
, struct_decl
.get_locus ()};
218 // its a single variant ADT
219 std::vector
<TyTy::VariantDef
*> variants
;
221 new TyTy::VariantDef (struct_decl
.get_mappings ().get_hirid (),
222 struct_decl
.get_mappings ().get_defid (),
223 struct_decl
.get_identifier ().as_string (), ident
,
224 TyTy::VariantDef::VariantType::TUPLE
, nullptr,
225 std::move (fields
)));
227 // Process #[repr(X)] attribute, if any
228 const AST::AttrVec
&attrs
= struct_decl
.get_outer_attrs ();
229 TyTy::ADTType::ReprOptions repr
230 = parse_repr_options (attrs
, struct_decl
.get_locus ());
232 auto *type
= new TyTy::ADTType (
233 struct_decl
.get_mappings ().get_hirid (), mappings
->get_next_hir_id (),
234 struct_decl
.get_identifier ().as_string (), ident
,
235 TyTy::ADTType::ADTKind::TUPLE_STRUCT
, std::move (variants
),
236 std::move (substitutions
), repr
,
237 TyTy::SubstitutionArgumentMappings::empty (
238 context
->get_lifetime_resolver ().get_num_bound_regions ()),
241 context
->insert_type (struct_decl
.get_mappings (), type
);
244 context
->get_variance_analysis_ctx ().add_type_constraints (*type
);
248 TypeCheckItem::visit (HIR::StructStruct
&struct_decl
)
250 auto lifetime_pin
= context
->push_clean_lifetime_resolver ();
252 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
253 if (struct_decl
.has_generics ())
254 resolve_generic_params (struct_decl
.get_generic_params (), substitutions
);
256 TyTy::RegionConstraints region_constraints
;
257 for (auto &where_clause_item
: struct_decl
.get_where_clause ().get_items ())
259 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
262 std::vector
<TyTy::StructFieldType
*> fields
;
263 for (auto &field
: struct_decl
.get_fields ())
265 TyTy::BaseType
*field_type
266 = TypeCheckType::Resolve (field
.get_field_type ().get ());
268 = new TyTy::StructFieldType (field
.get_mappings ().get_hirid (),
269 field
.get_field_name ().as_string (),
270 field_type
, field
.get_locus ());
271 fields
.push_back (ty_field
);
272 context
->insert_type (field
.get_mappings (), ty_field
->get_field_type ());
275 auto path
= CanonicalPath::create_empty ();
277 // FIXME: HACK: ARTHUR: Disgusting
278 if (flag_name_resolution_2_0
)
281 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
282 auto canonical_path
= nr_ctx
.types
.to_canonical_path (
283 struct_decl
.get_mappings ().get_nodeid ());
285 if (!canonical_path
.has_value ())
287 path
= canonical_path
.value ();
291 const CanonicalPath
*canonical_path
= nullptr;
292 bool ok
= mappings
->lookup_canonical_path (
293 struct_decl
.get_mappings ().get_nodeid (), &canonical_path
);
296 path
= *canonical_path
;
299 RustIdent ident
{path
, struct_decl
.get_locus ()};
301 // its a single variant ADT
302 std::vector
<TyTy::VariantDef
*> variants
;
304 new TyTy::VariantDef (struct_decl
.get_mappings ().get_hirid (),
305 struct_decl
.get_mappings ().get_defid (),
306 struct_decl
.get_identifier ().as_string (), ident
,
307 TyTy::VariantDef::VariantType::STRUCT
, nullptr,
308 std::move (fields
)));
310 // Process #[repr(X)] attribute, if any
311 const AST::AttrVec
&attrs
= struct_decl
.get_outer_attrs ();
312 TyTy::ADTType::ReprOptions repr
313 = parse_repr_options (attrs
, struct_decl
.get_locus ());
315 auto *type
= new TyTy::ADTType (
316 struct_decl
.get_mappings ().get_hirid (), mappings
->get_next_hir_id (),
317 struct_decl
.get_identifier ().as_string (), ident
,
318 TyTy::ADTType::ADTKind::STRUCT_STRUCT
, std::move (variants
),
319 std::move (substitutions
), repr
,
320 TyTy::SubstitutionArgumentMappings::empty (
321 context
->get_lifetime_resolver ().get_num_bound_regions ()),
324 context
->insert_type (struct_decl
.get_mappings (), type
);
327 context
->get_variance_analysis_ctx ().add_type_constraints (*type
);
331 TypeCheckItem::visit (HIR::Enum
&enum_decl
)
333 auto lifetime_pin
= context
->push_clean_lifetime_resolver ();
334 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
335 if (enum_decl
.has_generics ())
336 resolve_generic_params (enum_decl
.get_generic_params (), substitutions
);
338 std::vector
<TyTy::VariantDef
*> variants
;
339 int64_t discriminant_value
= 0;
340 for (auto &variant
: enum_decl
.get_variants ())
342 TyTy::VariantDef
*field_type
343 = TypeCheckEnumItem::Resolve (variant
.get (), discriminant_value
);
345 discriminant_value
++;
346 variants
.push_back (field_type
);
350 const CanonicalPath
*canonical_path
= nullptr;
352 = mappings
->lookup_canonical_path (enum_decl
.get_mappings ().get_nodeid (),
355 RustIdent ident
{*canonical_path
, enum_decl
.get_locus ()};
359 = new TyTy::ADTType (enum_decl
.get_mappings ().get_hirid (),
360 mappings
->get_next_hir_id (),
361 enum_decl
.get_identifier ().as_string (), ident
,
362 TyTy::ADTType::ADTKind::ENUM
, std::move (variants
),
363 std::move (substitutions
));
365 context
->insert_type (enum_decl
.get_mappings (), type
);
368 context
->get_variance_analysis_ctx ().add_type_constraints (*type
);
372 TypeCheckItem::visit (HIR::Union
&union_decl
)
374 auto lifetime_pin
= context
->push_clean_lifetime_resolver ();
375 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
376 if (union_decl
.has_generics ())
377 resolve_generic_params (union_decl
.get_generic_params (), substitutions
);
379 TyTy::RegionConstraints region_constraints
;
380 for (auto &where_clause_item
: union_decl
.get_where_clause ().get_items ())
382 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
385 std::vector
<TyTy::StructFieldType
*> fields
;
386 for (auto &variant
: union_decl
.get_variants ())
388 TyTy::BaseType
*variant_type
389 = TypeCheckType::Resolve (variant
.get_field_type ().get ());
391 = new TyTy::StructFieldType (variant
.get_mappings ().get_hirid (),
392 variant
.get_field_name ().as_string (),
393 variant_type
, variant
.get_locus ());
394 fields
.push_back (ty_variant
);
395 context
->insert_type (variant
.get_mappings (),
396 ty_variant
->get_field_type ());
400 const CanonicalPath
*canonical_path
= nullptr;
402 = mappings
->lookup_canonical_path (union_decl
.get_mappings ().get_nodeid (),
405 RustIdent ident
{*canonical_path
, union_decl
.get_locus ()};
407 // there is only a single variant
408 std::vector
<TyTy::VariantDef
*> variants
;
410 new TyTy::VariantDef (union_decl
.get_mappings ().get_hirid (),
411 union_decl
.get_mappings ().get_defid (),
412 union_decl
.get_identifier ().as_string (), ident
,
413 TyTy::VariantDef::VariantType::STRUCT
, nullptr,
414 std::move (fields
)));
417 = new TyTy::ADTType (union_decl
.get_mappings ().get_hirid (),
418 mappings
->get_next_hir_id (),
419 union_decl
.get_identifier ().as_string (), ident
,
420 TyTy::ADTType::ADTKind::UNION
, std::move (variants
),
421 std::move (substitutions
));
423 context
->insert_type (union_decl
.get_mappings (), type
);
426 context
->get_variance_analysis_ctx ().add_type_constraints (*type
);
430 TypeCheckItem::visit (HIR::StaticItem
&var
)
432 TyTy::BaseType
*type
= TypeCheckType::Resolve (var
.get_type ().get ());
433 TyTy::BaseType
*expr_type
= TypeCheckExpr::Resolve (var
.get_expr ().get ());
435 TyTy::BaseType
*unified
436 = coercion_site (var
.get_mappings ().get_hirid (),
437 TyTy::TyWithLocation (type
, var
.get_type ()->get_locus ()),
438 TyTy::TyWithLocation (expr_type
,
439 var
.get_expr ()->get_locus ()),
441 context
->insert_type (var
.get_mappings (), unified
);
446 TypeCheckItem::visit (HIR::ConstantItem
&constant
)
448 TyTy::BaseType
*type
= TypeCheckType::Resolve (constant
.get_type ().get ());
449 TyTy::BaseType
*expr_type
450 = TypeCheckExpr::Resolve (constant
.get_expr ().get ());
452 TyTy::BaseType
*unified
= unify_site (
453 constant
.get_mappings ().get_hirid (),
454 TyTy::TyWithLocation (type
, constant
.get_type ()->get_locus ()),
455 TyTy::TyWithLocation (expr_type
, constant
.get_expr ()->get_locus ()),
456 constant
.get_locus ());
457 context
->insert_type (constant
.get_mappings (), unified
);
462 TypeCheckItem::visit (HIR::ImplBlock
&impl_block
)
464 auto binder_pin
= context
->push_clean_lifetime_resolver (true);
466 bool failed_flag
= false;
467 auto result
= resolve_impl_block_substitutions (impl_block
, failed_flag
);
470 infered
= new TyTy::ErrorType (impl_block
.get_mappings ().get_hirid ());
473 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
474 = std::move (result
.first
);
475 TyTy::RegionConstraints region_constraints
= std::move (result
.second
);
477 TyTy::BaseType
*self
= resolve_impl_block_self (impl_block
);
479 // resolve each impl_item
480 for (auto &impl_item
: impl_block
.get_impl_items ())
482 TypeCheckImplItem::Resolve (&impl_block
, impl_item
.get (), self
,
486 // validate the impl items
487 validate_trait_impl_block (impl_block
, self
, substitutions
);
491 TypeCheckItem::resolve_impl_item (HIR::ImplBlock
&impl_block
,
494 bool failed_flag
= false;
495 auto result
= resolve_impl_block_substitutions (impl_block
, failed_flag
);
498 return new TyTy::ErrorType (impl_block
.get_mappings ().get_hirid ());
501 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
502 = std::move (result
.first
);
503 TyTy::RegionConstraints region_constraints
= std::move (result
.second
);
505 TyTy::BaseType
*self
= resolve_impl_block_self (impl_block
);
507 return TypeCheckImplItem::Resolve (&impl_block
, &item
, self
, substitutions
);
511 TypeCheckItem::visit (HIR::Function
&function
)
513 auto lifetime_pin
= context
->push_clean_lifetime_resolver ();
514 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
515 if (function
.has_generics ())
516 resolve_generic_params (function
.get_generic_params (),
517 substitutions
); // TODO resolve constraints
519 TyTy::RegionConstraints region_constraints
;
520 for (auto &where_clause_item
: function
.get_where_clause ().get_items ())
522 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
525 TyTy::BaseType
*ret_type
= nullptr;
526 if (!function
.has_function_return_type ())
528 = TyTy::TupleType::get_unit_type (function
.get_mappings ().get_hirid ());
532 = TypeCheckType::Resolve (function
.get_return_type ().get ());
533 if (resolved
->get_kind () == TyTy::TypeKind::ERROR
)
535 rust_error_at (function
.get_locus (),
536 "failed to resolve return type");
540 ret_type
= resolved
->clone ();
542 function
.get_return_type ()->get_mappings ().get_hirid ());
545 std::vector
<std::pair
<HIR::Pattern
*, TyTy::BaseType
*>> params
;
546 for (auto ¶m
: function
.get_function_params ())
548 // get the name as well required for later on
549 auto param_tyty
= TypeCheckType::Resolve (param
.get_type ().get ());
550 params
.emplace_back (param
.get_param_name ().get (), param_tyty
);
552 context
->insert_type (param
.get_mappings (), param_tyty
);
553 TypeCheckPattern::Resolve (param
.get_param_name ().get (), param_tyty
);
556 auto path
= CanonicalPath::create_empty ();
558 // FIXME: HACK: ARTHUR: Disgusting
559 if (flag_name_resolution_2_0
)
562 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
563 auto canonical_path
= nr_ctx
.values
.to_canonical_path (
564 function
.get_mappings ().get_nodeid ());
566 path
= canonical_path
.value ();
570 const CanonicalPath
*canonical_path
= nullptr;
571 bool ok
= mappings
->lookup_canonical_path (
572 function
.get_mappings ().get_nodeid (), &canonical_path
);
575 path
= *canonical_path
;
578 RustIdent ident
{path
, function
.get_locus ()};
580 auto fn_type
= new TyTy::FnType (
581 function
.get_mappings ().get_hirid (),
582 function
.get_mappings ().get_defid (),
583 function
.get_function_name ().as_string (), ident
,
584 TyTy::FnType::FNTYPE_DEFAULT_FLAGS
, ABI::RUST
, std::move (params
), ret_type
,
585 std::move (substitutions
),
586 TyTy::SubstitutionArgumentMappings::empty (
587 context
->get_lifetime_resolver ().get_num_bound_regions ()),
590 context
->insert_type (function
.get_mappings (), fn_type
);
592 // need to get the return type from this
593 TyTy::FnType
*resolved_fn_type
= fn_type
;
594 auto expected_ret_tyty
= resolved_fn_type
->get_return_type ();
595 context
->push_return_type (TypeCheckContextItem (&function
),
598 context
->switch_to_fn_body ();
600 = TypeCheckExpr::Resolve (function
.get_definition ().get ());
602 location_t fn_return_locus
= function
.has_function_return_type ()
603 ? function
.get_return_type ()->get_locus ()
604 : function
.get_locus ();
605 coercion_site (function
.get_definition ()->get_mappings ().get_hirid (),
606 TyTy::TyWithLocation (expected_ret_tyty
, fn_return_locus
),
607 TyTy::TyWithLocation (block_expr_ty
),
608 function
.get_definition ()->get_locus ());
610 context
->pop_return_type ();
616 TypeCheckItem::visit (HIR::Module
&module
)
618 for (auto &item
: module
.get_items ())
619 TypeCheckItem::Resolve (*item
);
623 TypeCheckItem::visit (HIR::Trait
&trait
)
625 TraitReference
*trait_ref
= TraitResolver::Resolve (trait
);
626 if (trait_ref
->is_error ())
628 infered
= new TyTy::ErrorType (trait
.get_mappings ().get_hirid ());
632 RustIdent ident
{CanonicalPath::create_empty (), trait
.get_locus ()};
633 infered
= new TyTy::DynamicObjectType (
634 trait
.get_mappings ().get_hirid (), ident
,
635 {TyTy::TypeBoundPredicate (*trait_ref
, BoundPolarity::RegularBound
,
636 trait
.get_locus ())});
640 TypeCheckItem::visit (HIR::ExternBlock
&extern_block
)
642 for (auto &item
: extern_block
.get_extern_items ())
644 TypeCheckTopLevelExternItem::Resolve (item
.get (), extern_block
);
648 std::pair
<std::vector
<TyTy::SubstitutionParamMapping
>, TyTy::RegionConstraints
>
649 TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock
&impl_block
,
652 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
;
653 if (impl_block
.has_generics ())
654 resolve_generic_params (impl_block
.get_generic_params (), substitutions
);
656 TyTy::RegionConstraints region_constraints
;
657 for (auto &where_clause_item
: impl_block
.get_where_clause ().get_items ())
659 ResolveWhereClauseItem::Resolve (*where_clause_item
, region_constraints
);
662 auto specified_bound
= TyTy::TypeBoundPredicate::error ();
663 TraitReference
*trait_reference
= &TraitReference::error_node ();
664 if (impl_block
.has_trait_ref ())
666 std::unique_ptr
<HIR::TypePath
> &ref
= impl_block
.get_trait_ref ();
667 trait_reference
= TraitResolver::Resolve (*ref
);
668 rust_assert (!trait_reference
->is_error ());
670 // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
673 = get_predicate_from_bound (*ref
, impl_block
.get_type ().get ());
676 TyTy::BaseType
*self
= TypeCheckType::Resolve (impl_block
.get_type ().get ());
678 // inherit the bounds
679 if (!specified_bound
.is_error ())
680 self
->inherit_bounds ({specified_bound
});
682 // check for any unconstrained type-params
683 const TyTy::SubstitutionArgumentMappings trait_constraints
684 = specified_bound
.get_substitution_arguments ();
685 const TyTy::SubstitutionArgumentMappings impl_constraints
686 = GetUsedSubstArgs::From (self
);
688 failure_flag
= check_for_unconstrained (substitutions
, trait_constraints
,
689 impl_constraints
, self
);
691 return {substitutions
, region_constraints
};
695 TypeCheckItem::validate_trait_impl_block (
696 HIR::ImplBlock
&impl_block
, TyTy::BaseType
*self
,
697 std::vector
<TyTy::SubstitutionParamMapping
> &substitutions
)
699 auto specified_bound
= TyTy::TypeBoundPredicate::error ();
700 TraitReference
*trait_reference
= &TraitReference::error_node ();
701 if (impl_block
.has_trait_ref ())
703 std::unique_ptr
<HIR::TypePath
> &ref
= impl_block
.get_trait_ref ();
704 trait_reference
= TraitResolver::Resolve (*ref
);
705 rust_assert (!trait_reference
->is_error ());
707 // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
710 = get_predicate_from_bound (*ref
, impl_block
.get_type ().get ());
713 bool is_trait_impl_block
= !trait_reference
->is_error ();
714 std::vector
<const TraitItemReference
*> trait_item_refs
;
715 for (auto &impl_item
: impl_block
.get_impl_items ())
717 if (!specified_bound
.is_error ())
720 = TypeCheckImplItemWithTrait::Resolve (&impl_block
,
721 impl_item
.get (), self
,
724 if (!trait_item_ref
.is_error ())
725 trait_item_refs
.push_back (trait_item_ref
.get_raw_item ());
729 bool impl_block_missing_trait_items
730 = !specified_bound
.is_error ()
731 && trait_reference
->size () != trait_item_refs
.size ();
732 if (impl_block_missing_trait_items
)
734 // filter the missing impl_items
735 std::vector
<std::reference_wrapper
<const TraitItemReference
>>
737 for (const auto &trait_item_ref
: trait_reference
->get_trait_items ())
740 for (auto implemented_trait_item
: trait_item_refs
)
742 std::string trait_item_name
= trait_item_ref
.get_identifier ();
743 std::string impl_item_name
744 = implemented_trait_item
->get_identifier ();
745 found
= trait_item_name
== impl_item_name
;
750 bool is_required_trait_item
= !trait_item_ref
.is_optional ();
751 if (!found
&& is_required_trait_item
)
752 missing_trait_items
.emplace_back (trait_item_ref
);
755 if (!missing_trait_items
.empty ())
757 std::string missing_items_buf
;
758 rich_location
r (line_table
, impl_block
.get_locus ());
759 for (size_t i
= 0; i
< missing_trait_items
.size (); i
++)
761 bool has_more
= (i
+ 1) < missing_trait_items
.size ();
762 const TraitItemReference
&missing_trait_item
763 = missing_trait_items
.at (i
);
764 missing_items_buf
+= missing_trait_item
.get_identifier ()
765 + (has_more
? ", " : "");
766 r
.add_range (missing_trait_item
.get_locus ());
769 rust_error_at (r
, ErrorCode::E0046
,
770 "missing %s in implementation of trait %<%s%>",
771 missing_items_buf
.c_str (),
772 trait_reference
->get_name ().c_str ());
776 if (is_trait_impl_block
)
778 trait_reference
->clear_associated_types ();
780 AssociatedImplTrait
associated (trait_reference
, specified_bound
,
781 &impl_block
, self
, context
);
782 context
->insert_associated_trait_impl (
783 impl_block
.get_mappings ().get_hirid (), std::move (associated
));
784 context
->insert_associated_impl_mapping (
785 trait_reference
->get_mappings ().get_hirid (), self
,
786 impl_block
.get_mappings ().get_hirid ());
791 TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock
&impl_block
)
793 return TypeCheckType::Resolve (impl_block
.get_type ().get ());
796 } // namespace Resolver