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-type.h"
20 : #include "options.h"
21 : #include "optional.h"
22 : #include "rust-hir-map.h"
23 : #include "rust-hir-trait-resolve.h"
24 : #include "rust-hir-type-check-expr.h"
25 : #include "rust-hir-path-probe.h"
26 : #include "rust-hir-type-bounds.h"
27 : #include "rust-immutable-name-resolution-context.h"
28 : #include "rust-mapping-common.h"
29 : #include "rust-substitution-mapper.h"
30 : #include "rust-type-util.h"
31 : #include "rust-system.h"
32 : #include "rust-compile-base.h"
33 :
34 : namespace Rust {
35 : namespace Resolver {
36 :
37 : HIR::GenericArgs
38 0 : TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment &segment)
39 : {
40 0 : TypeCheckResolveGenericArguments resolver (segment.get_locus ());
41 0 : switch (segment.get_type ())
42 : {
43 0 : case HIR::TypePathSegment::SegmentType::GENERIC:
44 0 : resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (segment));
45 0 : break;
46 :
47 : default:
48 : break;
49 : }
50 0 : return resolver.args;
51 0 : }
52 :
53 : void
54 0 : TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
55 : {
56 0 : args = generic.get_generic_args ();
57 0 : }
58 :
59 : TyTy::BaseType *
60 182631 : TypeCheckType::Resolve (HIR::Type &type)
61 : {
62 : // is it already resolved?
63 182631 : auto context = TypeCheckContext::get ();
64 182631 : TyTy::BaseType *resolved = nullptr;
65 182631 : bool already_resolved
66 182631 : = context->lookup_type (type.get_mappings ().get_hirid (), &resolved);
67 182631 : if (already_resolved)
68 122585 : return resolved;
69 :
70 60046 : TypeCheckType resolver (type.get_mappings ().get_hirid ());
71 60046 : type.accept_vis (resolver);
72 60046 : rust_assert (resolver.translated != nullptr);
73 60046 : resolver.context->insert_type (type.get_mappings (), resolver.translated);
74 60046 : return resolver.translated;
75 60046 : }
76 :
77 : void
78 60 : TypeCheckType::visit (HIR::BareFunctionType &fntype)
79 : {
80 60 : auto binder_pin = context->push_lifetime_binder ();
81 61 : for (auto &lifetime_param : fntype.get_for_lifetimes ())
82 : {
83 1 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
84 : }
85 :
86 60 : TyTy::BaseType *return_type;
87 60 : if (fntype.has_return_type ())
88 : {
89 45 : return_type = TypeCheckType::Resolve (fntype.get_return_type ());
90 : }
91 : else
92 : {
93 : // needs a new implicit ID
94 15 : HirId ref = mappings.get_next_hir_id ();
95 15 : return_type = TyTy::TupleType::get_unit_type ();
96 15 : context->insert_implicit_type (ref, return_type);
97 : }
98 :
99 60 : std::vector<TyTy::TyVar> params;
100 60 : params.reserve (fntype.get_function_params ().size ());
101 :
102 104 : for (auto ¶m : fntype.get_function_params ())
103 : {
104 44 : TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ());
105 44 : params.emplace_back (ptype->get_ref ());
106 : }
107 :
108 60 : translated
109 120 : = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (),
110 : std::move (params),
111 60 : TyTy::TyVar (return_type->get_ref ()),
112 60 : fntype.get_function_qualifiers ().get_abi (),
113 240 : fntype.get_function_qualifiers ().get_unsafety ());
114 60 : }
115 :
116 : void
117 386 : TypeCheckType::visit (HIR::TupleType &tuple)
118 : {
119 386 : if (tuple.is_unit_type ())
120 : {
121 76 : translated = TyTy::TupleType::get_unit_type ();
122 76 : return;
123 : }
124 :
125 310 : std::vector<TyTy::TyVar> fields;
126 310 : fields.reserve (tuple.get_elems ().size ());
127 :
128 904 : for (auto &elem : tuple.get_elems ())
129 : {
130 594 : auto field_ty = TypeCheckType::Resolve (*elem);
131 594 : fields.emplace_back (field_ty->get_ref ());
132 : }
133 :
134 620 : translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (),
135 930 : tuple.get_locus (), fields);
136 310 : }
137 :
138 : void
139 46548 : TypeCheckType::visit (HIR::TypePath &path)
140 : {
141 46548 : rust_debug ("{ARTHUR}: Path visited: %s", path.to_string ().c_str ());
142 :
143 : // this can happen so we need to look up the root then resolve the
144 : // remaining segments if possible
145 46548 : bool wasBigSelf = false;
146 46548 : size_t offset = 0;
147 46548 : TyTy::BaseType *root = resolve_root_path (path, &offset, &wasBigSelf);
148 46548 : if (root->get_kind () == TyTy::TypeKind::ERROR)
149 : {
150 8 : rust_debug_loc (path.get_locus (), "failed to resolve type-path type");
151 45578 : return;
152 : }
153 :
154 46540 : TyTy::BaseType *path_type = root->clone ();
155 46540 : path_type->set_ref (path.get_mappings ().get_hirid ());
156 46540 : context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
157 :
158 46540 : bool fully_resolved = offset >= path.get_segments ().size ();
159 46540 : if (fully_resolved)
160 : {
161 45562 : translated = path_type;
162 45562 : rust_debug_loc (path.get_locus (), "root resolved type-path to: [%s]",
163 45562 : translated->debug_str ().c_str ());
164 45562 : return;
165 : }
166 :
167 978 : translated
168 978 : = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
169 978 : offset, path_type, path.get_mappings (),
170 978 : path.get_locus (), wasBigSelf);
171 :
172 978 : rust_debug_loc (path.get_locus (), "resolved type-path to: [%s]",
173 1956 : translated->debug_str ().c_str ());
174 : }
175 :
176 : void
177 242 : TypeCheckType::visit (HIR::QualifiedPathInType &path)
178 : {
179 242 : HIR::QualifiedPathType qual_path_type = path.get_path_type ();
180 242 : TyTy::BaseType *root = TypeCheckType::Resolve (qual_path_type.get_type ());
181 242 : if (root->get_kind () == TyTy::TypeKind::ERROR)
182 : {
183 0 : rust_debug_loc (path.get_locus (), "failed to resolve the root");
184 0 : return;
185 : }
186 :
187 242 : if (!qual_path_type.has_as_clause ())
188 : {
189 1 : translated
190 1 : = resolve_segments (path.get_mappings ().get_hirid (),
191 : path.get_segments (), 0, translated,
192 1 : path.get_mappings (), path.get_locus (), false);
193 :
194 1 : return;
195 : }
196 :
197 : // Resolve the trait now
198 241 : auto &trait_path_ref = qual_path_type.get_trait ();
199 241 : TraitReference *trait_ref = TraitResolver::Resolve (trait_path_ref);
200 241 : if (trait_ref->is_error ())
201 : return;
202 :
203 : // get the predicate for the bound
204 241 : auto specified_bound
205 : = get_predicate_from_bound (qual_path_type.get_trait (),
206 241 : qual_path_type.get_type (),
207 241 : BoundPolarity::RegularBound, true);
208 241 : if (specified_bound.is_error ())
209 : return;
210 :
211 : // inherit the bound
212 482 : root->inherit_bounds ({specified_bound});
213 :
214 : // lookup the associated item from the specified bound
215 241 : HIR::TypePathSegment &item_seg = path.get_associated_segment ();
216 241 : HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment ();
217 241 : tl::optional<TyTy::TypeBoundPredicateItem> item
218 241 : = specified_bound.lookup_associated_item (item_seg_identifier.to_string ());
219 241 : if (!item.has_value ())
220 : {
221 1 : std::string item_seg_ident_name, rich_msg;
222 1 : item_seg_ident_name = qual_path_type.get_trait ().to_string ();
223 2 : rich_msg = "not found in `" + item_seg_ident_name + "`";
224 :
225 1 : rich_location richloc (line_table, item_seg.get_locus ());
226 1 : richloc.add_fixit_replace (rich_msg.c_str ());
227 :
228 2 : rust_error_at (richloc, ErrorCode::E0576,
229 : "cannot find associated type %qs in trait %qs",
230 1 : item_seg_identifier.to_string ().c_str (),
231 : item_seg_ident_name.c_str ());
232 1 : return;
233 1 : }
234 :
235 : // we try to look for the real impl item if possible
236 240 : TyTy::SubstitutionArgumentMappings args
237 240 : = TyTy::SubstitutionArgumentMappings::error ();
238 240 : HIR::ImplItem *impl_item = nullptr;
239 240 : if (root->is_concrete ())
240 : {
241 : // lookup the associated impl trait for this if we can (it might be
242 : // generic)
243 131 : AssociatedImplTrait *associated_impl_trait
244 131 : = lookup_associated_impl_block (specified_bound, root);
245 131 : if (associated_impl_trait != nullptr)
246 : {
247 92 : associated_impl_trait->setup_associated_types (root, specified_bound,
248 : &args);
249 :
250 99 : for (auto &i :
251 99 : associated_impl_trait->get_impl_block ()->get_impl_items ())
252 : {
253 99 : bool found = i->get_impl_item_name ().compare (
254 99 : item_seg_identifier.to_string ())
255 99 : == 0;
256 99 : if (found)
257 : {
258 92 : impl_item = i.get ();
259 92 : break;
260 : }
261 : }
262 : }
263 : }
264 :
265 92 : if (impl_item == nullptr)
266 : {
267 : // this may be valid as there could be a default trait implementation here
268 : // and we dont need to worry if the trait item is actually implemented or
269 : // not because this will have already been validated as part of the trait
270 : // impl block
271 148 : translated = item->get_tyty_for_receiver (root);
272 : }
273 : else
274 : {
275 92 : HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
276 92 : bool ok = query_type (impl_item_id, &translated);
277 92 : if (!ok)
278 : return;
279 :
280 92 : if (!args.is_error ())
281 : {
282 : // apply the args
283 92 : translated = SubstMapperInternal::Resolve (translated, args);
284 : }
285 : }
286 :
287 : // turbo-fish segment path::<ty>
288 240 : if (item_seg.get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
289 : {
290 7 : auto &generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (item_seg);
291 :
292 : // turbo-fish segment path::<ty>
293 7 : if (generic_seg.has_generic_args ())
294 : {
295 7 : if (!translated->has_substitutions_defined ())
296 : {
297 0 : rust_error_at (item_seg.get_locus (),
298 : "substitutions not supported for %s",
299 0 : translated->as_string ().c_str ());
300 0 : translated
301 0 : = new TyTy::ErrorType (path.get_mappings ().get_hirid ());
302 0 : return;
303 : }
304 7 : translated
305 7 : = SubstMapper::Resolve (translated, path.get_locus (),
306 7 : &generic_seg.get_generic_args (),
307 14 : context->regions_from_generic_args (
308 7 : generic_seg.get_generic_args ()));
309 : }
310 : }
311 :
312 : // continue on as a path-in-expression
313 240 : bool fully_resolved = path.get_segments ().empty ();
314 240 : if (fully_resolved)
315 : return;
316 :
317 0 : translated
318 0 : = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
319 0 : 0, translated, path.get_mappings (), path.get_locus (),
320 : false);
321 723 : }
322 :
323 : TyTy::BaseType *
324 46548 : TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
325 : bool *wasBigSelf)
326 : {
327 46548 : TyTy::BaseType *root_tyty = nullptr;
328 46548 : *offset = 0;
329 :
330 91754 : for (size_t i = 0; i < path.get_num_segments (); i++)
331 : {
332 47832 : std::unique_ptr<HIR::TypePathSegment> &seg = path.get_segments ().at (i);
333 :
334 47832 : bool have_more_segments = (path.get_num_segments () - 1 != i);
335 47832 : bool is_root = *offset == 0;
336 47832 : NodeId ast_node_id = seg->get_mappings ().get_nodeid ();
337 :
338 : // then lookup the reference_node_id
339 47832 : NodeId ref_node_id = UNKNOWN_NODEID;
340 :
341 47832 : if (seg->is_lang_item ())
342 49 : ref_node_id = Analysis::Mappings::get ().get_lang_item_node (
343 49 : seg->get_lang_item ());
344 : else
345 : {
346 47783 : auto &nr_ctx
347 47783 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
348 :
349 : // assign the ref_node_id if we've found something
350 47783 : nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) {
351 46806 : ref_node_id = resolved;
352 : });
353 : }
354 :
355 : // ref_node_id is the NodeId that the segments refers to.
356 47832 : if (ref_node_id == UNKNOWN_NODEID)
357 : {
358 977 : if (is_root)
359 : {
360 0 : rust_error_at (seg->get_locus (),
361 : "unknown reference for resolved name: %qs",
362 0 : seg->to_string ().c_str ());
363 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
364 : }
365 977 : else if (root_tyty == nullptr)
366 : {
367 1 : rust_error_at (seg->get_locus (),
368 : "unknown reference for resolved name: %qs",
369 1 : seg->to_string ().c_str ());
370 1 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
371 : }
372 : return root_tyty;
373 : }
374 :
375 46855 : if (seg->is_ident_only () && seg->to_string () == "Self")
376 7909 : *wasBigSelf = true;
377 :
378 : // node back to HIR
379 46855 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
380 46855 : if (!hid.has_value ())
381 : {
382 0 : if (is_root)
383 : {
384 0 : rust_error_at (seg->get_locus (), "789 reverse lookup failure");
385 0 : rust_debug_loc (
386 : seg->get_locus (),
387 : "failure with [%s] mappings [%s] ref_node_id [%u]",
388 0 : seg->to_string ().c_str (),
389 0 : seg->get_mappings ().as_string ().c_str (), ref_node_id);
390 :
391 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
392 : }
393 :
394 : return root_tyty;
395 : }
396 46855 : auto ref = hid.value ();
397 :
398 46855 : auto seg_is_module = mappings.lookup_module (ref).has_value ();
399 46855 : auto seg_is_crate = mappings.is_local_hirid_crate (ref);
400 46855 : if (seg_is_module || seg_is_crate)
401 : {
402 : // A::B::C::this_is_a_module::D::E::F
403 : // ^^^^^^^^^^^^^^^^
404 : // Currently handling this.
405 308 : if (have_more_segments)
406 : {
407 308 : (*offset)++;
408 308 : continue;
409 : }
410 :
411 : // In the case of :
412 : // A::B::C::this_is_a_module
413 : // ^^^^^^^^^^^^^^^^
414 : // This is an error, we are not expecting a module.
415 0 : rust_error_at (seg->get_locus (), "expected value");
416 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
417 : }
418 :
419 46547 : TyTy::BaseType *lookup = nullptr;
420 46547 : if (!query_type (ref, &lookup))
421 : {
422 1 : if (is_root || root_tyty == nullptr)
423 : {
424 1 : rust_error_at (seg->get_locus (),
425 : "failed to resolve type path segment: %qs",
426 1 : seg->to_string ().c_str ());
427 1 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
428 : }
429 :
430 : return root_tyty;
431 : }
432 :
433 : // if we have a previous segment type
434 46546 : if (root_tyty != nullptr)
435 : {
436 : // if this next segment needs substitution we must apply the
437 : // previous type arguments
438 : //
439 : // such as: GenericStruct::<_>::new(123, 456)
440 0 : if (lookup->needs_generic_substitutions ())
441 : {
442 0 : if (!root_tyty->needs_generic_substitutions ())
443 : {
444 0 : auto used_args_in_prev_segment
445 0 : = GetUsedSubstArgs::From (root_tyty);
446 0 : lookup
447 0 : = SubstMapperInternal::Resolve (lookup,
448 : used_args_in_prev_segment);
449 0 : }
450 : }
451 : }
452 :
453 : // turbo-fish segment path::<ty>
454 46546 : if (seg->is_generic_segment ())
455 : {
456 1890 : auto &generic_segment
457 1890 : = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
458 :
459 1890 : auto regions = context->regions_from_generic_args (
460 1890 : generic_segment.get_generic_args ());
461 1890 : lookup = SubstMapper::Resolve (lookup, path.get_locus (),
462 1890 : &generic_segment.get_generic_args (),
463 : regions);
464 1890 : if (lookup->get_kind () == TyTy::TypeKind::ERROR)
465 3 : return new TyTy::ErrorType (seg->get_mappings ().get_hirid ());
466 1890 : }
467 44656 : else if (lookup->needs_generic_substitutions ())
468 : {
469 175 : HIR::GenericArgs empty
470 175 : = HIR::GenericArgs::create_empty (path.get_locus ());
471 175 : lookup
472 175 : = SubstMapper::Resolve (lookup, path.get_locus (), &empty,
473 175 : context->regions_from_generic_args (empty));
474 175 : }
475 :
476 46543 : *offset = *offset + 1;
477 46543 : root_tyty = lookup;
478 :
479 : // this enforces the proper get_segments checks to take place
480 91441 : auto *maybe_adt = root_tyty->try_as<const TyTy::ADTType> ();
481 5587 : if (maybe_adt && maybe_adt->is_enum ())
482 : return root_tyty;
483 : }
484 :
485 : return root_tyty;
486 : }
487 :
488 : bool
489 845 : TypeCheckType::resolve_associated_type (const std::string &search,
490 : TypeCheckBlockContextItem &ctx,
491 : TyTy::BaseType **result)
492 : {
493 845 : if (ctx.is_trait_block ())
494 : {
495 697 : HIR::Trait &trait = ctx.get_trait ();
496 778 : for (auto &item : trait.get_trait_items ())
497 : {
498 760 : if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::TYPE)
499 19 : continue;
500 :
501 741 : if (item->trait_identifier () == search)
502 : {
503 679 : HirId item_id = item->get_mappings ().get_hirid ();
504 679 : if (query_type (item_id, result))
505 813 : return true;
506 : }
507 : }
508 :
509 : // FIXME
510 : // query any parent trait?
511 :
512 : return false;
513 : }
514 :
515 : // look for any segment in here which matches
516 148 : HIR::ImplBlock &block = ctx.get_impl_block ();
517 169 : for (auto &item : block.get_impl_items ())
518 : {
519 155 : if (item->get_impl_item_type () != HIR::ImplItem::TYPE_ALIAS)
520 14 : continue;
521 :
522 141 : if (item->get_impl_item_name () == search)
523 : {
524 134 : HirId item_id = item->get_impl_mappings ().get_hirid ();
525 134 : if (query_type (item_id, result))
526 813 : return true;
527 : }
528 : }
529 :
530 : return false;
531 : }
532 :
533 : TyTy::BaseType *
534 979 : TypeCheckType::resolve_segments (
535 : HirId expr_id, std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments,
536 : size_t offset, TyTy::BaseType *tyseg,
537 : const Analysis::NodeMapping &expr_mappings, location_t expr_locus,
538 : bool tySegIsBigSelf)
539 : {
540 979 : TyTy::BaseType *prev_segment = tyseg;
541 1954 : for (size_t i = offset; i < segments.size (); i++)
542 : {
543 978 : std::unique_ptr<HIR::TypePathSegment> &seg = segments.at (i);
544 :
545 978 : bool reciever_is_generic
546 978 : = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
547 978 : bool probe_bounds = true;
548 978 : bool probe_impls = !reciever_is_generic;
549 978 : bool ignore_mandatory_trait_items = !reciever_is_generic;
550 978 : bool first_segment = i == offset;
551 978 : bool selfResolveOk = false;
552 :
553 978 : if (first_segment && tySegIsBigSelf
554 978 : && context->block_context ().is_in_context ())
555 : {
556 845 : TypeCheckBlockContextItem ctx = context->block_context ().peek ();
557 845 : TyTy::BaseType *lookup = nullptr;
558 845 : selfResolveOk
559 845 : = resolve_associated_type (seg->to_string (), ctx, &lookup);
560 845 : if (selfResolveOk)
561 : {
562 813 : prev_segment = tyseg;
563 813 : tyseg = lookup;
564 : }
565 : }
566 845 : if (!selfResolveOk)
567 : {
568 : // probe the path is done in two parts one where we search impls if no
569 : // candidate is found then we search extensions from traits
570 165 : auto candidates
571 : = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
572 : probe_impls, false,
573 165 : ignore_mandatory_trait_items);
574 165 : if (candidates.size () == 0)
575 : {
576 149 : candidates
577 149 : = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
578 : false, probe_bounds,
579 149 : ignore_mandatory_trait_items);
580 149 : if (candidates.size () == 0)
581 : {
582 1 : prev_segment->debug ();
583 1 : rust_error_at (
584 : seg->get_locus (),
585 : "failed to resolve path segment using an impl Probe");
586 1 : return new TyTy::ErrorType (expr_id);
587 : }
588 : }
589 :
590 164 : if (candidates.size () > 1)
591 : {
592 0 : ReportMultipleCandidateError::Report (candidates,
593 : seg->get_ident_segment (),
594 : seg->get_locus ());
595 0 : return new TyTy::ErrorType (expr_id);
596 : }
597 :
598 164 : auto &candidate = *candidates.begin ();
599 164 : prev_segment = tyseg;
600 164 : tyseg = candidate.ty;
601 :
602 164 : if (candidate.is_enum_candidate ())
603 : {
604 2 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
605 2 : auto last_variant = adt->get_variants ();
606 2 : TyTy::VariantDef *variant = last_variant.back ();
607 :
608 2 : rich_location richloc (line_table, seg->get_locus ());
609 2 : richloc.add_fixit_replace ("not a type");
610 :
611 2 : rust_error_at (richloc, ErrorCode::E0573,
612 : "expected type, found variant of %<%s::%s%>",
613 4 : adt->get_name ().c_str (),
614 2 : variant->get_identifier ().c_str ());
615 2 : return new TyTy::ErrorType (expr_id);
616 2 : }
617 165 : }
618 :
619 975 : if (seg->is_generic_segment ())
620 : {
621 0 : auto &generic_segment
622 0 : = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
623 :
624 0 : std::vector<TyTy::Region> regions;
625 0 : for (auto &lifetime :
626 0 : generic_segment.get_generic_args ().get_lifetime_args ())
627 : {
628 0 : auto region = context->lookup_and_resolve_lifetime (lifetime);
629 0 : if (!region.has_value ())
630 : {
631 0 : rust_error_at (lifetime.get_locus (),
632 : "failed to resolve lifetime");
633 0 : return new TyTy::ErrorType (expr_id);
634 : }
635 0 : regions.push_back (region.value ());
636 : }
637 :
638 0 : tyseg = SubstMapper::Resolve (tyseg, expr_locus,
639 0 : &generic_segment.get_generic_args (),
640 : regions);
641 0 : if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
642 0 : return new TyTy::ErrorType (expr_id);
643 0 : }
644 : }
645 :
646 : return tyseg;
647 : }
648 :
649 : void
650 166 : TypeCheckType::visit (HIR::TraitObjectType &type)
651 : {
652 166 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
653 344 : for (auto &bound : type.get_type_param_bounds ())
654 : {
655 : // TODO: here we need to check if there are additional bounds that aren't
656 : // auto traits. this is an error. for example, `dyn A + Sized + Sync` is
657 : // okay, because Sized and Sync are both auto traits but `dyn A + Copy +
658 : // Clone` is not okay and should error out.
659 :
660 178 : if (bound->get_bound_type ()
661 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
662 7 : continue;
663 :
664 171 : HIR::TypeParamBound &b = *bound.get ();
665 171 : HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
666 :
667 171 : auto binder_pin = context->push_lifetime_binder ();
668 178 : for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
669 : {
670 7 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
671 : }
672 :
673 171 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
674 : trait_bound.get_path (),
675 171 : tl::nullopt /*this will setup a PLACEHOLDER for self*/);
676 :
677 171 : if (!predicate.is_error ()
678 171 : && predicate.is_object_safe (true, type.get_locus ()))
679 169 : specified_bounds.push_back (std::move (predicate));
680 171 : }
681 :
682 166 : RustIdent ident{CanonicalPath::create_empty (), type.get_locus ()};
683 166 : translated
684 166 : = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), ident,
685 332 : std::move (specified_bounds));
686 166 : }
687 :
688 : void
689 5 : TypeCheckType::visit (HIR::ParenthesisedType &type)
690 : {
691 : // I think this really needs to be a tuple.. but will sort that out when we
692 : // fix the parser issue
693 5 : translated = TypeCheckType::Resolve (type.get_type_in_parens ());
694 5 : }
695 :
696 : void
697 663 : TypeCheckType::visit (HIR::ArrayType &type)
698 : {
699 663 : auto element_type = TypeCheckType::Resolve (type.get_element_type ());
700 663 : auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
701 663 : if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
702 0 : return;
703 :
704 663 : TyTy::BaseType *expected_ty = nullptr;
705 663 : bool ok = context->lookup_builtin ("usize", &expected_ty);
706 663 : rust_assert (ok);
707 :
708 663 : TyTy::BaseConstType *const_type = nullptr;
709 663 : if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
710 : {
711 36 : const_type = capacity_type->as_const_type ();
712 :
713 72 : unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
714 36 : TyTy::TyWithLocation (expected_ty),
715 : TyTy::TyWithLocation (const_type->get_specified_type (),
716 36 : type.get_size_expr ().get_locus ()),
717 36 : type.get_size_expr ().get_locus ());
718 : }
719 : else
720 : {
721 627 : HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
722 627 : TyTy::BaseType *result
723 1254 : = unify_site (size_id, TyTy::TyWithLocation (expected_ty),
724 : TyTy::TyWithLocation (capacity_type,
725 627 : type.get_size_expr ().get_locus ()),
726 627 : type.get_size_expr ().get_locus ());
727 :
728 627 : if (result->is<TyTy::ErrorType> ())
729 1 : const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id);
730 : else
731 : {
732 626 : auto ctx = Compile::Context::get ();
733 626 : tree capacity_expr
734 626 : = Compile::HIRCompileBase::query_compile_const_expr (
735 : ctx, capacity_type, type.get_size_expr ());
736 :
737 626 : const_type = new TyTy::ConstValueType (capacity_expr, expected_ty,
738 626 : size_id, size_id);
739 626 : context->insert_type (type.get_size_expr ().get_mappings (),
740 626 : const_type->as_base_type ());
741 : }
742 : }
743 :
744 663 : translated
745 663 : = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
746 : TyTy::TyVar (
747 663 : const_type->as_base_type ()->get_ref ()),
748 1989 : TyTy::TyVar (element_type->get_ref ()));
749 : }
750 :
751 : void
752 841 : TypeCheckType::visit (HIR::SliceType &type)
753 : {
754 841 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
755 841 : translated
756 841 : = new TyTy::SliceType (type.get_mappings ().get_hirid (), type.get_locus (),
757 1682 : TyTy::TyVar (base->get_ref ()));
758 841 : }
759 : void
760 4367 : TypeCheckType::visit (HIR::ReferenceType &type)
761 : {
762 4367 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
763 4367 : rust_assert (type.has_lifetime ());
764 4367 : auto region = context->lookup_and_resolve_lifetime (type.get_lifetime ());
765 4367 : if (!region.has_value ())
766 : {
767 2 : rust_error_at (type.get_locus (), "failed to resolve lifetime");
768 2 : translated = new TyTy::ErrorType (type.get_mappings ().get_hirid ());
769 2 : return;
770 : }
771 13095 : translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (),
772 4365 : TyTy::TyVar (base->get_ref ()),
773 8730 : type.get_mut (), region.value ());
774 : }
775 :
776 : void
777 6487 : TypeCheckType::visit (HIR::RawPointerType &type)
778 : {
779 6487 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
780 6487 : translated
781 12974 : = new TyTy::PointerType (type.get_mappings ().get_hirid (),
782 6487 : TyTy::TyVar (base->get_ref ()), type.get_mut ());
783 6487 : }
784 :
785 : void
786 206 : TypeCheckType::visit (HIR::InferredType &type)
787 : {
788 412 : translated = new TyTy::InferType (type.get_mappings ().get_hirid (),
789 : TyTy::InferType::InferTypeKind::GENERAL,
790 : TyTy::InferType::TypeHint::Default (),
791 412 : type.get_locus ());
792 206 : }
793 :
794 : void
795 46 : TypeCheckType::visit (HIR::NeverType &type)
796 : {
797 46 : TyTy::BaseType *lookup = nullptr;
798 46 : bool ok = context->lookup_builtin ("!", &lookup);
799 46 : rust_assert (ok);
800 :
801 46 : translated = lookup->clone ();
802 46 : }
803 :
804 : void
805 29 : TypeCheckType::visit (HIR::ImplTraitType &type)
806 : {
807 29 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
808 58 : for (auto &bound : type.get_type_param_bounds ())
809 : {
810 29 : if (bound->get_bound_type ()
811 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
812 0 : continue;
813 :
814 29 : HIR::TypeParamBound &b = *bound.get ();
815 29 : HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
816 :
817 29 : auto binder_pin = context->push_lifetime_binder ();
818 29 : for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
819 : {
820 0 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
821 : }
822 :
823 29 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
824 : trait_bound.get_path (),
825 29 : tl::nullopt /*this will setup a PLACEHOLDER for self*/);
826 :
827 29 : if (!predicate.is_error ()
828 29 : && predicate.is_object_safe (true, type.get_locus ()))
829 29 : specified_bounds.push_back (std::move (predicate));
830 29 : }
831 :
832 87 : translated = new TyTy::OpaqueType (type.get_locus (),
833 29 : type.get_mappings ().get_hirid (),
834 29 : specified_bounds);
835 29 : }
836 :
837 : TyTy::ParamType *
838 12899 : TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m,
839 : bool resolve_trait_bounds, bool apply_sized)
840 : {
841 12899 : TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
842 12899 : switch (param.get_kind ())
843 : {
844 12899 : case HIR::GenericParam::GenericKind::TYPE:
845 12899 : resolver.visit (static_cast<HIR::TypeParam &> (param));
846 12899 : break;
847 :
848 0 : case HIR::GenericParam::GenericKind::CONST:
849 0 : resolver.visit (static_cast<HIR::ConstGenericParam &> (param));
850 0 : break;
851 :
852 0 : case HIR::GenericParam::GenericKind::LIFETIME:
853 0 : resolver.visit (static_cast<HIR::LifetimeParam &> (param));
854 0 : break;
855 : }
856 12899 : return resolver.resolved;
857 12899 : }
858 :
859 : void
860 8657 : TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam ¶m,
861 : TyTy::ParamType *pty)
862 : {
863 8657 : TypeResolveGenericParam resolver (true, true);
864 8657 : resolver.apply_trait_bounds (param, pty);
865 8656 : }
866 :
867 : void
868 0 : TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m)
869 : {
870 : // nothing to do
871 0 : }
872 :
873 : void
874 0 : TypeResolveGenericParam::visit (HIR::ConstGenericParam ¶m)
875 : {
876 : // TODO
877 0 : }
878 :
879 : void
880 12899 : TypeResolveGenericParam::visit (HIR::TypeParam ¶m)
881 : {
882 12899 : if (param.has_type ())
883 358 : TypeCheckType::Resolve (param.get_type ());
884 :
885 25798 : resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
886 : param.get_locus (),
887 38697 : param.get_mappings ().get_hirid (), {});
888 :
889 12899 : if (resolve_trait_bounds)
890 4329 : apply_trait_bounds (param, resolved);
891 12899 : }
892 :
893 : void
894 12986 : TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m,
895 : TyTy::ParamType *pty)
896 : {
897 12986 : std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
898 12986 : if (param.has_type_param_bounds ())
899 : {
900 : // We need two possible parameter types. One with no Bounds and one with
901 : // the bounds. the Self type for the bounds cannot itself contain the
902 : // bounds otherwise it will be a trait cycle
903 1263 : HirId implicit_id = mappings.get_next_hir_id ();
904 1263 : TyTy::ParamType *p
905 1263 : = new TyTy::ParamType (param.get_type_representation ().as_string (),
906 : param.get_locus (), implicit_id,
907 2526 : {} /*empty specified bounds*/);
908 1263 : context->insert_implicit_type (implicit_id, p);
909 :
910 : // generate an implicit HIR Type we can apply to the predicate
911 1263 : Analysis::NodeMapping mappings (param.get_mappings ().get_crate_num (),
912 1263 : param.get_mappings ().get_nodeid (),
913 : implicit_id,
914 1263 : param.get_mappings ().get_local_defid ());
915 2526 : implicit_self_bound = std::make_unique<HIR::TypePath> (
916 3789 : HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false));
917 : }
918 :
919 12986 : std::map<DefId, std::vector<TyTy::TypeBoundPredicate>> predicates;
920 :
921 : // https://doc.rust-lang.org/std/marker/trait.Sized.html
922 : // All type parameters have an implicit bound of Sized. The special syntax
923 : // ?Sized can be used to remove this bound if it’s not appropriate.
924 : //
925 : // We can only do this when we are not resolving the implicit Self for Sized
926 : // itself
927 12986 : if (apply_sized)
928 : {
929 9298 : TyTy::TypeBoundPredicate sized_predicate
930 9298 : = get_marker_predicate (LangItem::Kind::SIZED, param.get_locus ());
931 :
932 18594 : predicates[sized_predicate.get_id ()] = {sized_predicate};
933 9297 : }
934 :
935 : // resolve the bounds
936 12985 : if (param.has_type_param_bounds ())
937 : {
938 2587 : for (auto &bound : param.get_type_param_bounds ())
939 : {
940 1324 : switch (bound->get_bound_type ())
941 : {
942 1324 : case HIR::TypeParamBound::BoundType::TRAITBOUND:
943 1324 : {
944 1324 : HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound);
945 :
946 1324 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
947 : b.get_path (),
948 : tl::optional<std::reference_wrapper<HIR::Type>> (
949 1324 : std::ref (*implicit_self_bound)),
950 1324 : b.get_polarity ());
951 1324 : if (!predicate.is_error ())
952 : {
953 1323 : switch (predicate.get_polarity ())
954 : {
955 385 : case BoundPolarity::AntiBound:
956 385 : {
957 385 : bool found = predicates.find (predicate.get_id ())
958 385 : != predicates.end ();
959 385 : if (found)
960 385 : predicates.erase (predicate.get_id ());
961 : else
962 : {
963 : // emit error message
964 0 : rich_location r (line_table, b.get_locus ());
965 0 : r.add_range (predicate.get ()->get_locus ());
966 0 : rust_error_at (
967 : r, "antibound for %s is not applied here",
968 0 : predicate.get ()->get_name ().c_str ());
969 0 : }
970 : }
971 : break;
972 :
973 938 : default:
974 938 : {
975 938 : if (predicates.find (predicate.get_id ())
976 938 : == predicates.end ())
977 : {
978 929 : predicates[predicate.get_id ()] = {};
979 : }
980 938 : predicates[predicate.get_id ()].push_back (predicate);
981 : }
982 938 : break;
983 : }
984 : }
985 1324 : }
986 1324 : break;
987 :
988 : default:
989 : break;
990 : }
991 : }
992 : }
993 :
994 : // now to flat map the specified_bounds into the raw specified predicates
995 25970 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
996 22826 : for (auto it = predicates.begin (); it != predicates.end (); it++)
997 : {
998 19691 : for (const auto &predicate : it->second)
999 : {
1000 9850 : specified_bounds.push_back (predicate);
1001 : }
1002 : }
1003 :
1004 : // inherit them
1005 12985 : pty->inherit_bounds (specified_bounds);
1006 12985 : }
1007 :
1008 : void
1009 565 : ResolveWhereClauseItem::Resolve (HIR::WhereClauseItem &item,
1010 : TyTy::RegionConstraints ®ion_constraints)
1011 : {
1012 565 : ResolveWhereClauseItem resolver (region_constraints);
1013 :
1014 565 : auto binder_pin = resolver.context->push_lifetime_binder ();
1015 :
1016 565 : switch (item.get_item_type ())
1017 : {
1018 2 : case HIR::WhereClauseItem::LIFETIME:
1019 2 : resolver.visit (static_cast<HIR::LifetimeWhereClauseItem &> (item));
1020 2 : break;
1021 :
1022 563 : case HIR::WhereClauseItem::TYPE_BOUND:
1023 563 : resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (item));
1024 563 : break;
1025 : }
1026 565 : }
1027 :
1028 : void
1029 2 : ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &item)
1030 : {
1031 2 : auto lhs = context->lookup_and_resolve_lifetime (item.get_lifetime ());
1032 2 : if (!lhs.has_value ())
1033 : {
1034 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
1035 : }
1036 4 : for (auto &lifetime : item.get_lifetime_bounds ())
1037 : {
1038 2 : auto rhs_i = context->lookup_and_resolve_lifetime (lifetime);
1039 2 : if (!rhs_i.has_value ())
1040 : {
1041 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
1042 : }
1043 2 : region_constraints.region_region.emplace_back (lhs.value (),
1044 : rhs_i.value ());
1045 : }
1046 2 : }
1047 :
1048 : void
1049 563 : ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
1050 : {
1051 563 : auto binder_pin = context->push_lifetime_binder ();
1052 563 : if (item.has_for_lifetimes ())
1053 : {
1054 14 : for (auto &lifetime_param : item.get_for_lifetimes ())
1055 : {
1056 7 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
1057 : }
1058 : }
1059 :
1060 563 : auto &binding_type_path = item.get_bound_type ();
1061 563 : TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path);
1062 :
1063 : // FIXME double check there might be a trait cycle here see TypeParam handling
1064 :
1065 563 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
1066 1126 : for (auto &bound : item.get_type_param_bounds ())
1067 : {
1068 563 : switch (bound->get_bound_type ())
1069 : {
1070 559 : case HIR::TypeParamBound::BoundType::TRAITBOUND:
1071 559 : {
1072 559 : auto *b = static_cast<HIR::TraitBound *> (bound.get ());
1073 :
1074 559 : TyTy::TypeBoundPredicate predicate
1075 559 : = get_predicate_from_bound (b->get_path (), binding_type_path);
1076 559 : if (!predicate.is_error ())
1077 559 : specified_bounds.push_back (std::move (predicate));
1078 559 : }
1079 559 : break;
1080 4 : case HIR::TypeParamBound::BoundType::LIFETIME:
1081 4 : {
1082 8 : if (auto param = binding->try_as<TyTy::ParamType> ())
1083 : {
1084 4 : auto *b = static_cast<HIR::Lifetime *> (bound.get ());
1085 4 : auto region = context->lookup_and_resolve_lifetime (*b);
1086 4 : if (!region.has_value ())
1087 : {
1088 0 : rust_error_at (UNKNOWN_LOCATION,
1089 : "failed to resolve lifetime");
1090 : }
1091 4 : region_constraints.type_region.emplace_back (param,
1092 : region.value ());
1093 : }
1094 : }
1095 4 : break;
1096 :
1097 : default:
1098 : break;
1099 : }
1100 : }
1101 563 : binding->inherit_bounds (specified_bounds);
1102 :
1103 : // When we apply these bounds we must lookup which type this binding
1104 : // resolves to, as this is the type which will be used during resolution
1105 : // of the block.
1106 563 : NodeId ast_node_id = binding_type_path.get_mappings ().get_nodeid ();
1107 :
1108 : // then lookup the reference_node_id
1109 563 : NodeId ref_node_id = UNKNOWN_NODEID;
1110 :
1111 563 : auto &nr_ctx
1112 563 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
1113 :
1114 563 : if (auto id = nr_ctx.lookup (ast_node_id))
1115 : {
1116 563 : ref_node_id = *id;
1117 : }
1118 : else
1119 : {
1120 : // FIXME
1121 0 : rust_error_at (UNDEF_LOCATION,
1122 : "Failed to lookup type reference for node: %s",
1123 0 : binding_type_path.to_string ().c_str ());
1124 0 : return;
1125 : }
1126 :
1127 : // node back to HIR
1128 563 : if (auto hid = mappings.lookup_node_to_hir (ref_node_id))
1129 : {
1130 : // the base reference for this name _must_ have a type set
1131 563 : TyTy::BaseType *lookup;
1132 563 : if (!context->lookup_type (*hid, &lookup))
1133 : {
1134 0 : rust_error_at (mappings.lookup_location (*hid),
1135 : "Failed to resolve where-clause binding type: %s",
1136 0 : binding_type_path.to_string ().c_str ());
1137 0 : return;
1138 : }
1139 :
1140 : // FIXME
1141 : // rust_assert (binding->is_equal (*lookup));
1142 563 : lookup->inherit_bounds (specified_bounds);
1143 563 : return;
1144 : }
1145 0 : rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure");
1146 563 : }
1147 :
1148 : } // namespace Resolver
1149 : } // namespace Rust
|