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