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