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