libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / typecheck / rust-hir-type-check-implitem.cc
blob8a9a3f35a321b112f3cff3764466548337c67693
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-implitem.h"
20 #include "rust-diagnostics.h"
21 #include "rust-hir-type-check-base.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-type-util.h"
26 #include "rust-tyty.h"
28 namespace Rust {
29 namespace Resolver {
31 TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
32 const HIR::ExternBlock &parent)
33 : TypeCheckBase (), parent (parent)
36 TyTy::BaseType *
37 TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem *item,
38 const HIR::ExternBlock &parent)
40 // is it already resolved?
41 auto context = TypeCheckContext::get ();
42 TyTy::BaseType *resolved = nullptr;
43 bool already_resolved
44 = context->lookup_type (item->get_mappings ().get_hirid (), &resolved);
45 if (already_resolved)
46 return resolved;
48 TypeCheckTopLevelExternItem resolver (parent);
49 item->accept_vis (resolver);
50 return resolver.resolved;
53 void
54 TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item)
56 TyTy::BaseType *actual_type
57 = TypeCheckType::Resolve (item.get_item_type ().get ());
59 context->insert_type (item.get_mappings (), actual_type);
60 resolved = actual_type;
63 void
64 TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
66 auto binder_pin = context->push_clean_lifetime_resolver ();
68 std::vector<TyTy::SubstitutionParamMapping> substitutions;
69 if (function.has_generics ())
71 for (auto &generic_param : function.get_generic_params ())
73 switch (generic_param.get ()->get_kind ())
75 case HIR::GenericParam::GenericKind::LIFETIME:
76 context->intern_and_insert_lifetime (
77 static_cast<HIR::LifetimeParam &> (*generic_param)
78 .get_lifetime ());
79 // TODO: handle bounds
80 break;
81 case HIR::GenericParam::GenericKind::CONST:
82 // FIXME: Skipping Lifetime and Const completely until better
83 // handling.
84 break;
86 case HIR::GenericParam::GenericKind::TYPE: {
87 auto param_type
88 = TypeResolveGenericParam::Resolve (generic_param.get ());
89 context->insert_type (generic_param->get_mappings (),
90 param_type);
92 substitutions.push_back (TyTy::SubstitutionParamMapping (
93 static_cast<HIR::TypeParam &> (*generic_param), param_type));
95 break;
100 TyTy::RegionConstraints region_constraints;
101 if (function.has_where_clause ())
103 for (auto &where_clause_item : function.get_where_clause ().get_items ())
105 ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
106 region_constraints);
110 TyTy::BaseType *ret_type = nullptr;
111 if (!function.has_return_type ())
112 ret_type
113 = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
114 else
116 auto resolved
117 = TypeCheckType::Resolve (function.get_return_type ().get ());
118 if (resolved == nullptr)
120 rust_error_at (function.get_locus (),
121 "failed to resolve return type");
122 return;
125 ret_type = resolved->clone ();
126 ret_type->set_ref (
127 function.get_return_type ()->get_mappings ().get_hirid ());
130 std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
131 for (auto &param : function.get_function_params ())
133 // get the name as well required for later on
134 auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
136 // these are implicit mappings and not used
137 auto crate_num = mappings->get_current_crate ();
138 Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (),
139 mappings->get_next_hir_id (crate_num),
140 UNKNOWN_LOCAL_DEFID);
142 HIR::IdentifierPattern *param_pattern
143 = new HIR::IdentifierPattern (mapping, param.get_param_name (),
144 UNDEF_LOCATION, false, Mutability::Imm,
145 std::unique_ptr<HIR::Pattern> (nullptr));
147 params.push_back (
148 std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern,
149 param_tyty));
151 context->insert_type (param.get_mappings (), param_tyty);
153 // FIXME do we need error checking for patterns here?
154 // see https://github.com/Rust-GCC/gccrs/issues/995
157 uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
158 if (function.is_variadic ())
160 flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
161 if (parent.get_abi () != Rust::ABI::C)
163 rust_error_at (
164 function.get_locus (), ErrorCode::E0045,
165 "C-variadic function must have C or cdecl calling convention");
169 RustIdent ident{
170 CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
171 function.get_item_name ().as_string ()),
172 function.get_locus ()};
174 auto fnType = new TyTy::FnType (
175 function.get_mappings ().get_hirid (),
176 function.get_mappings ().get_defid (),
177 function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
178 std::move (params), ret_type, std::move (substitutions),
179 TyTy::SubstitutionArgumentMappings::empty (
180 context->get_lifetime_resolver ().get_num_bound_regions ()),
181 region_constraints);
183 context->insert_type (function.get_mappings (), fnType);
184 resolved = fnType;
187 void
188 TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
190 rust_sorry_at (type.get_locus (), "extern types are not supported yet");
191 // auto binder_pin = context->push_clean_lifetime_resolver ();
193 // std::vector<TyTy::SubstitutionParamMapping> substitutions;
194 // if (function.has_generics ())
195 // {
196 // for (auto &generic_param : function.get_generic_params ())
197 // {
198 // switch (generic_param.get ()->get_kind ())
199 // {
200 // case HIR::GenericParam::GenericKind::LIFETIME:
201 // context->intern_and_insert_lifetime (
202 // static_cast<HIR::LifetimeParam &> (*generic_param)
203 // .get_lifetime ());
204 // // TODO: handle bounds
205 // break;
206 // case HIR::GenericParam::GenericKind::CONST:
207 // // FIXME: Skipping Lifetime and Const completely until better
208 // // handling.
209 // break;
211 // case HIR::GenericParam::GenericKind::TYPE: {
212 // auto param_type
213 // = TypeResolveGenericParam::Resolve (generic_param.get ());
214 // context->insert_type (generic_param->get_mappings (),
215 // param_type);
217 // substitutions.push_back (TyTy::SubstitutionParamMapping (
218 // static_cast<HIR::TypeParam &> (*generic_param), param_type));
219 // }
220 // break;
221 // }
222 // }
223 // }
225 // TyTy::RegionConstraints region_constraints;
226 // if (function.has_where_clause ())
227 // {
228 // for (auto &where_clause_item : function.get_where_clause ().get_items
229 // ())
230 // {
231 // ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
232 // region_constraints);
233 // }
234 // }
236 // TyTy::BaseType *ret_type = nullptr;
237 // if (!function.has_return_type ())
238 // ret_type
239 // = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid
240 // ());
241 // else
242 // {
243 // auto resolved
244 // = TypeCheckType::Resolve (function.get_return_type ().get ());
245 // if (resolved == nullptr)
246 // {
247 // rust_error_at (function.get_locus (),
248 // "failed to resolve return type");
249 // return;
250 // }
252 // ret_type = resolved->clone ();
253 // ret_type->set_ref (
254 // function.get_return_type ()->get_mappings ().get_hirid ());
255 // }
257 // std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
258 // for (auto &param : function.get_function_params ())
259 // {
260 // // get the name as well required for later on
261 // auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
263 // // these are implicit mappings and not used
264 // auto crate_num = mappings->get_current_crate ();
265 // Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id
266 // (),
267 // mappings->get_next_hir_id (crate_num),
268 // UNKNOWN_LOCAL_DEFID);
270 // HIR::IdentifierPattern *param_pattern
271 // = new HIR::IdentifierPattern (mapping, param.get_param_name (),
272 // UNDEF_LOCATION, false, Mutability::Imm,
273 // std::unique_ptr<HIR::Pattern> (nullptr));
275 // params.push_back (
276 // std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern,
277 // param_tyty));
279 // context->insert_type (param.get_mappings (), param_tyty);
281 // // FIXME do we need error checking for patterns here?
282 // // see https://github.com/Rust-GCC/gccrs/issues/995
283 // }
285 // uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
286 // if (function.is_variadic ())
287 // {
288 // flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
289 // if (parent.get_abi () != Rust::ABI::C)
290 // {
291 // rust_error_at (
292 // function.get_locus (), ErrorCode::E0045,
293 // "C-variadic function must have C or cdecl calling convention");
294 // }
295 // }
297 // RustIdent ident{
298 // CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
299 // function.get_item_name ().as_string ()),
300 // function.get_locus ()};
302 // auto fnType = new TyTy::FnType (
303 // function.get_mappings ().get_hirid (),
304 // function.get_mappings ().get_defid (),
305 // function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
306 // std::move (params), ret_type, std::move (substitutions),
307 // TyTy::SubstitutionArgumentMappings::empty (
308 // context->get_lifetime_resolver ().get_num_bound_regions ()),
309 // region_constraints);
311 // context->insert_type (function.get_mappings (), fnType);
312 // resolved = fnType;
315 TypeCheckImplItem::TypeCheckImplItem (
316 HIR::ImplBlock *parent, TyTy::BaseType *self,
317 std::vector<TyTy::SubstitutionParamMapping> substitutions)
318 : TypeCheckBase (), parent (parent), self (self),
319 substitutions (substitutions)
322 TyTy::BaseType *
323 TypeCheckImplItem::Resolve (
324 HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
325 std::vector<TyTy::SubstitutionParamMapping> substitutions)
327 // is it already resolved?
328 auto context = TypeCheckContext::get ();
329 TyTy::BaseType *resolved = nullptr;
330 bool already_resolved
331 = context->lookup_type (item->get_impl_mappings ().get_hirid (), &resolved);
332 if (already_resolved)
333 return resolved;
335 // resolve
336 TypeCheckImplItem resolver (parent, self, substitutions);
337 item->accept_vis (resolver);
338 return resolver.result;
341 void
342 TypeCheckImplItem::visit (HIR::Function &function)
344 auto binder_pin = context->push_lifetime_binder ();
346 if (function.has_generics ())
347 resolve_generic_params (function.get_generic_params (), substitutions);
349 TyTy::RegionConstraints region_constraints;
350 for (auto &where_clause_item : function.get_where_clause ().get_items ())
352 ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
353 region_constraints);
356 TyTy::BaseType *ret_type = nullptr;
357 if (!function.has_function_return_type ())
358 ret_type
359 = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
360 else
362 auto resolved
363 = TypeCheckType::Resolve (function.get_return_type ().get ());
364 if (resolved == nullptr)
366 rust_error_at (function.get_locus (),
367 "failed to resolve return type");
368 return;
371 ret_type = resolved->clone ();
372 ret_type->set_ref (
373 function.get_return_type ()->get_mappings ().get_hirid ());
376 std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
377 if (function.is_method ())
379 // these are implicit mappings and not used
380 auto crate_num = mappings->get_current_crate ();
381 Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (),
382 mappings->get_next_hir_id (crate_num),
383 UNKNOWN_LOCAL_DEFID);
385 // add the synthetic self param at the front, this is a placeholder for
386 // compilation to know parameter names. The types are ignored but we
387 // reuse the HIR identifier pattern which requires it
388 HIR::SelfParam &self_param = function.get_self_param ();
389 // FIXME: which location should be used for Rust::Identifier for `self`?
390 HIR::IdentifierPattern *self_pattern = new HIR::IdentifierPattern (
391 mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
392 self_param.get_mut (), std::unique_ptr<HIR::Pattern> (nullptr));
394 // might have a specified type
395 TyTy::BaseType *self_type = nullptr;
396 if (self_param.has_type ())
398 std::unique_ptr<HIR::Type> &specified_type = self_param.get_type ();
399 self_type = TypeCheckType::Resolve (specified_type.get ());
401 else
403 switch (self_param.get_self_kind ())
405 case HIR::SelfParam::IMM:
406 case HIR::SelfParam::MUT:
407 self_type = self->clone ();
408 break;
410 case HIR::SelfParam::IMM_REF: {
411 auto region = context->lookup_and_resolve_lifetime (
412 self_param.get_lifetime ());
413 if (!region.has_value ())
415 rust_inform (self_param.get_locus (),
416 "failed to resolve lifetime");
417 region = TyTy::Region::make_anonymous (); // FIXME
419 self_type = new TyTy::ReferenceType (
420 self_param.get_mappings ().get_hirid (),
421 TyTy::TyVar (self->get_ref ()), Mutability::Imm,
422 region.value ());
424 break;
426 case HIR::SelfParam::MUT_REF: {
427 auto region = context->lookup_and_resolve_lifetime (
428 self_param.get_lifetime ());
429 if (!region.has_value ())
431 rust_error_at (self_param.get_locus (),
432 "failed to resolve lifetime");
433 return;
435 self_type = new TyTy::ReferenceType (
436 self_param.get_mappings ().get_hirid (),
437 TyTy::TyVar (self->get_ref ()), Mutability::Mut,
438 region.value ());
440 break;
442 default:
443 rust_unreachable ();
444 return;
448 context->insert_type (self_param.get_mappings (), self_type);
449 params.push_back (
450 std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, self_type));
453 for (auto &param : function.get_function_params ())
455 // get the name as well required for later on
456 auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
457 params.push_back (std::pair<HIR::Pattern *, TyTy::BaseType *> (
458 param.get_param_name ().get (), param_tyty));
460 context->insert_type (param.get_mappings (), param_tyty);
461 TypeCheckPattern::Resolve (param.get_param_name ().get (), param_tyty);
464 const CanonicalPath *canonical_path = nullptr;
465 bool ok
466 = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
467 &canonical_path);
468 rust_assert (ok);
470 RustIdent ident{*canonical_path, function.get_locus ()};
471 auto fnType = new TyTy::FnType (
472 function.get_mappings ().get_hirid (),
473 function.get_mappings ().get_defid (),
474 function.get_function_name ().as_string (), ident,
475 function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
476 : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
477 ABI::RUST, std::move (params), ret_type, std::move (substitutions),
478 TyTy::SubstitutionArgumentMappings::empty (
479 context->get_lifetime_resolver ().get_num_bound_regions ()),
480 region_constraints);
482 context->insert_type (function.get_mappings (), fnType);
483 result = fnType;
485 // need to get the return type from this
486 TyTy::FnType *resolve_fn_type = fnType;
487 auto expected_ret_tyty = resolve_fn_type->get_return_type ();
488 context->push_return_type (TypeCheckContextItem (parent, &function),
489 expected_ret_tyty);
491 auto block_expr_ty
492 = TypeCheckExpr::Resolve (function.get_definition ().get ());
494 location_t fn_return_locus = function.has_function_return_type ()
495 ? function.get_return_type ()->get_locus ()
496 : function.get_locus ();
498 coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
499 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
500 TyTy::TyWithLocation (block_expr_ty),
501 function.get_definition ()->get_locus ());
503 context->pop_return_type ();
506 void
507 TypeCheckImplItem::visit (HIR::ConstantItem &constant)
509 TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ().get ());
510 TyTy::BaseType *expr_type
511 = TypeCheckExpr::Resolve (constant.get_expr ().get ());
513 TyTy::BaseType *unified = unify_site (
514 constant.get_mappings ().get_hirid (),
515 TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
516 TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
517 constant.get_locus ());
518 context->insert_type (constant.get_mappings (), unified);
519 result = unified;
522 void
523 TypeCheckImplItem::visit (HIR::TypeAlias &alias)
525 auto binder_pin = context->push_lifetime_binder ();
527 if (alias.has_generics ())
528 resolve_generic_params (alias.get_generic_params (), substitutions);
530 TyTy::BaseType *actual_type
531 = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
533 context->insert_type (alias.get_mappings (), actual_type);
534 result = actual_type;
535 TyTy::RegionConstraints region_constraints;
536 for (auto &where_clause_item : alias.get_where_clause ().get_items ())
538 ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
539 region_constraints);
543 TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
544 HIR::ImplBlock *parent, TyTy::BaseType *self,
545 TyTy::TypeBoundPredicate &trait_reference,
546 std::vector<TyTy::SubstitutionParamMapping> substitutions)
547 : TypeCheckBase (), trait_reference (trait_reference),
548 resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
549 parent (parent), self (self), substitutions (substitutions)
551 rust_assert (is_trait_impl_block ());
554 TyTy::TypeBoundPredicateItem
555 TypeCheckImplItemWithTrait::Resolve (
556 HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
557 TyTy::TypeBoundPredicate &trait_reference,
558 std::vector<TyTy::SubstitutionParamMapping> substitutions)
560 TypeCheckImplItemWithTrait resolver (parent, self, trait_reference,
561 substitutions);
562 item->accept_vis (resolver);
563 return resolver.resolved_trait_item;
566 void
567 TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
569 // normal resolution of the item
570 TyTy::BaseType *lookup
571 = TypeCheckImplItem::Resolve (parent, &constant, self, substitutions);
573 // map the impl item to the associated trait item
574 const auto tref = trait_reference.get ();
575 const TraitItemReference *raw_trait_item = nullptr;
576 bool found
577 = tref->lookup_trait_item_by_type (constant.get_identifier ().as_string (),
578 TraitItemReference::TraitItemType::CONST,
579 &raw_trait_item);
581 // unknown trait item - https://doc.rust-lang.org/error_codes/E0323.html
582 if (!found || raw_trait_item->is_error ())
584 rich_location r (line_table, constant.get_locus ());
585 r.add_range (trait_reference.get_locus ());
586 rust_error_at (r, ErrorCode::E0323,
587 "item %qs is an associated const, which does not match "
588 "its trait %qs",
589 constant.get_identifier ().as_string ().c_str (),
590 trait_reference.get_name ().c_str ());
591 return;
594 // get the item from the predicate
595 resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
596 rust_assert (!resolved_trait_item.is_error ());
598 // merge the attributes
599 const HIR::TraitItem *hir_trait_item
600 = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
601 merge_attributes (constant.get_outer_attrs (), *hir_trait_item);
603 // check the types are compatible
604 auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
605 if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
606 TyTy::TyWithLocation (lookup), constant.get_locus (),
607 true /*emit_errors*/))
609 rich_location r (line_table, constant.get_locus ());
610 r.add_range (resolved_trait_item.get_locus ());
612 rust_error_at (
613 r, "constant %<%s%> has an incompatible type for trait %<%s%>",
614 constant.get_identifier ().as_string ().c_str (),
615 trait_reference.get_name ().c_str ());
619 void
620 TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
622 // normal resolution of the item
623 TyTy::BaseType *lookup
624 = TypeCheckImplItem::Resolve (parent, &type, self, substitutions);
626 // map the impl item to the associated trait item
627 const auto tref = trait_reference.get ();
628 const TraitItemReference *raw_trait_item = nullptr;
629 bool found
630 = tref->lookup_trait_item_by_type (type.get_new_type_name ().as_string (),
631 TraitItemReference::TraitItemType::TYPE,
632 &raw_trait_item);
634 // unknown trait item
635 if (!found || raw_trait_item->is_error ())
637 rich_location r (line_table, type.get_locus ());
638 r.add_range (trait_reference.get_locus ());
639 rust_error_at (r, "type alias %<%s%> is not a member of trait %<%s%>",
640 type.get_new_type_name ().as_string ().c_str (),
641 trait_reference.get_name ().c_str ());
642 return;
645 // get the item from the predicate
646 resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
647 rust_assert (!resolved_trait_item.is_error ());
649 // merge the attributes
650 const HIR::TraitItem *hir_trait_item
651 = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
652 merge_attributes (type.get_outer_attrs (), *hir_trait_item);
654 // check the types are compatible
655 auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
656 if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
657 TyTy::TyWithLocation (lookup), type.get_locus (),
658 true /*emit_errors*/))
660 rich_location r (line_table, type.get_locus ());
661 r.add_range (resolved_trait_item.get_locus ());
663 rust_error_at (
664 r, "type alias %<%s%> has an incompatible type for trait %<%s%>",
665 type.get_new_type_name ().as_string ().c_str (),
666 trait_reference.get_name ().c_str ());
669 // its actually a projection, since we need a way to actually bind the
670 // generic substitutions to the type itself
671 TyTy::ProjectionType *projection
672 = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup, tref,
673 raw_trait_item->get_mappings ().get_defid (),
674 substitutions);
676 context->insert_type (type.get_mappings (), projection);
677 raw_trait_item->associated_type_set (projection);
680 void
681 TypeCheckImplItemWithTrait::visit (HIR::Function &function)
683 // normal resolution of the item
684 TyTy::BaseType *lookup
685 = TypeCheckImplItem::Resolve (parent, &function, self, substitutions);
687 // map the impl item to the associated trait item
688 const auto tref = trait_reference.get ();
689 const TraitItemReference *raw_trait_item = nullptr;
690 bool found = tref->lookup_trait_item_by_type (
691 function.get_function_name ().as_string (),
692 TraitItemReference::TraitItemType::FN, &raw_trait_item);
694 // unknown trait item
695 if (!found || raw_trait_item->is_error ())
697 rich_location r (line_table, function.get_locus ());
698 r.add_range (trait_reference.get_locus ());
699 rust_error_at (r, "method %<%s%> is not a member of trait %<%s%>",
700 function.get_function_name ().as_string ().c_str (),
701 trait_reference.get_name ().c_str ());
702 return;
705 // get the item from the predicate
706 resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
707 rust_assert (!resolved_trait_item.is_error ());
709 // merge the attributes
710 const HIR::TraitItem *hir_trait_item
711 = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
712 merge_attributes (function.get_outer_attrs (), *hir_trait_item);
714 // check the types are compatible
715 auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
716 if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
717 TyTy::TyWithLocation (lookup), function.get_locus (),
718 true /*emit_errors*/))
720 rich_location r (line_table, function.get_locus ());
721 r.add_range (resolved_trait_item.get_locus ());
723 rust_error_at (r, ErrorCode::E0053,
724 "method %<%s%> has an incompatible type for trait %<%s%>",
725 function.get_function_name ().as_string ().c_str (),
726 trait_reference.get_name ().c_str ());
730 void
731 TypeCheckImplItemWithTrait::merge_attributes (AST::AttrVec &impl_item_attrs,
732 const HIR::TraitItem &trait_item)
734 for (const auto &attr : trait_item.get_outer_attrs ())
736 impl_item_attrs.push_back (attr);
740 bool
741 TypeCheckImplItemWithTrait::is_trait_impl_block () const
743 return !trait_reference.is_error ();
746 } // namespace Resolver
747 } // namespace Rust