libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / typecheck / rust-hir-type-check-item.cc
blob3e504e5df3221742cfadc07a870d1e27e43c480f
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
8 // version.
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.
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"
35 namespace Rust {
36 namespace Resolver {
38 TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
40 TyTy::BaseType *
41 TypeCheckItem::Resolve (HIR::Item &item)
43 // is it already resolved?
44 auto context = TypeCheckContext::get ();
45 TyTy::BaseType *resolved = nullptr;
46 bool already_resolved
47 = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
48 if (already_resolved)
49 return 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;
59 TyTy::BaseType *
60 TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
62 TypeCheckItem resolver;
63 return resolver.resolve_impl_item (impl_block, item);
66 TyTy::BaseType *
67 TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
69 TypeCheckItem resolver;
71 bool failed_flag = false;
72 auto result
73 = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
74 if (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);
85 TyTy::BaseType *
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);
94 if (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);
105 // nothing to do
106 if (substitutions.empty () || self->is_concrete ())
107 return self;
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 ()));
118 else
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 (
130 infer_arguments),
131 locus);
133 TyTy::BaseType *infer = SubstMapperInternal::Resolve (self, *infer_arguments);
135 // we only need to apply to the bounds manually on types which dont bind
136 // generics
137 if (!infer->has_substitutions_defined ())
139 for (auto &bound : infer->get_specified_bounds ())
140 bound.handle_substitions (*infer_arguments);
143 return infer;
146 void
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;
162 void
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;
178 size_t idx = 0;
179 for (auto &field : struct_decl.get_fields ())
181 TyTy::BaseType *field_type
182 = TypeCheckType::Resolve (field.get_field_type ().get ());
183 auto *ty_field
184 = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
185 std::to_string (idx), field_type,
186 field.get_locus ());
187 fields.push_back (ty_field);
188 context->insert_type (field.get_mappings (), ty_field->get_field_type ());
189 idx++;
192 // get the path
194 auto path = CanonicalPath::create_empty ();
196 // FIXME: HACK: ARTHUR: Disgusting
197 if (flag_name_resolution_2_0)
199 auto nr_ctx
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 ();
206 else
208 const CanonicalPath *canonical_path = nullptr;
209 bool ok = mappings->lookup_canonical_path (
210 struct_decl.get_mappings ().get_nodeid (), &canonical_path);
211 rust_assert (ok);
213 path = *canonical_path;
216 RustIdent ident{path, struct_decl.get_locus ()};
218 // its a single variant ADT
219 std::vector<TyTy::VariantDef *> variants;
220 variants.push_back (
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 ()),
239 region_constraints);
241 context->insert_type (struct_decl.get_mappings (), type);
242 infered = type;
244 context->get_variance_analysis_ctx ().add_type_constraints (*type);
247 void
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 ());
267 auto *ty_field
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)
280 auto nr_ctx
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 ())
286 rust_unreachable ();
287 path = canonical_path.value ();
289 else
291 const CanonicalPath *canonical_path = nullptr;
292 bool ok = mappings->lookup_canonical_path (
293 struct_decl.get_mappings ().get_nodeid (), &canonical_path);
294 rust_assert (ok);
296 path = *canonical_path;
299 RustIdent ident{path, struct_decl.get_locus ()};
301 // its a single variant ADT
302 std::vector<TyTy::VariantDef *> variants;
303 variants.push_back (
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 ()),
322 region_constraints);
324 context->insert_type (struct_decl.get_mappings (), type);
325 infered = type;
327 context->get_variance_analysis_ctx ().add_type_constraints (*type);
330 void
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);
349 // get the path
350 const CanonicalPath *canonical_path = nullptr;
351 bool ok
352 = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
353 &canonical_path);
354 rust_assert (ok);
355 RustIdent ident{*canonical_path, enum_decl.get_locus ()};
357 // multi variant ADT
358 auto *type
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);
366 infered = type;
368 context->get_variance_analysis_ctx ().add_type_constraints (*type);
371 void
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 ());
390 auto *ty_variant
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 ());
399 // get the path
400 const CanonicalPath *canonical_path = nullptr;
401 bool ok
402 = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
403 &canonical_path);
404 rust_assert (ok);
405 RustIdent ident{*canonical_path, union_decl.get_locus ()};
407 // there is only a single variant
408 std::vector<TyTy::VariantDef *> variants;
409 variants.push_back (
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)));
416 auto *type
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);
424 infered = type;
426 context->get_variance_analysis_ctx ().add_type_constraints (*type);
429 void
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 ()),
440 var.get_locus ());
441 context->insert_type (var.get_mappings (), unified);
442 infered = unified;
445 void
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);
458 infered = unified;
461 void
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);
468 if (failed_flag)
470 infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
471 return;
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,
483 substitutions);
486 // validate the impl items
487 validate_trait_impl_block (impl_block, self, substitutions);
490 TyTy::BaseType *
491 TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
492 HIR::ImplItem &item)
494 bool failed_flag = false;
495 auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
496 if (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);
510 void
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 ())
527 ret_type
528 = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
529 else
531 auto resolved
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");
537 return;
540 ret_type = resolved->clone ();
541 ret_type->set_ref (
542 function.get_return_type ()->get_mappings ().get_hirid ());
545 std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params;
546 for (auto &param : 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)
561 auto nr_ctx
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 ();
568 else
570 const CanonicalPath *canonical_path = nullptr;
571 bool ok = mappings->lookup_canonical_path (
572 function.get_mappings ().get_nodeid (), &canonical_path);
573 rust_assert (ok);
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 ()),
588 region_constraints);
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),
596 expected_ret_tyty);
598 context->switch_to_fn_body ();
599 auto block_expr_ty
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 ();
612 infered = fn_type;
615 void
616 TypeCheckItem::visit (HIR::Module &module)
618 for (auto &item : module.get_items ())
619 TypeCheckItem::Resolve (*item);
622 void
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 ());
629 return;
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 ())});
639 void
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,
650 bool &failure_flag)
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
671 // for example
672 specified_bound
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};
694 void
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
708 // for example
709 specified_bound
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 ())
719 auto trait_item_ref
720 = TypeCheckImplItemWithTrait::Resolve (&impl_block,
721 impl_item.get (), self,
722 specified_bound,
723 substitutions);
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>>
736 missing_trait_items;
737 for (const auto &trait_item_ref : trait_reference->get_trait_items ())
739 bool found = false;
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;
746 if (found)
747 break;
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 ());
790 TyTy::BaseType *
791 TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
793 return TypeCheckType::Resolve (impl_block.get_type ().get ());
796 } // namespace Resolver
797 } // namespace Rust