Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
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.
9 :
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.
14 :
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/>.
18 :
19 : #include "rust-hir-type-check-implitem.h"
20 : #include "rust-diagnostics.h"
21 : #include "rust-hir-full-decls.h"
22 : #include "rust-hir-pattern.h"
23 : #include "rust-hir-type-check-base.h"
24 : #include "rust-hir-type-check-intrinsic.h"
25 : #include "rust-hir-type-check-type.h"
26 : #include "rust-hir-type-check-expr.h"
27 : #include "rust-hir-type-check-pattern.h"
28 : #include "rust-rib.h"
29 : #include "rust-type-util.h"
30 : #include "rust-tyty.h"
31 : #include "rust-finalized-name-resolution-context.h"
32 :
33 : namespace Rust {
34 : namespace Resolver {
35 :
36 2544 : TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
37 2544 : const HIR::ExternBlock &parent)
38 2544 : : TypeCheckBase (), parent (parent)
39 2544 : {}
40 :
41 : TyTy::BaseType *
42 2594 : TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem &item,
43 : const HIR::ExternBlock &parent)
44 : {
45 : // is it already resolved?
46 2594 : auto context = TypeCheckContext::get ();
47 2594 : TyTy::BaseType *resolved = nullptr;
48 2594 : bool already_resolved
49 2594 : = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
50 2594 : if (already_resolved)
51 50 : return resolved;
52 :
53 2544 : TypeCheckTopLevelExternItem resolver (parent);
54 2544 : item.accept_vis (resolver);
55 2544 : return resolver.resolved;
56 2544 : }
57 :
58 : void
59 1 : TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item)
60 : {
61 1 : TyTy::BaseType *actual_type = TypeCheckType::Resolve (item.get_item_type ());
62 :
63 1 : context->insert_type (item.get_mappings (), actual_type);
64 1 : resolved = actual_type;
65 1 : }
66 :
67 : void
68 2543 : TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
69 : {
70 2543 : auto binder_pin = context->push_clean_lifetime_resolver ();
71 :
72 2543 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
73 2543 : if (function.has_generics ())
74 : {
75 978 : resolve_generic_params (HIR::Item::ItemKind::Function,
76 : function.get_locus (),
77 978 : function.get_generic_params (), substitutions,
78 978 : true /*is_foreign*/, parent.get_abi ());
79 : }
80 :
81 2543 : TyTy::RegionConstraints region_constraints;
82 2543 : if (function.has_where_clause ())
83 : {
84 0 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
85 : {
86 0 : ResolveWhereClauseItem::Resolve (*where_clause_item,
87 : region_constraints);
88 : }
89 : }
90 :
91 2543 : TyTy::BaseType *ret_type = nullptr;
92 2543 : if (!function.has_return_type ())
93 1212 : ret_type = TyTy::TupleType::get_unit_type ();
94 : else
95 : {
96 1331 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
97 1331 : if (resolved == nullptr)
98 : {
99 0 : rust_error_at (function.get_locus (),
100 : "failed to resolve return type");
101 0 : return;
102 : }
103 :
104 1331 : ret_type = resolved->clone ();
105 1331 : ret_type->set_ref (
106 1331 : function.get_return_type ().get_mappings ().get_hirid ());
107 : }
108 :
109 2543 : std::vector<TyTy::FnParam> params;
110 5432 : for (auto ¶m : function.get_function_params ())
111 : {
112 : // get the name as well required for later on
113 2889 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
114 :
115 : // these are implicit mappings and not used
116 2889 : auto crate_num = mappings.get_current_crate ();
117 5778 : Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
118 2889 : mappings.get_next_hir_id (crate_num),
119 2889 : UNKNOWN_LOCAL_DEFID);
120 :
121 2889 : auto param_pattern = std::make_unique<HIR::IdentifierPattern> (
122 2889 : HIR::IdentifierPattern (mapping, param.get_param_name (),
123 : UNDEF_LOCATION, false, Mutability::Imm,
124 5778 : std::unique_ptr<HIR::Pattern> (nullptr)));
125 :
126 2889 : params.emplace_back (std::move (param_pattern), param_tyty);
127 :
128 2889 : context->insert_type (param.get_mappings (), param_tyty);
129 :
130 : // FIXME do we need error checking for patterns here?
131 : // see https://github.com/Rust-GCC/gccrs/issues/995
132 2889 : }
133 :
134 2543 : uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
135 2543 : if (function.is_variadic ())
136 : {
137 849 : flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
138 849 : if (parent.get_abi () != Rust::ABI::C)
139 : {
140 1 : rust_error_at (
141 : function.get_locus (), ErrorCode::E0045,
142 : "C-variadic function must have C or cdecl calling convention");
143 : }
144 : }
145 :
146 2543 : RustIdent ident{
147 5086 : CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
148 2543 : function.get_item_name ().as_string ()),
149 2543 : function.get_locus ()};
150 :
151 2543 : auto fnType = new TyTy::FnType (
152 2543 : function.get_mappings ().get_hirid (),
153 5086 : function.get_mappings ().get_defid (),
154 2543 : function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
155 : std::move (params), ret_type, std::move (substitutions),
156 5086 : TyTy::SubstitutionArgumentMappings::empty (
157 2543 : context->get_lifetime_resolver ().get_num_bound_regions ()),
158 10172 : region_constraints);
159 :
160 2543 : context->insert_type (function.get_mappings (), fnType);
161 :
162 2543 : if (parent.get_abi () == Rust::ABI::INTRINSIC
163 2543 : && IntrinsicChecker::check (fnType) == IntrinsicCheckResult::Invalid)
164 14 : return;
165 :
166 2529 : resolved = fnType;
167 5086 : }
168 :
169 : void
170 0 : TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
171 : {
172 0 : rust_sorry_at (type.get_locus (), "extern types are not supported yet");
173 : // TODO
174 0 : }
175 :
176 8182 : TypeCheckImplItem::TypeCheckImplItem (
177 : HIR::ImplBlock &parent, TyTy::BaseType *self,
178 8182 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
179 8182 : : TypeCheckBase (), parent (parent), self (self),
180 8182 : substitutions (substitutions)
181 8182 : {}
182 :
183 : TyTy::BaseType *
184 11842 : TypeCheckImplItem::Resolve (
185 : HIR::ImplBlock &parent, HIR::ImplItem &item, TyTy::BaseType *self,
186 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
187 : {
188 : // is it already resolved?
189 11842 : auto context = TypeCheckContext::get ();
190 11842 : TyTy::BaseType *resolved = nullptr;
191 11842 : bool already_resolved
192 11842 : = context->lookup_type (item.get_impl_mappings ().get_hirid (), &resolved);
193 11842 : if (already_resolved)
194 3660 : return resolved;
195 :
196 : // resolve
197 8182 : TypeCheckImplItem resolver (parent, self, substitutions);
198 8182 : resolver.context->block_context ().enter (
199 8182 : TypeCheckBlockContextItem (&parent));
200 8182 : item.accept_vis (resolver);
201 8182 : resolver.context->block_context ().exit ();
202 :
203 8182 : return resolver.result;
204 8182 : }
205 :
206 : void
207 6929 : TypeCheckImplItem::visit (HIR::Function &function)
208 : {
209 6929 : auto binder_pin = context->push_lifetime_binder ();
210 :
211 6929 : if (function.has_generics ())
212 112 : resolve_generic_params (HIR::Item::ItemKind::Function,
213 : function.get_locus (),
214 112 : function.get_generic_params (), substitutions);
215 :
216 6929 : TyTy::RegionConstraints region_constraints;
217 6930 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
218 : {
219 1 : ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
220 : region_constraints);
221 : }
222 :
223 6929 : TyTy::BaseType *ret_type = nullptr;
224 6929 : if (!function.has_function_return_type ())
225 423 : ret_type = TyTy::TupleType::get_unit_type ();
226 : else
227 : {
228 6506 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
229 6506 : if (resolved == nullptr)
230 : {
231 0 : rust_error_at (function.get_locus (),
232 : "failed to resolve return type");
233 0 : return;
234 : }
235 :
236 6506 : ret_type = resolved->clone ();
237 6506 : ret_type->set_ref (
238 6506 : function.get_return_type ().get_mappings ().get_hirid ());
239 : }
240 :
241 6929 : std::vector<TyTy::FnParam> params;
242 6929 : if (function.is_method ())
243 : {
244 : // these are implicit mappings and not used
245 5811 : auto crate_num = mappings.get_current_crate ();
246 11622 : Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
247 5811 : mappings.get_next_hir_id (crate_num),
248 5811 : UNKNOWN_LOCAL_DEFID);
249 :
250 : // add the synthetic self param at the front, this is a placeholder for
251 : // compilation to know parameter names. The types are ignored but we
252 : // reuse the HIR identifier pattern which requires it
253 5811 : HIR::SelfParam &self_param = function.get_self_param_unchecked ();
254 : // FIXME: which location should be used for Rust::Identifier for `self`?
255 5811 : std::unique_ptr<HIR::Pattern> self_pattern
256 5811 : = std::make_unique<HIR::IdentifierPattern> (
257 11622 : HIR::IdentifierPattern (mapping, {"self"}, self_param.get_locus (),
258 5811 : self_param.is_ref (), self_param.get_mut (),
259 29055 : std::unique_ptr<HIR::Pattern> (nullptr)));
260 :
261 : // might have a specified type
262 5811 : TyTy::BaseType *self_type = nullptr;
263 5811 : if (self_param.has_type ())
264 : {
265 1 : auto &specified_type = self_param.get_type ();
266 1 : self_type = TypeCheckType::Resolve (specified_type);
267 : }
268 : else
269 : {
270 5810 : switch (self_param.get_self_kind ())
271 : {
272 2542 : case HIR::SelfParam::IMM:
273 2542 : case HIR::SelfParam::MUT:
274 2542 : self_type = self->clone ();
275 2542 : break;
276 :
277 3102 : case HIR::SelfParam::IMM_REF:
278 3102 : {
279 3102 : tl::optional<TyTy::Region> region;
280 3102 : if (self_param.has_lifetime ())
281 : {
282 5684 : region = context->lookup_and_resolve_lifetime (
283 2842 : self_param.get_lifetime ());
284 2842 : if (!region.has_value ())
285 : {
286 1 : rust_inform (self_param.get_locus (),
287 : "failed to resolve lifetime");
288 1 : return;
289 : }
290 : }
291 : else
292 : {
293 260 : region = TyTy::Region::make_anonymous ();
294 : }
295 6202 : self_type = new TyTy::ReferenceType (
296 6202 : self_param.get_mappings ().get_hirid (),
297 3101 : TyTy::TyVar (self->get_ref ()), Mutability::Imm,
298 6202 : region.value ());
299 : }
300 3101 : break;
301 :
302 166 : case HIR::SelfParam::MUT_REF:
303 166 : {
304 166 : tl::optional<TyTy::Region> region;
305 166 : if (self_param.has_lifetime ())
306 : {
307 332 : region = context->lookup_and_resolve_lifetime (
308 166 : self_param.get_lifetime ());
309 166 : if (!region.has_value ())
310 : {
311 0 : rust_error_at (self_param.get_locus (),
312 : "failed to resolve lifetime");
313 0 : return;
314 : }
315 : }
316 : else
317 : {
318 0 : region = TyTy::Region::make_anonymous ();
319 : }
320 332 : self_type = new TyTy::ReferenceType (
321 332 : self_param.get_mappings ().get_hirid (),
322 166 : TyTy::TyVar (self->get_ref ()), Mutability::Mut,
323 332 : region.value ());
324 : }
325 166 : break;
326 :
327 0 : default:
328 0 : rust_unreachable ();
329 : return;
330 : }
331 : }
332 :
333 5810 : context->insert_type (self_param.get_mappings (), self_type);
334 5810 : params.emplace_back (std::move (self_pattern), self_type);
335 5811 : }
336 :
337 11329 : for (auto ¶m : function.get_function_params ())
338 : {
339 : // get the name as well required for later on
340 4401 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
341 :
342 4401 : context->insert_type (param.get_mappings (), param_tyty);
343 4401 : TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
344 :
345 4401 : params.emplace_back (param.get_param_name ().clone_pattern (),
346 : param_tyty);
347 : }
348 :
349 6928 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
350 :
351 6928 : CanonicalPath canonical_path
352 6928 : = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid (),
353 6928 : Resolver2_0::Namespace::Types);
354 :
355 13856 : RustIdent ident{canonical_path, function.get_locus ()};
356 6928 : auto fnType = new TyTy::FnType (
357 6928 : function.get_mappings ().get_hirid (),
358 6928 : function.get_mappings ().get_defid (),
359 6928 : function.get_function_name ().as_string (), ident,
360 6928 : function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
361 : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
362 6928 : ABI::RUST, std::move (params), ret_type, std::move (substitutions),
363 13856 : TyTy::SubstitutionArgumentMappings::empty (
364 6928 : context->get_lifetime_resolver ().get_num_bound_regions ()),
365 34640 : region_constraints);
366 :
367 6928 : context->insert_type (function.get_mappings (), fnType);
368 6928 : result = fnType;
369 :
370 : // need to get the return type from this
371 6928 : TyTy::FnType *resolve_fn_type = fnType;
372 6928 : auto expected_ret_tyty = resolve_fn_type->get_return_type ();
373 6928 : context->push_return_type (TypeCheckContextItem (parent, &function),
374 : expected_ret_tyty);
375 :
376 6928 : auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
377 :
378 6928 : location_t fn_return_locus = function.has_function_return_type ()
379 6928 : ? function.get_return_type ().get_locus ()
380 423 : : function.get_locus ();
381 :
382 13856 : coercion_site (function.get_definition ().get_mappings ().get_hirid (),
383 6928 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
384 6928 : TyTy::TyWithLocation (block_expr_ty),
385 6928 : function.get_definition ().get_locus ());
386 :
387 6928 : context->pop_return_type ();
388 13858 : }
389 :
390 : void
391 70 : TypeCheckImplItem::visit (HIR::ConstantItem &constant)
392 : {
393 70 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
394 70 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
395 :
396 140 : TyTy::BaseType *unified = unify_site (
397 70 : constant.get_mappings ().get_hirid (),
398 70 : TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
399 70 : TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
400 : constant.get_locus ());
401 :
402 70 : if (substitutions.empty ())
403 : {
404 41 : context->insert_type (constant.get_mappings (), unified);
405 41 : result = unified;
406 41 : return;
407 : }
408 :
409 : // special case when this is a generic constant
410 29 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
411 : // TODO: Is Values the correct NS?
412 29 : CanonicalPath canonical_path
413 29 : = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid (),
414 29 : Resolver2_0::Namespace::Values);
415 29 : RustIdent ident{canonical_path, constant.get_locus ()};
416 29 : auto fnType = new TyTy::FnType (
417 29 : constant.get_mappings ().get_hirid (),
418 29 : constant.get_mappings ().get_defid (),
419 29 : constant.get_identifier ().as_string (), ident,
420 : TyTy::FnType::FNTYPE_IS_SYN_CONST_FLAG, ABI::RUST, {}, unified,
421 29 : std::move (substitutions),
422 58 : TyTy::SubstitutionArgumentMappings::empty (
423 29 : context->get_lifetime_resolver ().get_num_bound_regions ()),
424 116 : {});
425 :
426 29 : context->insert_type (constant.get_mappings (), fnType);
427 29 : result = fnType;
428 29 : }
429 :
430 : void
431 1183 : TypeCheckImplItem::visit (HIR::TypeAlias &alias)
432 : {
433 1183 : auto binder_pin = context->push_lifetime_binder ();
434 :
435 1183 : if (alias.has_generics ())
436 15 : resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
437 15 : alias.get_generic_params (), substitutions);
438 :
439 1183 : TyTy::BaseType *actual_type
440 1183 : = TypeCheckType::Resolve (alias.get_type_aliased ());
441 :
442 1183 : context->insert_type (alias.get_mappings (), actual_type);
443 1183 : result = actual_type;
444 1183 : TyTy::RegionConstraints region_constraints;
445 1183 : for (auto &where_clause_item : alias.get_where_clause ().get_items ())
446 : {
447 0 : ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
448 : region_constraints);
449 : }
450 1183 : }
451 :
452 6083 : TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
453 : HIR::ImplBlock &parent, TyTy::BaseType *self,
454 : TyTy::TypeBoundPredicate &trait_reference,
455 6083 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
456 6083 : : TypeCheckBase (), trait_reference (trait_reference),
457 6083 : resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
458 6083 : parent (parent), self (self), substitutions (substitutions)
459 : {
460 6083 : rust_assert (is_trait_impl_block ());
461 6083 : }
462 :
463 : TyTy::TypeBoundPredicateItem
464 6083 : TypeCheckImplItemWithTrait::Resolve (
465 : HIR::ImplBlock &parent, HIR::ImplItem &item, TyTy::BaseType *self,
466 : TyTy::TypeBoundPredicate &trait_reference,
467 : std::vector<TyTy::SubstitutionParamMapping> substitutions)
468 : {
469 6083 : TypeCheckImplItemWithTrait resolver (parent, self, trait_reference,
470 6083 : substitutions);
471 6083 : item.accept_vis (resolver);
472 6083 : return resolver.resolved_trait_item;
473 6083 : }
474 :
475 : void
476 31 : TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
477 : {
478 : // normal resolution of the item
479 31 : TyTy::BaseType *lookup
480 31 : = TypeCheckImplItem::Resolve (parent, constant, self, substitutions);
481 :
482 : // map the impl item to the associated trait item
483 31 : const auto tref = trait_reference.get ();
484 31 : const TraitItemReference *raw_trait_item = nullptr;
485 31 : bool found
486 31 : = tref->lookup_trait_item_by_type (constant.get_identifier ().as_string (),
487 : TraitItemReference::TraitItemType::CONST,
488 : &raw_trait_item);
489 :
490 : // unknown trait item - https://doc.rust-lang.org/error_codes/E0323.html
491 31 : if (!found || raw_trait_item->is_error ())
492 : {
493 1 : rich_location r (line_table, constant.get_locus ());
494 1 : r.add_range (trait_reference.get_locus ());
495 1 : rust_error_at (r, ErrorCode::E0323,
496 : "item %qs is an associated const, which does not match "
497 : "its trait %qs",
498 2 : constant.get_identifier ().as_string ().c_str (),
499 1 : trait_reference.get_name ().c_str ());
500 1 : return;
501 1 : }
502 :
503 : // get the item from the predicate
504 30 : resolved_trait_item
505 30 : = trait_reference.lookup_associated_item (raw_trait_item).value ();
506 :
507 : // merge the attributes
508 30 : const HIR::TraitItem *hir_trait_item
509 30 : = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
510 30 : merge_attributes (constant.get_outer_attrs (), *hir_trait_item);
511 :
512 : // check the types are compatible
513 30 : auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
514 30 : if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
515 30 : TyTy::TyWithLocation (lookup), constant.get_locus (),
516 : true /*emit_errors*/))
517 : {
518 0 : rich_location r (line_table, constant.get_locus ());
519 0 : r.add_range (resolved_trait_item.get_locus ());
520 :
521 0 : rust_error_at (r, "constant %qs has an incompatible type for trait %qs",
522 0 : constant.get_identifier ().as_string ().c_str (),
523 0 : trait_reference.get_name ().c_str ());
524 0 : }
525 : }
526 :
527 : void
528 1853 : TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
529 : {
530 1853 : auto binder_pin = context->push_lifetime_binder ();
531 :
532 1853 : if (type.has_generics ())
533 15 : resolve_generic_params (HIR::Item::ItemKind::TypeAlias, type.get_locus (),
534 15 : type.get_generic_params (), substitutions);
535 :
536 : // normal resolution of the item
537 1853 : TyTy::BaseType *lookup
538 1853 : = TypeCheckImplItem::Resolve (parent, type, self, substitutions);
539 :
540 : // map the impl item to the associated trait item
541 1853 : const auto tref = trait_reference.get ();
542 1853 : const TraitItemReference *raw_trait_item = nullptr;
543 1853 : bool found
544 1853 : = tref->lookup_trait_item_by_type (type.get_new_type_name ().as_string (),
545 : TraitItemReference::TraitItemType::TYPE,
546 : &raw_trait_item);
547 :
548 : // unknown trait item
549 1853 : if (!found || raw_trait_item->is_error ())
550 : {
551 0 : rich_location r (line_table, type.get_locus ());
552 0 : r.add_range (trait_reference.get_locus ());
553 0 : rust_error_at (r, "type alias %qs is not a member of trait %qs",
554 0 : type.get_new_type_name ().as_string ().c_str (),
555 0 : trait_reference.get_name ().c_str ());
556 0 : return;
557 0 : }
558 :
559 : // get the item from the predicate
560 1853 : resolved_trait_item
561 1853 : = trait_reference.lookup_associated_item (raw_trait_item).value ();
562 :
563 : // merge the attributes
564 1853 : const HIR::TraitItem *hir_trait_item
565 1853 : = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
566 1853 : merge_attributes (type.get_outer_attrs (), *hir_trait_item);
567 :
568 : // unwrap a ProjectionType that already wraps a concrete
569 1853 : if (auto *p = lookup->try_as<TyTy::ProjectionType> ())
570 1413 : if (!p->is_trait_position () && p->get () != nullptr
571 1413 : && p->get ()->get_kind () != TyTy::TypeKind::PROJECTION)
572 670 : lookup = p->get ();
573 :
574 : // The impl alias is itself a projection so the substitution machinery has a
575 : // handle to bind the impl's generic arguments to the alias body.
576 1853 : auto projection
577 1853 : = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup, tref,
578 1853 : raw_trait_item->get_mappings ().get_defid (),
579 5559 : substitutions, self);
580 :
581 : // check the types are compatible
582 1853 : auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
583 1853 : if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
584 1853 : TyTy::TyWithLocation (projection), type.get_locus (),
585 : true /*emit_errors*/))
586 : {
587 0 : rich_location r (line_table, type.get_locus ());
588 0 : r.add_range (resolved_trait_item.get_locus ());
589 :
590 0 : rust_error_at (r, "type alias %qs has an incompatible type for trait %qs",
591 0 : type.get_new_type_name ().as_string ().c_str (),
592 0 : trait_reference.get_name ().c_str ());
593 0 : }
594 :
595 1853 : context->insert_type (type.get_mappings (), projection);
596 1853 : }
597 :
598 : void
599 4199 : TypeCheckImplItemWithTrait::visit (HIR::Function &function)
600 : {
601 : // normal resolution of the item
602 4199 : TyTy::BaseType *lookup
603 4199 : = TypeCheckImplItem::Resolve (parent, function, self, substitutions);
604 4199 : if (lookup == nullptr)
605 4 : return;
606 :
607 : // map the impl item to the associated trait item
608 4198 : const auto tref = trait_reference.get ();
609 4198 : const TraitItemReference *raw_trait_item = nullptr;
610 4198 : bool found = tref->lookup_trait_item_by_type (
611 4198 : function.get_function_name ().as_string (),
612 : TraitItemReference::TraitItemType::FN, &raw_trait_item);
613 :
614 : // unknown trait item
615 4198 : if (!found || raw_trait_item->is_error ())
616 : {
617 3 : rich_location r (line_table, function.get_locus ());
618 3 : r.add_range (trait_reference.get_locus ());
619 3 : rust_error_at (r, "method %qs is not a member of trait %qs",
620 6 : function.get_function_name ().as_string ().c_str (),
621 3 : trait_reference.get_name ().c_str ());
622 3 : return;
623 3 : }
624 :
625 : // get the item from the predicate
626 4195 : resolved_trait_item
627 4195 : = trait_reference.lookup_associated_item (raw_trait_item).value ();
628 :
629 : // merge the attributes
630 4195 : const HIR::TraitItem *hir_trait_item
631 4195 : = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
632 4195 : merge_attributes (function.get_outer_attrs (), *hir_trait_item);
633 :
634 : // check the types are compatible
635 4195 : auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
636 4195 : if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
637 4195 : TyTy::TyWithLocation (lookup), function.get_locus (),
638 : true /*emit_errors*/))
639 : {
640 5 : rich_location r (line_table, function.get_locus ());
641 5 : r.add_range (resolved_trait_item.get_locus ());
642 :
643 5 : rust_error_at (r, ErrorCode::E0053,
644 : "method %qs has an incompatible type for trait %qs",
645 10 : function.get_function_name ().as_string ().c_str (),
646 5 : trait_reference.get_name ().c_str ());
647 5 : }
648 : }
649 :
650 : void
651 6078 : TypeCheckImplItemWithTrait::merge_attributes (AST::AttrVec &impl_item_attrs,
652 : const HIR::TraitItem &trait_item)
653 : {
654 20310 : for (const auto &attr : trait_item.get_outer_attrs ())
655 : {
656 14232 : impl_item_attrs.push_back (attr);
657 : }
658 6078 : }
659 :
660 : bool
661 6083 : TypeCheckImplItemWithTrait::is_trait_impl_block () const
662 : {
663 6083 : return !trait_reference.is_error ();
664 : }
665 :
666 : } // namespace Resolver
667 : } // namespace Rust
|