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