Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-hir-type-check-type.h"
20 : : #include "rust-hir-trait-resolve.h"
21 : : #include "rust-hir-type-check-expr.h"
22 : : #include "rust-hir-path-probe.h"
23 : : #include "rust-hir-type-bounds.h"
24 : : #include "rust-substitution-mapper.h"
25 : : #include "rust-type-util.h"
26 : :
27 : : namespace Rust {
28 : : namespace Resolver {
29 : :
30 : : HIR::GenericArgs
31 : 0 : TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment *segment)
32 : : {
33 : 0 : TypeCheckResolveGenericArguments resolver (segment->get_locus ());
34 : 0 : switch (segment->get_type ())
35 : : {
36 : 0 : case HIR::TypePathSegment::SegmentType::GENERIC:
37 : 0 : resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (*segment));
38 : 0 : break;
39 : :
40 : : default:
41 : : break;
42 : : }
43 : 0 : return resolver.args;
44 : 0 : }
45 : :
46 : : void
47 : 0 : TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
48 : : {
49 : 0 : args = generic.get_generic_args ();
50 : 0 : }
51 : :
52 : : TyTy::BaseType *
53 : 64982 : TypeCheckType::Resolve (HIR::Type *type)
54 : : {
55 : : // is it already resolved?
56 : 64982 : auto context = TypeCheckContext::get ();
57 : 64982 : TyTy::BaseType *resolved = nullptr;
58 : 64982 : bool already_resolved
59 : 64982 : = context->lookup_type (type->get_mappings ().get_hirid (), &resolved);
60 : 64982 : if (already_resolved)
61 : 29653 : return resolved;
62 : :
63 : 35329 : TypeCheckType resolver (type->get_mappings ().get_hirid ());
64 : 35329 : type->accept_vis (resolver);
65 : 35329 : rust_assert (resolver.translated != nullptr);
66 : 35329 : resolver.context->insert_type (type->get_mappings (), resolver.translated);
67 : 35329 : return resolver.translated;
68 : 35329 : }
69 : :
70 : : void
71 : 34 : TypeCheckType::visit (HIR::BareFunctionType &fntype)
72 : : {
73 : 34 : auto binder_pin = context->push_lifetime_binder ();
74 : 34 : for (auto &lifetime_param : fntype.get_for_lifetimes ())
75 : : {
76 : 0 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
77 : : }
78 : :
79 : 34 : TyTy::BaseType *return_type;
80 : 34 : if (fntype.has_return_type ())
81 : : {
82 : 30 : return_type = TypeCheckType::Resolve (fntype.get_return_type ().get ());
83 : : }
84 : : else
85 : : {
86 : : // needs a new implicit ID
87 : 4 : HirId ref = mappings->get_next_hir_id ();
88 : 4 : return_type = TyTy::TupleType::get_unit_type (ref);
89 : 4 : context->insert_implicit_type (ref, return_type);
90 : : }
91 : :
92 : 34 : std::vector<TyTy::TyVar> params;
93 : 65 : for (auto ¶m : fntype.get_function_params ())
94 : : {
95 : 31 : TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ().get ());
96 : 31 : params.push_back (TyTy::TyVar (ptype->get_ref ()));
97 : : }
98 : :
99 : 34 : translated = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (),
100 : 34 : fntype.get_locus (), std::move (params),
101 : 68 : TyTy::TyVar (return_type->get_ref ()));
102 : 34 : }
103 : :
104 : : void
105 : 245 : TypeCheckType::visit (HIR::TupleType &tuple)
106 : : {
107 : 245 : if (tuple.is_unit_type ())
108 : : {
109 : 53 : auto unit_node_id = resolver->get_unit_type_node_id ();
110 : 53 : if (!context->lookup_builtin (unit_node_id, &translated))
111 : : {
112 : 0 : rust_error_at (tuple.get_locus (),
113 : : "failed to lookup builtin unit type");
114 : : }
115 : 53 : return;
116 : : }
117 : :
118 : 192 : std::vector<TyTy::TyVar> fields;
119 : 559 : for (auto &elem : tuple.get_elems ())
120 : : {
121 : 367 : auto field_ty = TypeCheckType::Resolve (elem.get ());
122 : 367 : fields.push_back (TyTy::TyVar (field_ty->get_ref ()));
123 : : }
124 : :
125 : 192 : translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (),
126 : 384 : tuple.get_locus (), fields);
127 : 192 : }
128 : :
129 : : void
130 : 27005 : TypeCheckType::visit (HIR::TypePath &path)
131 : : {
132 : : // this can happen so we need to look up the root then resolve the
133 : : // remaining segments if possible
134 : 27005 : size_t offset = 0;
135 : 27005 : NodeId resolved_node_id = UNKNOWN_NODEID;
136 : 27005 : TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id);
137 : 27005 : if (root->get_kind () == TyTy::TypeKind::ERROR)
138 : 26232 : return;
139 : :
140 : 27002 : TyTy::BaseType *path_type = root->clone ();
141 : 27002 : path_type->set_ref (path.get_mappings ().get_hirid ());
142 : 27002 : context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
143 : :
144 : 27002 : bool fully_resolved = offset >= path.get_segments ().size ();
145 : 27002 : if (fully_resolved)
146 : : {
147 : 26229 : translated = path_type;
148 : 26229 : return;
149 : : }
150 : :
151 : 773 : translated
152 : 773 : = resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
153 : : path.get_segments (), offset, path_type,
154 : 1546 : path.get_mappings (), path.get_locus ());
155 : : }
156 : :
157 : : void
158 : 159 : TypeCheckType::visit (HIR::QualifiedPathInType &path)
159 : : {
160 : 159 : HIR::QualifiedPathType qual_path_type = path.get_path_type ();
161 : 159 : TyTy::BaseType *root
162 : 159 : = TypeCheckType::Resolve (qual_path_type.get_type ().get ());
163 : 159 : if (root->get_kind () == TyTy::TypeKind::ERROR)
164 : : {
165 : 0 : rust_debug_loc (path.get_locus (), "failed to resolve the root");
166 : 0 : return;
167 : : }
168 : :
169 : 159 : if (!qual_path_type.has_as_clause ())
170 : : {
171 : : // then this is just a normal path-in-expression
172 : 0 : NodeId root_resolved_node_id = UNKNOWN_NODEID;
173 : 0 : bool ok = resolver->lookup_resolved_type (
174 : 0 : qual_path_type.get_type ()->get_mappings ().get_nodeid (),
175 : : &root_resolved_node_id);
176 : 0 : rust_assert (ok);
177 : :
178 : 0 : translated = resolve_segments (root_resolved_node_id,
179 : 0 : path.get_mappings ().get_hirid (),
180 : : path.get_segments (), 0, translated,
181 : 0 : path.get_mappings (), path.get_locus ());
182 : :
183 : 0 : return;
184 : : }
185 : :
186 : : // Resolve the trait now
187 : 159 : std::unique_ptr<HIR::TypePath> &trait_path_ref = qual_path_type.get_trait ();
188 : 159 : TraitReference *trait_ref = TraitResolver::Resolve (*trait_path_ref.get ());
189 : 159 : if (trait_ref->is_error ())
190 : : return;
191 : :
192 : : // does this type actually implement this type-bound?
193 : 159 : if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
194 : : {
195 : 0 : rust_error_at (qual_path_type.get_locus (),
196 : : "root does not satisfy specified trait-bound");
197 : 0 : return;
198 : : }
199 : :
200 : : // get the predicate for the bound
201 : 159 : auto specified_bound
202 : 159 : = get_predicate_from_bound (*qual_path_type.get_trait ().get (),
203 : 159 : qual_path_type.get_type ().get ());
204 : 159 : if (specified_bound.is_error ())
205 : : return;
206 : :
207 : : // inherit the bound
208 : 318 : root->inherit_bounds ({specified_bound});
209 : :
210 : : // lookup the associated item from the specified bound
211 : 159 : std::unique_ptr<HIR::TypePathSegment> &item_seg
212 : 159 : = path.get_associated_segment ();
213 : 159 : HIR::PathIdentSegment item_seg_identifier = item_seg->get_ident_segment ();
214 : 159 : TyTy::TypeBoundPredicateItem item
215 : 159 : = specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
216 : 159 : if (item.is_error ())
217 : : {
218 : 0 : rust_error_at (item_seg->get_locus (), "unknown associated item");
219 : 0 : return;
220 : : }
221 : :
222 : : // we try to look for the real impl item if possible
223 : 159 : TyTy::SubstitutionArgumentMappings args
224 : 159 : = TyTy::SubstitutionArgumentMappings::error ();
225 : 159 : HIR::ImplItem *impl_item = nullptr;
226 : 159 : if (root->is_concrete ())
227 : : {
228 : : // lookup the associated impl trait for this if we can (it might be
229 : : // generic)
230 : 124 : AssociatedImplTrait *associated_impl_trait
231 : 124 : = lookup_associated_impl_block (specified_bound, root);
232 : 124 : if (associated_impl_trait != nullptr)
233 : : {
234 : 85 : associated_impl_trait->setup_associated_types (root, specified_bound,
235 : : &args);
236 : :
237 : 92 : for (auto &i :
238 : 92 : associated_impl_trait->get_impl_block ()->get_impl_items ())
239 : : {
240 : 92 : bool found = i->get_impl_item_name ().compare (
241 : 92 : item_seg_identifier.as_string ())
242 : 92 : == 0;
243 : 92 : if (found)
244 : : {
245 : 85 : impl_item = i.get ();
246 : 85 : break;
247 : : }
248 : : }
249 : : }
250 : : }
251 : :
252 : 159 : NodeId root_resolved_node_id = UNKNOWN_NODEID;
253 : 85 : if (impl_item == nullptr)
254 : : {
255 : : // this may be valid as there could be a default trait implementation here
256 : : // and we dont need to worry if the trait item is actually implemented or
257 : : // not because this will have already been validated as part of the trait
258 : : // impl block
259 : 74 : translated = item.get_tyty_for_receiver (root);
260 : 74 : root_resolved_node_id
261 : 74 : = item.get_raw_item ()->get_mappings ().get_nodeid ();
262 : : }
263 : : else
264 : : {
265 : 85 : HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
266 : 85 : bool ok = query_type (impl_item_id, &translated);
267 : 85 : if (!ok)
268 : : {
269 : : // FIXME
270 : : // I think query_type should error if required here anyway
271 : : return;
272 : : }
273 : :
274 : 85 : if (!args.is_error ())
275 : : {
276 : : // apply the args
277 : 85 : translated = SubstMapperInternal::Resolve (translated, args);
278 : : }
279 : :
280 : 85 : root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid ();
281 : : }
282 : :
283 : : // turbo-fish segment path::<ty>
284 : 159 : if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
285 : : {
286 : 0 : HIR::TypePathSegmentGeneric &generic_seg
287 : 0 : = static_cast<HIR::TypePathSegmentGeneric &> (*item_seg.get ());
288 : :
289 : : // turbo-fish segment path::<ty>
290 : 0 : if (generic_seg.has_generic_args ())
291 : : {
292 : 0 : if (!translated->has_substitutions_defined ())
293 : : {
294 : 0 : rust_error_at (item_seg->get_locus (),
295 : : "substitutions not supported for %s",
296 : 0 : translated->as_string ().c_str ());
297 : 0 : translated
298 : 0 : = new TyTy::ErrorType (path.get_mappings ().get_hirid ());
299 : 0 : return;
300 : : }
301 : 0 : translated
302 : 0 : = SubstMapper::Resolve (translated, path.get_locus (),
303 : 0 : &generic_seg.get_generic_args (),
304 : 0 : context->regions_from_generic_args (
305 : 0 : generic_seg.get_generic_args ()));
306 : : }
307 : : }
308 : :
309 : : // continue on as a path-in-expression
310 : 159 : bool fully_resolved = path.get_segments ().empty ();
311 : 159 : if (fully_resolved)
312 : : {
313 : 159 : resolver->insert_resolved_type (path.get_mappings ().get_nodeid (),
314 : : root_resolved_node_id);
315 : 159 : context->insert_receiver (path.get_mappings ().get_hirid (), root);
316 : 159 : return;
317 : : }
318 : :
319 : 0 : translated
320 : 0 : = resolve_segments (root_resolved_node_id,
321 : 0 : path.get_mappings ().get_hirid (), path.get_segments (),
322 : 0 : 0, translated, path.get_mappings (), path.get_locus ());
323 : 636 : }
324 : :
325 : : TyTy::BaseType *
326 : 27005 : TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
327 : : NodeId *root_resolved_node_id)
328 : : {
329 : 27005 : TyTy::BaseType *root_tyty = nullptr;
330 : 27005 : *offset = 0;
331 : 53771 : for (size_t i = 0; i < path.get_num_segments (); i++)
332 : : {
333 : 27793 : std::unique_ptr<HIR::TypePathSegment> &seg = path.get_segments ().at (i);
334 : :
335 : 27793 : bool have_more_segments = (path.get_num_segments () - 1 != i);
336 : 27793 : bool is_root = *offset == 0;
337 : 27793 : NodeId ast_node_id = seg->get_mappings ().get_nodeid ();
338 : :
339 : : // then lookup the reference_node_id
340 : 27793 : NodeId ref_node_id = UNKNOWN_NODEID;
341 : 27793 : if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
342 : : {
343 : 27776 : resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
344 : : }
345 : :
346 : : // ref_node_id is the NodeId that the segments refers to.
347 : 27793 : if (ref_node_id == UNKNOWN_NODEID)
348 : : {
349 : 771 : if (is_root)
350 : : {
351 : 0 : rust_error_at (seg->get_locus (),
352 : : "unknown reference for resolved name: %<%s%>",
353 : 0 : seg->get_ident_segment ().as_string ().c_str ());
354 : 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
355 : : }
356 : : return root_tyty;
357 : : }
358 : :
359 : : // node back to HIR
360 : 27022 : HirId ref = UNKNOWN_HIRID;
361 : 27022 : if (!mappings->lookup_node_to_hir (ref_node_id, &ref))
362 : : {
363 : 0 : if (is_root)
364 : : {
365 : 0 : rust_error_at (seg->get_locus (), "789 reverse lookup failure");
366 : 0 : rust_debug_loc (
367 : : seg->get_locus (),
368 : : "failure with [%s] mappings [%s] ref_node_id [%u]",
369 : 0 : seg->as_string ().c_str (),
370 : 0 : seg->get_mappings ().as_string ().c_str (), ref_node_id);
371 : :
372 : 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
373 : : }
374 : :
375 : : return root_tyty;
376 : : }
377 : :
378 : 27022 : auto seg_is_module = (nullptr != mappings->lookup_module (ref));
379 : 27022 : auto seg_is_crate = mappings->is_local_hirid_crate (ref);
380 : 27022 : if (seg_is_module || seg_is_crate)
381 : : {
382 : : // A::B::C::this_is_a_module::D::E::F
383 : : // ^^^^^^^^^^^^^^^^
384 : : // Currently handling this.
385 : 17 : if (have_more_segments)
386 : : {
387 : 17 : (*offset)++;
388 : 17 : continue;
389 : : }
390 : :
391 : : // In the case of :
392 : : // A::B::C::this_is_a_module
393 : : // ^^^^^^^^^^^^^^^^
394 : : // This is an error, we are not expecting a module.
395 : 0 : rust_error_at (seg->get_locus (), "expected value");
396 : 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
397 : : }
398 : :
399 : 27005 : TyTy::BaseType *lookup = nullptr;
400 : 27005 : if (!query_type (ref, &lookup))
401 : : {
402 : 0 : if (is_root)
403 : : {
404 : 0 : rust_error_at (seg->get_locus (),
405 : : "failed to resolve root segment");
406 : 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
407 : : }
408 : : return root_tyty;
409 : : }
410 : :
411 : : // if we have a previous segment type
412 : 27005 : if (root_tyty != nullptr)
413 : : {
414 : : // if this next segment needs substitution we must apply the
415 : : // previous type arguments
416 : : //
417 : : // such as: GenericStruct::<_>::new(123, 456)
418 : 0 : if (lookup->needs_generic_substitutions ())
419 : : {
420 : 0 : if (!root_tyty->needs_generic_substitutions ())
421 : : {
422 : 0 : auto used_args_in_prev_segment
423 : 0 : = GetUsedSubstArgs::From (root_tyty);
424 : 0 : lookup
425 : 0 : = SubstMapperInternal::Resolve (lookup,
426 : : used_args_in_prev_segment);
427 : 0 : }
428 : : }
429 : : }
430 : :
431 : : // turbo-fish segment path::<ty>
432 : 27005 : if (seg->is_generic_segment ())
433 : : {
434 : 926 : HIR::TypePathSegmentGeneric *generic_segment
435 : 926 : = static_cast<HIR::TypePathSegmentGeneric *> (seg.get ());
436 : :
437 : 926 : auto regions = context->regions_from_generic_args (
438 : 926 : generic_segment->get_generic_args ());
439 : 926 : lookup = SubstMapper::Resolve (lookup, path.get_locus (),
440 : 926 : &generic_segment->get_generic_args (),
441 : : regions);
442 : 926 : if (lookup->get_kind () == TyTy::TypeKind::ERROR)
443 : 1 : return new TyTy::ErrorType (seg->get_mappings ().get_hirid ());
444 : 926 : }
445 : 26079 : else if (lookup->needs_generic_substitutions ())
446 : : {
447 : 142 : HIR::GenericArgs empty
448 : 142 : = HIR::GenericArgs::create_empty (path.get_locus ());
449 : 142 : lookup
450 : 142 : = SubstMapper::Resolve (lookup, path.get_locus (), &empty,
451 : 284 : context->regions_from_generic_args (empty));
452 : 142 : }
453 : :
454 : 27004 : *root_resolved_node_id = ref_node_id;
455 : 27004 : *offset = *offset + 1;
456 : 27004 : root_tyty = lookup;
457 : :
458 : : // this enforces the proper get_segments checks to take place
459 : 53753 : auto *maybe_adt = root_tyty->try_as<const TyTy::ADTType> ();
460 : 2486 : if (maybe_adt && maybe_adt->is_enum ())
461 : 255 : return root_tyty;
462 : : }
463 : :
464 : : return root_tyty;
465 : : }
466 : :
467 : : TyTy::BaseType *
468 : 773 : TypeCheckType::resolve_segments (
469 : : NodeId root_resolved_node_id, HirId expr_id,
470 : : std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset,
471 : : TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings,
472 : : location_t expr_locus)
473 : : {
474 : 773 : NodeId resolved_node_id = root_resolved_node_id;
475 : 773 : TyTy::BaseType *prev_segment = tyseg;
476 : 1544 : for (size_t i = offset; i < segments.size (); i++)
477 : : {
478 : 773 : std::unique_ptr<HIR::TypePathSegment> &seg = segments.at (i);
479 : :
480 : 773 : bool reciever_is_generic
481 : 773 : = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
482 : 773 : bool probe_bounds = true;
483 : 773 : bool probe_impls = !reciever_is_generic;
484 : 773 : bool ignore_mandatory_trait_items = !reciever_is_generic;
485 : :
486 : : // probe the path is done in two parts one where we search impls if no
487 : : // candidate is found then we search extensions from traits
488 : 773 : auto candidates
489 : : = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
490 : : probe_impls, false,
491 : 773 : ignore_mandatory_trait_items);
492 : 773 : if (candidates.size () == 0)
493 : : {
494 : 650 : candidates
495 : 650 : = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
496 : : false, probe_bounds,
497 : 650 : ignore_mandatory_trait_items);
498 : :
499 : 650 : if (candidates.size () == 0)
500 : : {
501 : 0 : rust_error_at (
502 : : seg->get_locus (),
503 : : "failed to resolve path segment using an impl Probe");
504 : 0 : return new TyTy::ErrorType (expr_id);
505 : : }
506 : : }
507 : :
508 : 773 : if (candidates.size () > 1)
509 : : {
510 : 0 : ReportMultipleCandidateError::Report (candidates,
511 : : seg->get_ident_segment (),
512 : : seg->get_locus ());
513 : 0 : return new TyTy::ErrorType (expr_id);
514 : : }
515 : :
516 : 773 : auto &candidate = *candidates.begin ();
517 : 773 : prev_segment = tyseg;
518 : 773 : tyseg = candidate.ty;
519 : :
520 : 773 : if (candidate.is_enum_candidate ())
521 : : {
522 : 2 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
523 : 2 : auto last_variant = adt->get_variants ();
524 : 2 : TyTy::VariantDef *variant = last_variant.back ();
525 : :
526 : 2 : rich_location richloc (line_table, seg->get_locus ());
527 : 2 : richloc.add_fixit_replace ("not a type");
528 : :
529 : 2 : rust_error_at (richloc, ErrorCode::E0573,
530 : : "expected type, found variant of %<%s::%s%>",
531 : 4 : adt->get_name ().c_str (),
532 : 2 : variant->get_identifier ().c_str ());
533 : 2 : return new TyTy::ErrorType (expr_id);
534 : 2 : }
535 : :
536 : 771 : if (candidate.is_impl_candidate ())
537 : : {
538 : 121 : resolved_node_id
539 : 121 : = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid ();
540 : : }
541 : : else
542 : : {
543 : 650 : resolved_node_id
544 : 650 : = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
545 : : }
546 : :
547 : 771 : if (seg->is_generic_segment ())
548 : : {
549 : 0 : auto *generic_segment
550 : 0 : = static_cast<HIR::TypePathSegmentGeneric *> (seg.get ());
551 : :
552 : 0 : std::vector<TyTy::Region> regions;
553 : 0 : for (auto &lifetime :
554 : 0 : generic_segment->get_generic_args ().get_lifetime_args ())
555 : : {
556 : 0 : auto region = context->lookup_and_resolve_lifetime (lifetime);
557 : 0 : if (!region.has_value ())
558 : : {
559 : 0 : rust_error_at (lifetime.get_locus (),
560 : : "failed to resolve lifetime");
561 : 0 : return new TyTy::ErrorType (expr_id);
562 : : }
563 : 0 : regions.push_back (region.value ());
564 : : }
565 : :
566 : 0 : tyseg = SubstMapper::Resolve (tyseg, expr_locus,
567 : 0 : &generic_segment->get_generic_args (),
568 : : regions);
569 : 0 : if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
570 : 0 : return new TyTy::ErrorType (expr_id);
571 : 0 : }
572 : 773 : }
573 : :
574 : 771 : context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
575 : 771 : rust_assert (resolved_node_id != UNKNOWN_NODEID);
576 : :
577 : : // lookup if the name resolver was able to canonically resolve this or not
578 : 771 : NodeId path_resolved_id = UNKNOWN_NODEID;
579 : 771 : if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (),
580 : : &path_resolved_id))
581 : : {
582 : 0 : rust_assert (path_resolved_id == resolved_node_id);
583 : : }
584 : : // check the type scope
585 : 771 : else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (),
586 : : &path_resolved_id))
587 : : {
588 : 0 : rust_assert (path_resolved_id == resolved_node_id);
589 : : }
590 : : else
591 : : {
592 : : // name scope first
593 : 771 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
594 : : {
595 : 0 : resolver->insert_resolved_name (expr_mappings.get_nodeid (),
596 : : resolved_node_id);
597 : : }
598 : : // check the type scope
599 : 771 : else if (resolver->get_type_scope ().decl_was_declared_here (
600 : : resolved_node_id))
601 : : {
602 : 771 : resolver->insert_resolved_type (expr_mappings.get_nodeid (),
603 : : resolved_node_id);
604 : : }
605 : : }
606 : :
607 : : return tyseg;
608 : : }
609 : :
610 : : void
611 : 110 : TypeCheckType::visit (HIR::TraitObjectType &type)
612 : : {
613 : 110 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
614 : 227 : for (auto &bound : type.get_type_param_bounds ())
615 : : {
616 : 117 : if (bound->get_bound_type ()
617 : : != HIR::TypeParamBound::BoundType::TRAITBOUND)
618 : 7 : continue;
619 : :
620 : 110 : HIR::TypeParamBound &b = *bound.get ();
621 : 110 : HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
622 : :
623 : 110 : auto binder_pin = context->push_lifetime_binder ();
624 : 117 : for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
625 : : {
626 : 7 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
627 : : }
628 : :
629 : 110 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
630 : : trait_bound.get_path (),
631 : 110 : nullptr /*this will setup a PLACEHOLDER for self*/);
632 : :
633 : 110 : if (!predicate.is_error ()
634 : 110 : && predicate.is_object_safe (true, type.get_locus ()))
635 : 108 : specified_bounds.push_back (std::move (predicate));
636 : 110 : }
637 : :
638 : 110 : RustIdent ident{CanonicalPath::create_empty (), type.get_locus ()};
639 : 110 : translated
640 : 110 : = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), ident,
641 : 220 : std::move (specified_bounds));
642 : 110 : }
643 : :
644 : : void
645 : 393 : TypeCheckType::visit (HIR::ArrayType &type)
646 : : {
647 : 393 : auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ().get ());
648 : 393 : if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
649 : 0 : return;
650 : :
651 : 393 : TyTy::BaseType *expected_ty = nullptr;
652 : 393 : bool ok = context->lookup_builtin ("usize", &expected_ty);
653 : 393 : rust_assert (ok);
654 : 393 : context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty);
655 : :
656 : 393 : unify_site (type.get_size_expr ()->get_mappings ().get_hirid (),
657 : : TyTy::TyWithLocation (expected_ty),
658 : : TyTy::TyWithLocation (capacity_type,
659 : 393 : type.get_size_expr ()->get_locus ()),
660 : 393 : type.get_size_expr ()->get_locus ());
661 : :
662 : 393 : TyTy::BaseType *base
663 : 393 : = TypeCheckType::Resolve (type.get_element_type ().get ());
664 : 393 : translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
665 : 393 : type.get_locus (), *type.get_size_expr (),
666 : 786 : TyTy::TyVar (base->get_ref ()));
667 : : }
668 : :
669 : : void
670 : 746 : TypeCheckType::visit (HIR::SliceType &type)
671 : : {
672 : 746 : TyTy::BaseType *base
673 : 746 : = TypeCheckType::Resolve (type.get_element_type ().get ());
674 : 746 : translated
675 : 746 : = new TyTy::SliceType (type.get_mappings ().get_hirid (), type.get_locus (),
676 : 1492 : TyTy::TyVar (base->get_ref ()));
677 : 746 : }
678 : : void
679 : 1797 : TypeCheckType::visit (HIR::ReferenceType &type)
680 : : {
681 : 1797 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ().get ());
682 : 1797 : rust_assert (type.has_lifetime ());
683 : 1797 : auto region = context->lookup_and_resolve_lifetime (type.get_lifetime ());
684 : 1797 : if (!region.has_value ())
685 : : {
686 : 2 : rust_error_at (type.get_locus (), "failed to resolve lifetime");
687 : 2 : translated = new TyTy::ErrorType (type.get_mappings ().get_hirid ());
688 : 2 : return;
689 : : }
690 : 1795 : translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (),
691 : : TyTy::TyVar (base->get_ref ()),
692 : 3590 : type.get_mut (), region.value ());
693 : : } // namespace Resolver
694 : :
695 : : void
696 : 4686 : TypeCheckType::visit (HIR::RawPointerType &type)
697 : : {
698 : 4686 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ().get ());
699 : 4686 : translated
700 : 4686 : = new TyTy::PointerType (type.get_mappings ().get_hirid (),
701 : 9372 : TyTy::TyVar (base->get_ref ()), type.get_mut ());
702 : 4686 : }
703 : :
704 : : void
705 : 131 : TypeCheckType::visit (HIR::InferredType &type)
706 : : {
707 : 262 : translated = new TyTy::InferType (type.get_mappings ().get_hirid (),
708 : : TyTy::InferType::InferTypeKind::GENERAL,
709 : : TyTy::InferType::TypeHint::Default (),
710 : 262 : type.get_locus ());
711 : 131 : }
712 : :
713 : : void
714 : 23 : TypeCheckType::visit (HIR::NeverType &type)
715 : : {
716 : 23 : TyTy::BaseType *lookup = nullptr;
717 : 23 : bool ok = context->lookup_builtin ("!", &lookup);
718 : 23 : rust_assert (ok);
719 : :
720 : 23 : translated = lookup->clone ();
721 : 23 : }
722 : :
723 : : TyTy::ParamType *
724 : 8432 : TypeResolveGenericParam::Resolve (HIR::GenericParam *param, bool apply_sized)
725 : : {
726 : 8432 : TypeResolveGenericParam resolver (apply_sized);
727 : 8432 : switch (param->get_kind ())
728 : : {
729 : 8432 : case HIR::GenericParam::GenericKind::TYPE:
730 : 8432 : resolver.visit (static_cast<HIR::TypeParam &> (*param));
731 : 8432 : break;
732 : :
733 : 0 : case HIR::GenericParam::GenericKind::CONST:
734 : 0 : resolver.visit (static_cast<HIR::ConstGenericParam &> (*param));
735 : 0 : break;
736 : :
737 : 0 : case HIR::GenericParam::GenericKind::LIFETIME:
738 : 0 : resolver.visit (static_cast<HIR::LifetimeParam &> (*param));
739 : 0 : break;
740 : : }
741 : 8430 : return resolver.resolved;
742 : 8430 : }
743 : :
744 : : void
745 : 0 : TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m)
746 : : {
747 : : // nothing to do
748 : 0 : }
749 : :
750 : : void
751 : 0 : TypeResolveGenericParam::visit (HIR::ConstGenericParam ¶m)
752 : : {
753 : : // TODO
754 : 0 : }
755 : :
756 : : void
757 : 8432 : TypeResolveGenericParam::visit (HIR::TypeParam ¶m)
758 : : {
759 : 8432 : if (param.has_type ())
760 : 102 : TypeCheckType::Resolve (param.get_type ().get ());
761 : :
762 : 8432 : HIR::Type *implicit_self_bound = nullptr;
763 : 8432 : if (param.has_type_param_bounds ())
764 : : {
765 : : // We need two possible parameter types. One with no Bounds and one with
766 : : // the bounds. the Self type for the bounds cannot itself contain the
767 : : // bounds otherwise it will be a trait cycle
768 : 337 : HirId implicit_id = mappings->get_next_hir_id ();
769 : 337 : TyTy::ParamType *p
770 : 337 : = new TyTy::ParamType (param.get_type_representation ().as_string (),
771 : : param.get_locus (), implicit_id, param,
772 : 337 : {} /*empty specified bounds*/);
773 : 337 : context->insert_implicit_type (implicit_id, p);
774 : :
775 : : // generate an implicit HIR Type we can apply to the predicate
776 : 337 : Analysis::NodeMapping mappings (param.get_mappings ().get_crate_num (),
777 : 337 : param.get_mappings ().get_nodeid (),
778 : : implicit_id,
779 : 337 : param.get_mappings ().get_local_defid ());
780 : 337 : implicit_self_bound
781 : 337 : = new HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false);
782 : : }
783 : :
784 : 8432 : std::map<DefId, std::vector<TyTy::TypeBoundPredicate>> predicates;
785 : :
786 : : // https://doc.rust-lang.org/std/marker/trait.Sized.html
787 : : // All type parameters have an implicit bound of Sized. The special syntax
788 : : // ?Sized can be used to remove this bound if it’s not appropriate.
789 : : //
790 : : // We can only do this when we are not resolving the implicit Self for Sized
791 : : // itself
792 : 8432 : rust_debug_loc (param.get_locus (), "apply_sized: %s",
793 : 8432 : apply_sized ? "true" : "false");
794 : 8432 : if (apply_sized)
795 : : {
796 : 6351 : TyTy::TypeBoundPredicate sized_predicate
797 : : = get_marker_predicate (Analysis::RustLangItem::ItemType::SIZED,
798 : 6351 : param.get_locus ());
799 : :
800 : 12698 : predicates[sized_predicate.get_id ()] = {sized_predicate};
801 : 6349 : }
802 : :
803 : : // resolve the bounds
804 : 8430 : if (param.has_type_param_bounds ())
805 : : {
806 : 676 : for (auto &bound : param.get_type_param_bounds ())
807 : : {
808 : 339 : switch (bound->get_bound_type ())
809 : : {
810 : 339 : case HIR::TypeParamBound::BoundType::TRAITBOUND: {
811 : 339 : HIR::TraitBound *b
812 : 339 : = static_cast<HIR::TraitBound *> (bound.get ());
813 : :
814 : 339 : TyTy::TypeBoundPredicate predicate
815 : : = get_predicate_from_bound (b->get_path (),
816 : : implicit_self_bound,
817 : 339 : b->get_polarity ());
818 : 339 : if (!predicate.is_error ())
819 : : {
820 : 339 : switch (predicate.get_polarity ())
821 : : {
822 : 1 : case BoundPolarity::AntiBound: {
823 : 1 : bool found = predicates.find (predicate.get_id ())
824 : 1 : != predicates.end ();
825 : 1 : if (found)
826 : 1 : predicates.erase (predicate.get_id ());
827 : : else
828 : : {
829 : : // emit error message
830 : 0 : rich_location r (line_table, b->get_locus ());
831 : 0 : r.add_range (predicate.get ()->get_locus ());
832 : 0 : rust_error_at (
833 : : r, "antibound for %s is not applied here",
834 : 0 : predicate.get ()->get_name ().c_str ());
835 : 0 : }
836 : : }
837 : : break;
838 : :
839 : 338 : default: {
840 : 338 : if (predicates.find (predicate.get_id ())
841 : 338 : == predicates.end ())
842 : : {
843 : 338 : predicates[predicate.get_id ()] = {};
844 : : }
845 : 338 : predicates[predicate.get_id ()].push_back (predicate);
846 : : }
847 : 338 : break;
848 : : }
849 : : }
850 : 339 : }
851 : 339 : break;
852 : :
853 : : default:
854 : : break;
855 : : }
856 : : }
857 : : }
858 : :
859 : : // now to flat map the specified_bounds into the raw specified predicates
860 : 16860 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
861 : 15116 : for (auto it = predicates.begin (); it != predicates.end (); it++)
862 : : {
863 : 13372 : for (const auto &predicate : it->second)
864 : : {
865 : 6686 : specified_bounds.push_back (predicate);
866 : : }
867 : : }
868 : :
869 : 16860 : resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
870 : : param.get_locus (),
871 : 16860 : param.get_mappings ().get_hirid (), param,
872 : 16860 : specified_bounds);
873 : 8430 : }
874 : :
875 : : void
876 : 436 : ResolveWhereClauseItem::Resolve (HIR::WhereClauseItem &item,
877 : : TyTy::RegionConstraints ®ion_constraints)
878 : : {
879 : 436 : ResolveWhereClauseItem resolver (region_constraints);
880 : :
881 : 436 : auto binder_pin = resolver.context->push_lifetime_binder ();
882 : :
883 : 436 : switch (item.get_item_type ())
884 : : {
885 : 0 : case HIR::WhereClauseItem::LIFETIME:
886 : 0 : resolver.visit (static_cast<HIR::LifetimeWhereClauseItem &> (item));
887 : 0 : break;
888 : :
889 : 436 : case HIR::WhereClauseItem::TYPE_BOUND:
890 : 436 : resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (item));
891 : 436 : break;
892 : : }
893 : 436 : }
894 : :
895 : : void
896 : 0 : ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &item)
897 : : {
898 : 0 : auto lhs = context->lookup_and_resolve_lifetime (item.get_lifetime ());
899 : 0 : if (!lhs.has_value ())
900 : : {
901 : 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
902 : : }
903 : 0 : for (auto &lifetime : item.get_lifetime_bounds ())
904 : : {
905 : 0 : auto rhs_i = context->lookup_and_resolve_lifetime (lifetime);
906 : 0 : if (!rhs_i.has_value ())
907 : : {
908 : 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
909 : : }
910 : 0 : region_constraints.region_region.emplace_back (lhs.value (),
911 : : rhs_i.value ());
912 : : }
913 : 0 : }
914 : :
915 : : void
916 : 436 : ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
917 : : {
918 : 436 : auto binder_pin = context->push_lifetime_binder ();
919 : 436 : if (item.has_for_lifetimes ())
920 : : {
921 : 14 : for (auto &lifetime_param : item.get_for_lifetimes ())
922 : : {
923 : 7 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
924 : : }
925 : : }
926 : :
927 : 436 : auto &binding_type_path = item.get_bound_type ();
928 : 436 : TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path.get ());
929 : :
930 : : // FIXME double check there might be a trait cycle here see TypeParam handling
931 : :
932 : 436 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
933 : 872 : for (auto &bound : item.get_type_param_bounds ())
934 : : {
935 : 436 : switch (bound->get_bound_type ())
936 : : {
937 : 432 : case HIR::TypeParamBound::BoundType::TRAITBOUND: {
938 : 432 : auto *b = static_cast<HIR::TraitBound *> (bound.get ());
939 : :
940 : 432 : TyTy::TypeBoundPredicate predicate
941 : : = get_predicate_from_bound (b->get_path (),
942 : 432 : binding_type_path.get ());
943 : 432 : if (!predicate.is_error ())
944 : 432 : specified_bounds.push_back (std::move (predicate));
945 : 432 : }
946 : 432 : break;
947 : 4 : case HIR::TypeParamBound::BoundType::LIFETIME: {
948 : 8 : if (auto param = binding->try_as<TyTy::ParamType> ())
949 : : {
950 : 4 : auto *b = static_cast<HIR::Lifetime *> (bound.get ());
951 : 4 : auto region = context->lookup_and_resolve_lifetime (*b);
952 : 4 : if (!region.has_value ())
953 : : {
954 : 0 : rust_error_at (UNKNOWN_LOCATION,
955 : : "failed to resolve lifetime");
956 : : }
957 : 4 : region_constraints.type_region.emplace_back (param,
958 : : region.value ());
959 : : }
960 : : }
961 : 4 : break;
962 : :
963 : : default:
964 : : break;
965 : : }
966 : : }
967 : 436 : binding->inherit_bounds (specified_bounds);
968 : :
969 : : // When we apply these bounds we must lookup which type this binding
970 : : // resolves to, as this is the type which will be used during resolution
971 : : // of the block.
972 : 436 : NodeId ast_node_id = binding_type_path->get_mappings ().get_nodeid ();
973 : :
974 : : // then lookup the reference_node_id
975 : 436 : NodeId ref_node_id = UNKNOWN_NODEID;
976 : 436 : if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
977 : : {
978 : : // FIXME
979 : 0 : rust_error_at (UNDEF_LOCATION,
980 : : "Failed to lookup type reference for node: %s",
981 : 0 : binding_type_path->as_string ().c_str ());
982 : 0 : return;
983 : : }
984 : :
985 : : // node back to HIR
986 : 436 : HirId ref;
987 : 436 : if (!mappings->lookup_node_to_hir (ref_node_id, &ref))
988 : : {
989 : : // FIXME
990 : 0 : rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure");
991 : 0 : return;
992 : : }
993 : :
994 : : // the base reference for this name _must_ have a type set
995 : 436 : TyTy::BaseType *lookup;
996 : 436 : if (!context->lookup_type (ref, &lookup))
997 : : {
998 : 0 : rust_error_at (mappings->lookup_location (ref),
999 : : "Failed to resolve where-clause binding type: %s",
1000 : 0 : binding_type_path->as_string ().c_str ());
1001 : 0 : return;
1002 : : }
1003 : :
1004 : : // FIXME
1005 : : // rust_assert (binding->is_equal (*lookup));
1006 : 436 : lookup->inherit_bounds (specified_bounds);
1007 : 436 : }
1008 : :
1009 : : } // namespace Resolver
1010 : : } // namespace Rust
|