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