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