Line data Source code
1 : // Copyright (C) 2020-2026 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 "rich-location.h"
23 : #include "rust-hir-map.h"
24 : #include "rust-hir-trait-resolve.h"
25 : #include "rust-hir-type-check-expr.h"
26 : #include "rust-hir-path-probe-type.h"
27 : #include "rust-finalized-name-resolution-context.h"
28 : #include "rust-mapping-common.h"
29 : #include "rust-rib.h"
30 : #include "rust-substitution-mapper.h"
31 : #include "rust-type-util.h"
32 : #include "rust-system.h"
33 : #include "rust-compile-base.h"
34 : #include "rust-resolve-builtins.h"
35 : #include "rust-tyty.h"
36 : #include "text-range-label.h"
37 :
38 : namespace Rust {
39 : namespace Resolver {
40 :
41 : HIR::GenericArgs
42 0 : TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment &segment)
43 : {
44 0 : TypeCheckResolveGenericArguments resolver (segment.get_locus ());
45 0 : switch (segment.get_type ())
46 : {
47 0 : case HIR::TypePathSegment::SegmentType::GENERIC:
48 0 : resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (segment));
49 0 : break;
50 :
51 : default:
52 : break;
53 : }
54 0 : return resolver.args;
55 0 : }
56 :
57 : void
58 0 : TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
59 : {
60 0 : args = generic.get_generic_args ();
61 0 : }
62 :
63 : TyTy::BaseType *
64 138692 : TypeCheckType::Resolve (HIR::Type &type, ResolutionMode mode)
65 : {
66 : // is it already resolved?
67 138692 : auto context = TypeCheckContext::get ();
68 138692 : TyTy::BaseType *resolved = nullptr;
69 138692 : bool already_resolved
70 138692 : = context->lookup_type (type.get_mappings ().get_hirid (), &resolved);
71 138692 : if (already_resolved && mode == ResolutionMode::REFERENCE)
72 69215 : return resolved;
73 :
74 69477 : TypeCheckType resolver (type.get_mappings ().get_hirid (), mode);
75 69477 : type.accept_vis (resolver);
76 69476 : rust_assert (resolver.translated != nullptr);
77 69476 : resolver.context->insert_type (type.get_mappings (), resolver.translated);
78 69476 : return resolver.translated;
79 69476 : }
80 :
81 : void
82 66 : TypeCheckType::visit (HIR::BareFunctionType &fntype)
83 : {
84 66 : auto binder_pin = context->push_lifetime_binder ();
85 68 : for (auto &lifetime_param : fntype.get_for_lifetimes ())
86 : {
87 2 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
88 : }
89 :
90 66 : TyTy::BaseType *return_type;
91 66 : if (fntype.has_return_type ())
92 : {
93 46 : return_type = TypeCheckType::Resolve (fntype.get_return_type ());
94 : }
95 : else
96 : {
97 : // needs a new implicit ID
98 20 : HirId ref = mappings.get_next_hir_id ();
99 20 : return_type = TyTy::TupleType::get_unit_type ();
100 20 : context->insert_implicit_type (ref, return_type);
101 : }
102 :
103 66 : std::vector<TyTy::TyVar> params;
104 66 : params.reserve (fntype.get_function_params ().size ());
105 :
106 117 : for (auto ¶m : fntype.get_function_params ())
107 : {
108 51 : TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ());
109 51 : params.emplace_back (ptype->get_ref ());
110 : }
111 :
112 66 : translated
113 132 : = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (),
114 : std::move (params),
115 66 : TyTy::TyVar (return_type->get_ref ()),
116 66 : fntype.get_function_qualifiers ().get_abi (),
117 264 : fntype.get_function_qualifiers ().get_unsafety ());
118 66 : }
119 :
120 : void
121 516 : TypeCheckType::visit (HIR::TupleType &tuple)
122 : {
123 516 : if (tuple.is_unit_type ())
124 : {
125 97 : translated = TyTy::TupleType::get_unit_type ();
126 97 : return;
127 : }
128 :
129 419 : std::vector<TyTy::TyVar> fields;
130 419 : fields.reserve (tuple.get_elems ().size ());
131 :
132 1212 : for (auto &elem : tuple.get_elems ())
133 : {
134 793 : auto field_ty = TypeCheckType::Resolve (*elem);
135 793 : fields.emplace_back (field_ty->get_ref ());
136 : }
137 :
138 838 : translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (),
139 1257 : tuple.get_locus (), fields);
140 419 : }
141 :
142 : void
143 54399 : TypeCheckType::visit (HIR::TypePath &path)
144 : {
145 : // this can happen so we need to look up the root then resolve the
146 : // remaining segments if possible
147 54399 : bool wasBigSelf = false;
148 54399 : size_t offset = 0;
149 54399 : TyTy::BaseType *root = resolve_root_path (path, &offset, &wasBigSelf);
150 54399 : if (root->get_kind () == TyTy::TypeKind::ERROR)
151 : {
152 9 : rust_debug_loc (path.get_locus (), "failed to resolve type-path type");
153 53252 : return;
154 : }
155 :
156 54390 : TyTy::BaseType *path_type = root;
157 54390 : if (mode == ResolutionMode::REFERENCE)
158 : {
159 : // A recursive path must keep referring to the in-progress nominal ADT.
160 : // Cloning its currently empty variant list would leave a permanently
161 : // incomplete snapshot in the recursive field.
162 53030 : auto *root_adt = root->try_as<TyTy::ADTType> ();
163 6144 : bool recursive_root
164 6144 : = root_adt != nullptr && root_adt->get_variants ().empty ();
165 52995 : if (!recursive_root)
166 : {
167 52995 : path_type = root->clone ();
168 52995 : path_type->set_ref (path.get_mappings ().get_hirid ());
169 : }
170 53030 : context->insert_implicit_type (path.get_mappings ().get_hirid (),
171 : path_type);
172 : }
173 :
174 54390 : bool fully_resolved = offset >= path.get_segments ().size ();
175 54390 : if (fully_resolved)
176 : {
177 53243 : translated = path_type;
178 53243 : rust_debug_loc (path.get_locus (), "root resolved type-path to: [%s]",
179 : translated->debug_str ().c_str ());
180 : return;
181 : }
182 :
183 1147 : translated
184 1147 : = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
185 1147 : offset, path_type, path.get_mappings (),
186 1147 : path.get_locus (), wasBigSelf);
187 :
188 1147 : if (auto p = translated->try_as<TyTy::ProjectionType> ())
189 1144 : translated
190 1144 : = normalize_projection (p, path.get_locus (), false /*emit errors*/,
191 : false /*unify self*/);
192 :
193 1147 : rust_debug_loc (path.get_locus (), "resolved type-path to: [%s]",
194 : translated->debug_str ().c_str ());
195 : }
196 :
197 : void
198 249 : TypeCheckType::visit (HIR::QualifiedPathInType &path)
199 : {
200 249 : HIR::QualifiedPathType qual_path_type = path.get_path_type ();
201 249 : TyTy::BaseType *root = TypeCheckType::Resolve (qual_path_type.get_type ());
202 249 : if (root->get_kind () == TyTy::TypeKind::ERROR)
203 : {
204 0 : rust_debug_loc (path.get_locus (), "failed to resolve the root");
205 : return;
206 : }
207 :
208 249 : if (!qual_path_type.has_as_clause ())
209 : {
210 1 : translated
211 1 : = resolve_segments (path.get_mappings ().get_hirid (),
212 : path.get_segments (), 0, translated,
213 1 : path.get_mappings (), path.get_locus (), false);
214 :
215 1 : return;
216 : }
217 :
218 : // Resolve the trait now
219 248 : auto &trait_path_ref = qual_path_type.get_trait ();
220 248 : TraitReference *trait_ref = TraitResolver::Resolve (trait_path_ref);
221 248 : if (trait_ref->is_error ())
222 : return;
223 :
224 : // get the predicate for the bound
225 248 : auto specified_bound
226 : = get_predicate_from_bound (qual_path_type.get_trait (),
227 248 : qual_path_type.get_type (),
228 248 : BoundPolarity::RegularBound, true);
229 248 : if (specified_bound.is_error ())
230 : return;
231 :
232 : // inherit the bound
233 248 : root->inherit_bound (specified_bound);
234 :
235 : // lookup the associated item from the specified bound
236 248 : HIR::TypePathSegment &item_seg = path.get_associated_segment ();
237 248 : HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment ();
238 248 : tl::optional<TyTy::TypeBoundPredicateItem> item
239 248 : = specified_bound.lookup_associated_item (item_seg_identifier.to_string ());
240 248 : if (!item.has_value ())
241 : {
242 1 : std::string item_seg_ident_name, rich_msg;
243 1 : item_seg_ident_name = qual_path_type.get_trait ().to_string ();
244 2 : rich_msg = "not found in `" + item_seg_ident_name + "`";
245 :
246 1 : rich_location richloc (line_table, item_seg.get_locus ());
247 1 : richloc.add_fixit_replace (rich_msg.c_str ());
248 :
249 2 : rust_error_at (richloc, ErrorCode::E0576,
250 : "cannot find associated type %qs in trait %qs",
251 1 : item_seg_identifier.to_string ().c_str (),
252 : item_seg_ident_name.c_str ());
253 1 : return;
254 1 : }
255 :
256 : // Build projection via the predicates own rebasing helper so the
257 : // projection's substitutions are populated with the trait-coord args from
258 : // the qualified path:
259 : // (<Bar<i32> as Foo<i32>>::A -> Projection Self=Bar<i32>, T=i32)
260 247 : TyTy::BaseType *rebased_item = item->get_tyty_for_receiver (root);
261 247 : if (auto *proj = rebased_item->try_as<TyTy::ProjectionType> ())
262 247 : translated
263 247 : = normalize_projection (proj, path.get_locus (), false /*emit errors*/,
264 : false /*unify self*/);
265 : else
266 : translated = rebased_item;
267 :
268 : // turbo-fish segment path::<ty>
269 247 : if (item_seg.get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
270 : {
271 7 : auto &generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (item_seg);
272 :
273 : // turbo-fish segment path::<ty>
274 7 : if (generic_seg.has_generic_args ())
275 : {
276 7 : if (!translated->has_substitutions_defined ())
277 : {
278 0 : rust_error_at (item_seg.get_locus (),
279 : "substitutions not supported for %s",
280 0 : translated->as_string ().c_str ());
281 0 : translated
282 0 : = new TyTy::ErrorType (path.get_mappings ().get_hirid ());
283 0 : return;
284 : }
285 7 : translated
286 7 : = SubstMapper::Resolve (translated, path.get_locus (),
287 7 : &generic_seg.get_generic_args (),
288 7 : context->regions_from_generic_args (
289 7 : generic_seg.get_generic_args ()));
290 :
291 : // unwrap the sweets
292 7 : if (auto *proj = translated->try_as<TyTy::ProjectionType> ())
293 7 : if (!proj->is_trait_position () && proj->get () != nullptr)
294 7 : translated = proj->get ();
295 : }
296 : }
297 :
298 : // continue on as a path-in-expression
299 247 : bool fully_resolved = path.get_segments ().empty ();
300 247 : if (fully_resolved)
301 : return;
302 :
303 0 : translated
304 0 : = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
305 0 : 0, translated, path.get_mappings (), path.get_locus (),
306 : false);
307 497 : }
308 :
309 : TyTy::BaseType *
310 54399 : TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
311 : bool *wasBigSelf)
312 : {
313 54399 : TyTy::BaseType *root_tyty = nullptr;
314 54399 : *offset = 0;
315 :
316 107306 : for (size_t i = 0; i < path.get_num_segments (); i++)
317 : {
318 55856 : std::unique_ptr<HIR::TypePathSegment> &seg = path.get_segments ().at (i);
319 :
320 55856 : bool have_more_segments = (path.get_num_segments () - 1 != i);
321 55856 : bool is_root = *offset == 0;
322 55856 : NodeId ast_node_id = seg->get_mappings ().get_nodeid ();
323 :
324 : // then lookup the reference_node_id
325 55856 : NodeId ref_node_id = UNKNOWN_NODEID;
326 :
327 55856 : if (seg->is_lang_item ())
328 50 : ref_node_id = Analysis::Mappings::get ().get_lang_item_node (
329 50 : seg->get_lang_item ());
330 : else
331 : {
332 55806 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
333 :
334 : // assign the ref_node_id if we've found something
335 55806 : nr_ctx.lookup (ast_node_id, Resolver2_0::Namespace::Types)
336 110466 : .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
337 :
338 : // TODO: Should we add a special method to the name resolver to handle
339 : // that case? Resolving something in the Types NS when we want to
340 : // prioritize builtin types over modules or other conflicting things?
341 111612 : if (auto builtin_type_id
342 55806 : = Resolver2_0::Builtins::find_builtin_node_id (seg->to_string ()))
343 28586 : if (mappings.is_module (ref_node_id))
344 2 : ref_node_id = builtin_type_id.value ();
345 : }
346 :
347 : // ref_node_id is the NodeId that the segments refers to.
348 55856 : if (ref_node_id == UNKNOWN_NODEID)
349 : {
350 1146 : if (is_root)
351 : {
352 0 : rust_error_at (seg->get_locus (),
353 : "unknown reference for resolved name: %qs",
354 0 : seg->to_string ().c_str ());
355 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
356 : }
357 1146 : else if (root_tyty == nullptr)
358 : {
359 1 : rust_error_at (seg->get_locus (),
360 : "unknown reference for resolved name: %qs",
361 1 : seg->to_string ().c_str ());
362 1 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
363 : }
364 : return root_tyty;
365 : }
366 :
367 54710 : if (seg->is_ident_only () && seg->to_string () == "Self")
368 9593 : *wasBigSelf = true;
369 :
370 : // node back to HIR
371 54710 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
372 54710 : if (!hid.has_value ())
373 : {
374 0 : if (is_root)
375 : {
376 0 : rust_error_at (seg->get_locus (), "789 reverse lookup failure");
377 0 : rust_debug_loc (
378 : seg->get_locus (),
379 : "failure with [%s] mappings [%s] ref_node_id [%u]",
380 : seg->to_string ().c_str (),
381 : seg->get_mappings ().as_string ().c_str (), ref_node_id);
382 :
383 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
384 : }
385 :
386 : return root_tyty;
387 : }
388 54710 : auto ref = hid.value ();
389 :
390 54710 : auto seg_is_module = mappings.hir.modules.lookup (ref).has_value ();
391 54710 : auto seg_is_crate = mappings.is_local_hirid_crate (ref);
392 54710 : if (seg_is_module || seg_is_crate)
393 : {
394 : // A::B::C::this_is_a_module::D::E::F
395 : // ^^^^^^^^^^^^^^^^
396 : // Currently handling this.
397 312 : if (have_more_segments)
398 : {
399 312 : (*offset)++;
400 312 : continue;
401 : }
402 :
403 : // In the case of :
404 : // A::B::C::this_is_a_module
405 : // ^^^^^^^^^^^^^^^^
406 : // This is an error, we are not expecting a module.
407 0 : rust_error_at (seg->get_locus (), "expected value, got module");
408 :
409 0 : return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
410 : }
411 :
412 54398 : TyTy::BaseType *lookup = nullptr;
413 54398 : 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->to_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 54397 : 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 54397 : if (seg->is_generic_segment ())
448 : {
449 2126 : auto &generic_segment
450 2126 : = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
451 :
452 2126 : auto regions = context->regions_from_generic_args (
453 2126 : generic_segment.get_generic_args ());
454 2126 : lookup = SubstMapper::Resolve (lookup, path.get_locus (),
455 2126 : &generic_segment.get_generic_args (),
456 : regions);
457 2126 : if (lookup->get_kind () == TyTy::TypeKind::ERROR)
458 4 : return new TyTy::ErrorType (seg->get_mappings ().get_hirid ());
459 2126 : }
460 52271 : else if (lookup->needs_generic_substitutions ())
461 : {
462 186 : HIR::GenericArgs empty
463 186 : = HIR::GenericArgs::create_empty (path.get_locus ());
464 186 : lookup
465 186 : = SubstMapper::Resolve (lookup, path.get_locus (), &empty,
466 186 : context->regions_from_generic_args (empty));
467 186 : }
468 :
469 54393 : *offset = *offset + 1;
470 54393 : root_tyty = lookup;
471 :
472 : // this enforces the proper get_segments checks to take place
473 106988 : auto *maybe_adt = root_tyty->try_as<const TyTy::ADTType> ();
474 6144 : if (maybe_adt && maybe_adt->is_enum ())
475 : return root_tyty;
476 : }
477 :
478 : return root_tyty;
479 : }
480 :
481 : bool
482 976 : TypeCheckType::resolve_associated_type (const std::string &search,
483 : TypeCheckBlockContextItem &ctx,
484 : TyTy::BaseType **result)
485 : {
486 976 : if (ctx.is_trait_block ())
487 : {
488 810 : HIR::Trait &trait = ctx.get_trait ();
489 926 : for (auto &item : trait.get_trait_items ())
490 : {
491 893 : if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::TYPE)
492 36 : continue;
493 :
494 857 : if (item->trait_identifier () == search)
495 : {
496 777 : HirId item_id = item->get_mappings ().get_hirid ();
497 777 : if (query_type (item_id, result))
498 976 : 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 166 : HIR::ImplBlock &block = ctx.get_impl_block ();
510 209 : for (auto &item : block.get_impl_items ())
511 : {
512 185 : if (item->get_impl_item_type () != HIR::ImplItem::TYPE_ALIAS)
513 26 : continue;
514 :
515 159 : if (item->get_impl_item_name () == search)
516 : {
517 142 : HirId item_id = item->get_impl_mappings ().get_hirid ();
518 142 : if (query_type (item_id, result))
519 976 : return true;
520 : }
521 : }
522 :
523 : return false;
524 : }
525 :
526 : bool
527 1147 : TypeCheckType::try_resolve_contextual_self_associated_type (
528 : const HIR::TypePathSegment &segment, bool first_segment,
529 : bool ty_seg_is_big_self, TyTy::BaseType **result)
530 : {
531 1147 : if (!first_segment || !ty_seg_is_big_self
532 1147 : || !context->block_context ().is_in_context ())
533 : return false;
534 :
535 976 : TypeCheckBlockContextItem ctx = context->block_context ().peek ();
536 976 : return resolve_associated_type (segment.to_string (), ctx, result);
537 : }
538 :
539 : TyTy::BaseType *
540 1148 : TypeCheckType::resolve_segments (
541 : HirId expr_id, std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments,
542 : size_t offset, TyTy::BaseType *tyseg,
543 : const Analysis::NodeMapping &expr_mappings, location_t expr_locus,
544 : bool tySegIsBigSelf)
545 : {
546 2292 : for (size_t i = offset; i < segments.size (); i++)
547 : {
548 1147 : auto &seg = segments.at (i);
549 1147 : const auto &ident_segment = seg->get_ident_segment ();
550 1147 : bool first_segment = i == offset;
551 1147 : TyTy::BaseType *associated_type = nullptr;
552 :
553 1147 : bool selfResolveOk
554 1147 : = try_resolve_contextual_self_associated_type (*seg, first_segment,
555 : tySegIsBigSelf,
556 : &associated_type);
557 1147 : if (selfResolveOk)
558 : {
559 919 : tyseg = associated_type;
560 : }
561 : else
562 : {
563 228 : if (auto adt = tyseg->try_as<TyTy::ADTType> ())
564 : {
565 16 : if (adt->is_enum ())
566 : {
567 2 : rich_location r (line_table, seg->get_locus ());
568 2 : text_range_label label ("enum declared here");
569 :
570 2 : auto item_lookup = mappings.lookup_defid (adt->get_id ());
571 2 : if (item_lookup.has_value ())
572 : {
573 2 : auto &item = item_lookup.value ();
574 2 : r.add_range (item->get_locus (), SHOW_RANGE_WITHOUT_CARET,
575 : &label);
576 : }
577 :
578 2 : TyTy::VariantDef *v;
579 4 : if (adt->lookup_variant (ident_segment.to_string (), &v))
580 : {
581 2 : rust_error_at (
582 : r, ErrorCode::E0573,
583 : "expected type, found variant of %<%s::%s%>",
584 4 : adt->get_name ().c_str (),
585 2 : v->get_identifier ().c_str ());
586 2 : return new TyTy::ErrorType (expr_id);
587 : }
588 2 : }
589 : }
590 :
591 226 : auto result = TypePathProbe::Probe (tyseg, ident_segment);
592 226 : auto &candidates = result.type_candidates;
593 :
594 226 : if (candidates.empty ())
595 : {
596 2 : rust_error_at (seg->get_locus (),
597 : "failed to resolve path segment %<%s%> as a type",
598 1 : ident_segment.to_string ().c_str ());
599 1 : return new TyTy::ErrorType (expr_id);
600 : }
601 :
602 225 : if (candidates.size () > 1)
603 : {
604 0 : ReportMultipleCandidateError::Report (candidates, ident_segment,
605 : seg->get_locus ());
606 0 : return new TyTy::ErrorType (expr_id);
607 : }
608 :
609 225 : auto &candidate = *candidates.begin ();
610 225 : tyseg = candidate.ty;
611 226 : }
612 :
613 1144 : if (seg->is_generic_segment ())
614 : {
615 20 : auto &generic_segment
616 20 : = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
617 :
618 20 : std::vector<TyTy::Region> regions;
619 0 : for (auto &lifetime :
620 20 : generic_segment.get_generic_args ().get_lifetime_args ())
621 : {
622 0 : auto region = context->lookup_and_resolve_lifetime (lifetime);
623 0 : if (!region.has_value ())
624 : {
625 0 : rust_error_at (lifetime.get_locus (),
626 : "failed to resolve lifetime");
627 0 : return new TyTy::ErrorType (expr_id);
628 : }
629 0 : regions.push_back (region.value ());
630 : }
631 :
632 20 : tyseg = SubstMapper::Resolve (tyseg, expr_locus,
633 20 : &generic_segment.get_generic_args (),
634 : regions);
635 20 : if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
636 0 : return new TyTy::ErrorType (expr_id);
637 20 : }
638 : }
639 :
640 : return tyseg;
641 : }
642 :
643 : void
644 227 : TypeCheckType::visit (HIR::TraitObjectType &type)
645 : {
646 227 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
647 467 : for (auto &bound : type.get_type_param_bounds ())
648 : {
649 : // TODO: here we need to check if there are additional bounds that aren't
650 : // auto traits. this is an error. for example, `dyn A + Sized + Sync` is
651 : // okay, because Sized and Sync are both auto traits but `dyn A + Copy +
652 : // Clone` is not okay and should error out.
653 :
654 240 : if (bound->get_bound_type ()
655 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
656 7 : continue;
657 :
658 233 : HIR::TypeParamBound &b = *bound.get ();
659 233 : HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
660 :
661 233 : auto binder_pin = context->push_lifetime_binder ();
662 240 : for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
663 : {
664 7 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
665 : }
666 :
667 233 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
668 : trait_bound.get_path (),
669 233 : tl::nullopt /*this will setup a PLACEHOLDER for self*/);
670 :
671 233 : if (!predicate.is_error ()
672 233 : && predicate.is_object_safe (true, type.get_locus ()))
673 231 : specified_bounds.push_back (std::move (predicate));
674 233 : }
675 :
676 : // The dyn_drop lint: a trait object with a `Drop` bound is pointless, as
677 : // values are dropped automatically regardless of the bound.
678 227 : if (flag_unused_check_2_0)
679 1 : if (auto drop = mappings.lookup_lang_item (LangItem::Kind::DROP))
680 2 : for (auto &bound : specified_bounds)
681 2 : if (bound.get_id () == drop.value ())
682 1 : rust_warning_at (type.get_locus (), OPT_Wunused,
683 : "this trait object has a %<Drop%> bound, which has "
684 : "no effect");
685 :
686 227 : RustIdent ident{CanonicalPath::create_empty (), type.get_locus ()};
687 227 : translated
688 227 : = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), ident,
689 454 : std::move (specified_bounds));
690 227 : }
691 :
692 : void
693 5 : TypeCheckType::visit (HIR::ParenthesisedType &type)
694 : {
695 : // I think this really needs to be a tuple.. but will sort that out when we
696 : // fix the parser issue
697 5 : translated = TypeCheckType::Resolve (type.get_type_in_parens ());
698 5 : }
699 :
700 : void
701 800 : TypeCheckType::visit (HIR::ArrayType &type)
702 : {
703 800 : auto element_type = TypeCheckType::Resolve (type.get_element_type ());
704 800 : context->push_const_context ();
705 800 : auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
706 799 : context->pop_const_context ();
707 :
708 799 : if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
709 0 : return;
710 :
711 799 : TyTy::BaseType *expected_ty = nullptr;
712 799 : bool ok = context->lookup_builtin ("usize", &expected_ty);
713 799 : rust_assert (ok);
714 :
715 799 : TyTy::BaseConstType *const_type = nullptr;
716 799 : if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
717 : {
718 43 : const_type = capacity_type->as_const_type ();
719 :
720 86 : unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
721 43 : TyTy::TyWithLocation (expected_ty),
722 : TyTy::TyWithLocation (const_type->get_specified_type (),
723 43 : type.get_size_expr ().get_locus ()),
724 43 : type.get_size_expr ().get_locus ());
725 : }
726 : else
727 : {
728 756 : HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
729 756 : TyTy::BaseType *result
730 1512 : = unify_site (size_id, TyTy::TyWithLocation (expected_ty),
731 : TyTy::TyWithLocation (capacity_type,
732 756 : type.get_size_expr ().get_locus ()),
733 756 : type.get_size_expr ().get_locus ());
734 :
735 756 : if (result->is<TyTy::ErrorType> ())
736 2 : const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id);
737 : else
738 : {
739 754 : auto ctx = Compile::Context::get ();
740 754 : tree capacity_expr
741 754 : = Compile::HIRCompileBase::query_compile_const_expr (
742 : ctx, capacity_type, type.get_size_expr ());
743 :
744 754 : const_type = new TyTy::ConstValueType (capacity_expr, expected_ty,
745 1508 : size_id, size_id);
746 : }
747 :
748 756 : context->insert_type (type.get_size_expr ().get_mappings (),
749 756 : const_type->as_base_type ());
750 : }
751 :
752 799 : translated
753 799 : = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
754 : TyTy::TyVar (
755 799 : const_type->as_base_type ()->get_ref ()),
756 2397 : TyTy::TyVar (element_type->get_ref ()));
757 : }
758 :
759 : void
760 916 : TypeCheckType::visit (HIR::SliceType &type)
761 : {
762 916 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
763 916 : translated
764 916 : = new TyTy::SliceType (type.get_mappings ().get_hirid (), type.get_locus (),
765 1832 : TyTy::TyVar (base->get_ref ()));
766 916 : }
767 : void
768 4717 : TypeCheckType::visit (HIR::ReferenceType &type)
769 : {
770 4717 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
771 4717 : rust_assert (type.has_lifetime ());
772 4717 : auto region = context->lookup_and_resolve_lifetime (type.get_lifetime ());
773 4717 : if (!region.has_value ())
774 : {
775 2 : rust_error_at (type.get_locus (), "failed to resolve lifetime");
776 2 : translated = new TyTy::ErrorType (type.get_mappings ().get_hirid ());
777 2 : return;
778 : }
779 14145 : translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (),
780 4715 : TyTy::TyVar (base->get_ref ()),
781 9430 : type.get_mut (), region.value ());
782 : }
783 :
784 : void
785 7116 : TypeCheckType::visit (HIR::RawPointerType &type)
786 : {
787 7116 : TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
788 7116 : translated
789 14232 : = new TyTy::PointerType (type.get_mappings ().get_hirid (),
790 7116 : TyTy::TyVar (base->get_ref ()), type.get_mut ());
791 7116 : }
792 :
793 : void
794 227 : TypeCheckType::visit (HIR::InferredType &type)
795 : {
796 454 : translated = new TyTy::InferType (type.get_mappings ().get_hirid (),
797 : TyTy::InferType::InferTypeKind::GENERAL,
798 : TyTy::InferType::TypeHint::Default (),
799 454 : type.get_locus ());
800 227 : }
801 :
802 : void
803 198 : TypeCheckType::visit (HIR::NeverType &type)
804 : {
805 198 : TyTy::BaseType *lookup = nullptr;
806 198 : bool ok = context->lookup_builtin ("!", &lookup);
807 198 : rust_assert (ok);
808 :
809 198 : translated = lookup->clone ();
810 198 : }
811 :
812 : void
813 41 : TypeCheckType::visit (HIR::ImplTraitType &type)
814 : {
815 41 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
816 85 : for (auto &bound : type.get_type_param_bounds ())
817 : {
818 44 : if (bound->get_bound_type ()
819 : != HIR::TypeParamBound::BoundType::TRAITBOUND)
820 2 : continue;
821 :
822 42 : HIR::TypeParamBound &b = *bound.get ();
823 42 : HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
824 :
825 42 : auto binder_pin = context->push_lifetime_binder ();
826 42 : for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
827 : {
828 0 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
829 : }
830 :
831 42 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
832 : trait_bound.get_path (),
833 42 : tl::nullopt /*this will setup a PLACEHOLDER for self*/);
834 :
835 42 : if (!predicate.is_error ()
836 42 : && predicate.is_object_safe (true, type.get_locus ()))
837 42 : specified_bounds.push_back (std::move (predicate));
838 42 : }
839 :
840 123 : translated = new TyTy::OpaqueType (type.get_locus (),
841 41 : type.get_mappings ().get_hirid (),
842 41 : specified_bounds);
843 41 : }
844 :
845 : TyTy::ParamType *
846 12924 : TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m,
847 : bool resolve_trait_bounds, bool apply_sized)
848 : {
849 12924 : TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
850 12924 : switch (param.get_kind ())
851 : {
852 12924 : case HIR::GenericParam::GenericKind::TYPE:
853 12924 : resolver.visit (static_cast<HIR::TypeParam &> (param));
854 12924 : break;
855 :
856 0 : case HIR::GenericParam::GenericKind::CONST:
857 0 : resolver.visit (static_cast<HIR::ConstGenericParam &> (param));
858 0 : break;
859 :
860 0 : case HIR::GenericParam::GenericKind::LIFETIME:
861 0 : resolver.visit (static_cast<HIR::LifetimeParam &> (param));
862 0 : break;
863 : }
864 12924 : return resolver.resolved;
865 12924 : }
866 :
867 : void
868 8044 : TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam ¶m,
869 : TyTy::ParamType *pty)
870 : {
871 8044 : TypeResolveGenericParam resolver (true, true);
872 8044 : resolver.apply_trait_bounds (param, pty);
873 8044 : }
874 :
875 : void
876 0 : TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m)
877 : {
878 : // nothing to do
879 0 : }
880 :
881 : void
882 0 : TypeResolveGenericParam::visit (HIR::ConstGenericParam ¶m)
883 : {
884 : // TODO
885 0 : }
886 :
887 : void
888 12924 : TypeResolveGenericParam::visit (HIR::TypeParam ¶m)
889 : {
890 12924 : if (param.has_type ())
891 408 : TypeCheckType::Resolve (param.get_type ());
892 :
893 25848 : resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
894 : param.get_locus (),
895 12924 : param.get_mappings ().get_hirid (),
896 38772 : param.get_mappings ().get_hirid (), {});
897 :
898 12924 : if (resolve_trait_bounds)
899 4986 : apply_trait_bounds (param, resolved);
900 12924 : }
901 :
902 : void
903 13030 : TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m,
904 : TyTy::ParamType *pty)
905 : {
906 13030 : std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
907 13030 : if (param.has_type_param_bounds ())
908 : {
909 : // We need two possible parameter types. One with no Bounds and one with
910 : // the bounds. the Self type for the bounds cannot itself contain the
911 : // bounds otherwise it will be a trait cycle
912 1380 : HirId implicit_id = mappings.get_next_hir_id ();
913 1380 : TyTy::ParamType *p
914 1380 : = new TyTy::ParamType (param.get_type_representation ().as_string (),
915 : param.get_locus (), implicit_id,
916 : pty->get_decl_id (),
917 2760 : {} /*empty specified bounds*/);
918 1380 : context->insert_implicit_type (implicit_id, p);
919 :
920 : // generate an implicit HIR Type we can apply to the predicate
921 1380 : Analysis::NodeMapping mappings (param.get_mappings ().get_crate_num (),
922 1380 : param.get_mappings ().get_nodeid (),
923 : implicit_id,
924 1380 : param.get_mappings ().get_local_defid ());
925 2760 : implicit_self_bound = std::make_unique<HIR::TypePath> (
926 4140 : HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false));
927 : }
928 :
929 13030 : std::map<DefId, std::vector<TyTy::TypeBoundPredicate>> predicates;
930 :
931 : // https://doc.rust-lang.org/std/marker/trait.Sized.html
932 : // All type parameters have an implicit bound of Sized. The special syntax
933 : // ?Sized can be used to remove this bound if it’s not appropriate.
934 : //
935 : // We can only do this when we are not resolving the implicit Self for Sized
936 : // itself
937 13030 : if (apply_sized)
938 : {
939 8773 : TyTy::TypeBoundPredicate sized_predicate
940 8773 : = get_marker_predicate (LangItem::Kind::SIZED, param.get_locus ());
941 :
942 17546 : predicates[sized_predicate.get_id ()] = {sized_predicate};
943 8773 : }
944 :
945 : // resolve the bounds
946 13030 : if (param.has_type_param_bounds ())
947 : {
948 2824 : for (auto &bound : param.get_type_param_bounds ())
949 : {
950 1444 : switch (bound->get_bound_type ())
951 : {
952 1444 : case HIR::TypeParamBound::BoundType::TRAITBOUND:
953 1444 : {
954 1444 : HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound);
955 :
956 1444 : TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
957 : b.get_path (),
958 : tl::optional<std::reference_wrapper<HIR::Type>> (
959 1444 : std::ref (*implicit_self_bound)),
960 1444 : b.get_polarity ());
961 1444 : if (!predicate.is_error ())
962 : {
963 1443 : switch (predicate.get_polarity ())
964 : {
965 534 : case BoundPolarity::AntiBound:
966 534 : {
967 534 : bool found = predicates.find (predicate.get_id ())
968 534 : != predicates.end ();
969 534 : if (found)
970 534 : predicates.erase (predicate.get_id ());
971 : else
972 : {
973 : // emit error message
974 0 : rich_location r (line_table, b.get_locus ());
975 0 : r.add_range (predicate.get ()->get_locus ());
976 0 : rust_error_at (
977 : r, "antibound for %s is not applied here",
978 0 : predicate.get ()->get_name ().c_str ());
979 0 : }
980 : }
981 : break;
982 :
983 909 : default:
984 909 : {
985 909 : if (predicates.find (predicate.get_id ())
986 909 : == predicates.end ())
987 : {
988 900 : predicates[predicate.get_id ()] = {};
989 : }
990 909 : predicates[predicate.get_id ()].push_back (predicate);
991 : }
992 909 : break;
993 : }
994 : }
995 1444 : }
996 1444 : break;
997 :
998 : default:
999 : break;
1000 : }
1001 : }
1002 : }
1003 :
1004 : // now to flat map the specified_bounds into the raw specified predicates
1005 13030 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
1006 22169 : for (auto it = predicates.begin (); it != predicates.end (); it++)
1007 : {
1008 18287 : for (const auto &predicate : it->second)
1009 : {
1010 9148 : specified_bounds.push_back (predicate);
1011 : }
1012 : }
1013 :
1014 : // inherit them
1015 13030 : pty->inherit_bounds (specified_bounds);
1016 13030 : }
1017 :
1018 : void
1019 2 : ResolveWhereClauseItem::Resolve (HIR::WhereClauseItem &item,
1020 : TyTy::RegionConstraints ®ion_constraints)
1021 : {
1022 2 : ResolveWhereClauseItem resolver (region_constraints);
1023 :
1024 2 : auto binder_pin = resolver.context->push_lifetime_binder ();
1025 :
1026 2 : switch (item.get_item_type ())
1027 : {
1028 2 : case HIR::WhereClauseItem::LIFETIME:
1029 2 : resolver.visit (static_cast<HIR::LifetimeWhereClauseItem &> (item));
1030 2 : break;
1031 :
1032 0 : case HIR::WhereClauseItem::TYPE_BOUND:
1033 0 : resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (item));
1034 0 : break;
1035 : }
1036 2 : }
1037 :
1038 : void
1039 60444 : ResolveWhereClauseItem::Resolve (HIR::WhereClause &clause,
1040 : TyTy::RegionConstraints ®ion_constraints)
1041 : {
1042 60444 : ResolveWhereClauseItem resolver (region_constraints);
1043 :
1044 60444 : class PlainTypePath : public HIR::HIRTypeVisitor
1045 : {
1046 : public:
1047 : bool matches = false;
1048 :
1049 0 : void visit (HIR::TypePathSegmentFunction &segment) override {}
1050 0 : void visit (HIR::QualifiedPathInType &path) override {}
1051 0 : void visit (HIR::TraitBound &bound) override {}
1052 0 : void visit (HIR::ImplTraitType &type) override {}
1053 0 : void visit (HIR::TraitObjectType &type) override {}
1054 0 : void visit (HIR::ParenthesisedType &type) override {}
1055 0 : void visit (HIR::TupleType &type) override {}
1056 0 : void visit (HIR::NeverType &type) override {}
1057 0 : void visit (HIR::RawPointerType &type) override {}
1058 0 : void visit (HIR::ReferenceType &type) override {}
1059 0 : void visit (HIR::ArrayType &type) override {}
1060 0 : void visit (HIR::SliceType &type) override {}
1061 0 : void visit (HIR::InferredType &type) override {}
1062 0 : void visit (HIR::BareFunctionType &type) override {}
1063 :
1064 684 : void visit (HIR::TypePath &path) override
1065 : {
1066 684 : bool is_single = path.get_segments ().size () == 1;
1067 684 : bool final_seg_is_reg
1068 684 : = path.get_final_segment ().get_type () == HIR::TypePathSegment::REG;
1069 :
1070 684 : matches = is_single && final_seg_is_reg;
1071 684 : }
1072 : };
1073 :
1074 60444 : resolver.defer_bindings = true;
1075 61130 : for (auto &item : clause.get_items ())
1076 686 : if (item->get_item_type () == HIR::WhereClauseItem::TYPE_BOUND)
1077 : {
1078 684 : auto &bound = static_cast<HIR::TypeBoundWhereClauseItem &> (*item);
1079 684 : PlainTypePath plain;
1080 684 : bound.get_bound_type ().accept_vis (plain);
1081 684 : if (plain.matches)
1082 676 : resolver.visit (bound);
1083 : }
1084 :
1085 60444 : resolver.defer_bindings = false;
1086 60444 : resolver.complete_bindings = true;
1087 61130 : for (auto &item : clause.get_items ())
1088 : {
1089 686 : if (item->get_item_type () == HIR::WhereClauseItem::TYPE_BOUND)
1090 684 : resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (*item));
1091 : else
1092 2 : Resolve (*item, region_constraints);
1093 : }
1094 60444 : }
1095 :
1096 : void
1097 2 : ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &item)
1098 : {
1099 2 : auto lhs = context->lookup_and_resolve_lifetime (item.get_lifetime ());
1100 2 : if (!lhs.has_value ())
1101 : {
1102 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
1103 : }
1104 4 : for (auto &lifetime : item.get_lifetime_bounds ())
1105 : {
1106 2 : auto rhs_i = context->lookup_and_resolve_lifetime (lifetime);
1107 2 : if (!rhs_i.has_value ())
1108 : {
1109 0 : rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
1110 : }
1111 2 : region_constraints.region_region.emplace_back (lhs.value (),
1112 : rhs_i.value ());
1113 : }
1114 2 : }
1115 :
1116 : void
1117 1360 : ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
1118 : {
1119 1360 : auto binder_pin = context->push_lifetime_binder ();
1120 1360 : if (item.has_for_lifetimes ())
1121 : {
1122 28 : for (auto &lifetime_param : item.get_for_lifetimes ())
1123 : {
1124 14 : context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
1125 : }
1126 : }
1127 :
1128 1360 : auto &binding_type_path = item.get_bound_type ();
1129 1360 : TyTy::BaseType *binding
1130 1360 : = TypeCheckType::Resolve (binding_type_path,
1131 : TypeCheckType::ResolutionMode::CANONICAL);
1132 :
1133 1360 : if (defer_bindings && binding->get_kind () != TyTy::TypeKind::PARAM)
1134 1 : return;
1135 :
1136 : // FIXME double check there might be a trait cycle here see TypeParam handling
1137 :
1138 1359 : std::vector<TyTy::TypeBoundPredicate> specified_bounds;
1139 2718 : for (auto &bound : item.get_type_param_bounds ())
1140 : {
1141 1359 : switch (bound->get_bound_type ())
1142 : {
1143 1351 : case HIR::TypeParamBound::BoundType::TRAITBOUND:
1144 1351 : {
1145 1351 : auto *b = static_cast<HIR::TraitBound *> (bound.get ());
1146 :
1147 1351 : TyTy::TypeBoundPredicate predicate
1148 1351 : = get_predicate_from_bound (b->get_path (), binding_type_path,
1149 : BoundPolarity::RegularBound, false,
1150 1351 : false, defer_bindings);
1151 1351 : if (!predicate.is_error ())
1152 1351 : specified_bounds.push_back (std::move (predicate));
1153 1351 : }
1154 1351 : break;
1155 8 : case HIR::TypeParamBound::BoundType::LIFETIME:
1156 8 : {
1157 8 : if (defer_bindings)
1158 : break;
1159 8 : if (auto param = binding->try_as<TyTy::ParamType> ())
1160 : {
1161 4 : auto *b = static_cast<HIR::Lifetime *> (bound.get ());
1162 4 : auto region = context->lookup_and_resolve_lifetime (*b);
1163 4 : if (!region.has_value ())
1164 : {
1165 0 : rust_error_at (UNKNOWN_LOCATION,
1166 : "failed to resolve lifetime");
1167 : }
1168 4 : region_constraints.type_region.emplace_back (param,
1169 : region.value ());
1170 : }
1171 : }
1172 4 : break;
1173 :
1174 : default:
1175 : break;
1176 : }
1177 : }
1178 :
1179 2710 : for (const auto &predicate : specified_bounds)
1180 : {
1181 1351 : bool replaced = false;
1182 1351 : if (complete_bindings)
1183 : {
1184 1758 : for (auto &bound : binding->get_specified_bounds ())
1185 : {
1186 3270 : if (bound.get_id () == predicate.get_id ()
1187 671 : && bound.get_locus () == predicate.get_locus ())
1188 : {
1189 557 : bound = predicate;
1190 557 : replaced = true;
1191 557 : break;
1192 : }
1193 : }
1194 : }
1195 :
1196 557 : if (!replaced)
1197 794 : binding->inherit_bound (predicate);
1198 : }
1199 1360 : }
1200 :
1201 : } // namespace Resolver
1202 : } // namespace Rust
|