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