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