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