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