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-dot-operator.h"
20 : #include "rust-hir-path-probe.h"
21 : #include "rust-hir-trait-resolve.h"
22 : #include "rust-hir-type-check-item.h"
23 : #include "rust-type-util.h"
24 : #include "rust-coercion.h"
25 :
26 : namespace Rust {
27 : namespace Resolver {
28 :
29 6444 : MethodResolver::MethodResolver (bool autoderef_flag,
30 : const HIR::PathIdentSegment &segment_name,
31 : const HIR::Trait *specified_trait)
32 6444 : : AutoderefCycle (autoderef_flag), segment_name (segment_name),
33 6444 : specified_trait (specified_trait), result ()
34 6444 : {}
35 :
36 : std::set<MethodCandidate>
37 6444 : MethodResolver::Probe (TyTy::BaseType *receiver,
38 : const HIR::PathIdentSegment &segment_name,
39 : bool autoderef_flag, const HIR::Trait *specified_trait)
40 : {
41 6444 : MethodResolver resolver (autoderef_flag, segment_name, specified_trait);
42 6444 : resolver.cycle (receiver);
43 6444 : return resolver.result;
44 6444 : }
45 :
46 : std::set<MethodCandidate>
47 3213 : MethodResolver::Select (std::set<MethodCandidate> &candidates,
48 : TyTy::BaseType *receiver,
49 : std::vector<TyTy::BaseType *> arguments,
50 : TyTy::BaseType *result_type)
51 : {
52 3213 : std::set<MethodCandidate> selected;
53 5184 : for (auto &candidate : candidates)
54 : {
55 1971 : TyTy::BaseType *candidate_type = candidate.candidate.ty;
56 1971 : rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
57 1971 : if (candidate_type == nullptr
58 1971 : || candidate_type->get_kind () != TyTy::TypeKind::FNDEF)
59 0 : continue;
60 1971 : TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type);
61 :
62 : // match the number of arguments
63 1971 : if (fn.num_params () != (arguments.size () + 1))
64 0 : continue;
65 :
66 : // match the arguments
67 3511 : bool failed = false;
68 3511 : for (size_t i = 0; i < arguments.size (); i++)
69 : {
70 1637 : TyTy::BaseType *arg = arguments.at (i);
71 1637 : TyTy::BaseType *param = fn.get_params ().at (i + 1).get_type ();
72 1637 : TyTy::BaseType *coerced
73 1637 : = try_coercion (0, TyTy::TyWithLocation (param),
74 1637 : TyTy::TyWithLocation (arg), UNDEF_LOCATION);
75 1637 : if (coerced->get_kind () == TyTy::TypeKind::ERROR)
76 : {
77 : failed = true;
78 : break;
79 : }
80 : }
81 :
82 1971 : if (!failed && result_type != nullptr)
83 : {
84 96 : TyTy::BaseType *return_type = fn.get_return_type ();
85 96 : rust_debug ("method candidate output check fn=%s expected=%s "
86 : "return=%s",
87 : fn.debug_str ().c_str (),
88 : result_type->debug_str ().c_str (),
89 : return_type->debug_str ().c_str ());
90 96 : failed = !types_compatable (TyTy::TyWithLocation (result_type),
91 96 : TyTy::TyWithLocation (return_type),
92 : UNDEF_LOCATION, false /* emit_errors */);
93 96 : rust_debug ("method candidate output check result=%s",
94 : failed ? "rejected" : "accepted");
95 : }
96 :
97 1971 : if (!failed)
98 1793 : selected.insert (candidate);
99 : }
100 :
101 3213 : return selected;
102 : }
103 :
104 : void
105 6687 : MethodResolver::try_hook (const TyTy::BaseType &r)
106 : {
107 6687 : rust_debug ("MethodResolver::try_hook get_predicate_items: [%s]",
108 : r.debug_str ().c_str ());
109 6687 : auto specified_bounds = context->predicates_for_type (&r);
110 6687 : predicate_items = get_predicate_items (segment_name, r, specified_bounds);
111 :
112 6687 : if (predicate_items.size () > 0)
113 298 : return;
114 :
115 6389 : if (r.get_kind () == TyTy::TypeKind::REF)
116 : {
117 3045 : const auto &ref = static_cast<const TyTy::ReferenceType &> (r);
118 3045 : const auto &element = ref.get_var_element_type ();
119 3045 : const auto &element_ty = *element.get_tyty ();
120 3045 : auto specified_bounds = context->predicates_for_type (&element_ty);
121 3045 : predicate_items
122 3045 : = get_predicate_items (segment_name, element_ty, specified_bounds);
123 3045 : }
124 3344 : else if (auto inner
125 3344 : = TyTy::try_get_box_inner_type (const_cast<TyTy::BaseType *> (&r)))
126 : {
127 7 : auto specified_bounds = context->predicates_for_type (*inner);
128 7 : predicate_items
129 7 : = get_predicate_items (segment_name, **inner, specified_bounds);
130 7 : }
131 6687 : }
132 :
133 : std::vector<MethodResolver::impl_item_candidate>
134 3239 : MethodResolver::assemble_inherent_impl_candidates (
135 : const TyTy::BaseType &receiver)
136 : {
137 3239 : std::vector<impl_item_candidate> inherent_impl_fns;
138 3239 : const TyTy::BaseType *raw = receiver.destructure ();
139 3239 : bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
140 3239 : bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
141 :
142 : // Assemble inherent impl items (non-trait impl blocks).
143 3239 : mappings.iterate_inherent_impl_items (
144 3239 : segment_name.to_string (),
145 3239 : [&] (HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
146 7206 : HIR::Function *func = static_cast<HIR::Function *> (item);
147 :
148 7206 : TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl);
149 :
150 7206 : if (impl_self == nullptr
151 7206 : || impl_self->get_kind () == TyTy::TypeKind::ERROR)
152 : return true;
153 :
154 7206 : if (receiver.get_kind () == TyTy::TypeKind::ADT
155 7206 : && impl_self->get_kind () == TyTy::TypeKind::ADT)
156 : {
157 343 : const auto &receiver_adt
158 : = static_cast<const TyTy::ADTType &> (receiver);
159 343 : const auto &impl_adt
160 : = static_cast<const TyTy::ADTType &> (*impl_self);
161 656 : if (receiver_adt.get_id () != impl_adt.get_id ())
162 30 : return true;
163 : }
164 :
165 : // see:
166 : // https://gcc-rust.zulipchat.com/#narrow/stream/266897-general/topic/Method.20Resolution/near/338646280
167 : // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L650-L660
168 7176 : bool impl_self_is_ptr = impl_self->get_kind () == TyTy::TypeKind::POINTER;
169 7176 : bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
170 7176 : if (receiver_is_raw_ptr && impl_self_is_ptr)
171 : {
172 573 : const TyTy::PointerType &sptr
173 : = *static_cast<const TyTy::PointerType *> (impl_self);
174 573 : const TyTy::PointerType &ptr
175 573 : = *static_cast<const TyTy::PointerType *> (raw);
176 :
177 : // we could do this via lang-item assemblies if we refactor this
178 573 : bool mut_match = sptr.mutability () == ptr.mutability ();
179 573 : if (!mut_match)
180 : return true;
181 : }
182 6603 : else if (receiver_is_ref && impl_self_is_ref)
183 : {
184 0 : const TyTy::ReferenceType &sptr
185 : = *static_cast<const TyTy::ReferenceType *> (impl_self);
186 0 : const TyTy::ReferenceType &ptr
187 0 : = *static_cast<const TyTy::ReferenceType *> (raw);
188 :
189 : // we could do this via lang-item assemblies if we refactor this
190 0 : bool mut_match = sptr.mutability () == ptr.mutability ();
191 0 : if (!mut_match)
192 : return true;
193 : }
194 :
195 7035 : TyTy::BaseType *ty = nullptr;
196 7035 : if (!query_type (func->get_mappings ().get_hirid (), &ty))
197 : return true;
198 7035 : if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
199 : return true;
200 7035 : if (ty->get_kind () != TyTy::TypeKind::FNDEF)
201 : return true;
202 :
203 7035 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
204 7035 : inherent_impl_fns.emplace_back (func, impl, fnty);
205 7035 : return true;
206 : });
207 :
208 3239 : return inherent_impl_fns;
209 : }
210 :
211 : void
212 5095 : MethodResolver::assemble_trait_impl_candidates (
213 : const TyTy::BaseType &receiver,
214 : std::vector<impl_item_candidate> &impl_candidates,
215 : std::vector<trait_item_candidate> &trait_candidates)
216 : {
217 5095 : const TyTy::BaseType *raw = receiver.destructure ();
218 5095 : bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
219 5095 : bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
220 :
221 22300 : auto process_impl = [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
222 17205 : bool is_trait_impl = impl->has_trait_ref ();
223 17205 : if (!is_trait_impl)
224 : return true;
225 :
226 : // look for impl implementation else lookup the associated trait item
227 33089 : for (auto &impl_item : impl->get_impl_items ())
228 : {
229 31305 : bool is_fn = impl_item->get_impl_item_type ()
230 31305 : == HIR::ImplItem::ImplItemType::FUNCTION;
231 31305 : if (!is_fn)
232 15884 : continue;
233 :
234 22254 : HIR::Function *func = static_cast<HIR::Function *> (impl_item.get ());
235 22254 : if (!func->is_method ())
236 0 : continue;
237 :
238 22254 : bool name_matches = func->get_function_name ().as_string ().compare (
239 44508 : segment_name.to_string ())
240 22254 : == 0;
241 22254 : if (!name_matches)
242 6563 : continue;
243 :
244 15691 : TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl);
245 :
246 15691 : if (impl_self == nullptr
247 15691 : || impl_self->get_kind () == TyTy::TypeKind::ERROR)
248 0 : continue;
249 :
250 15691 : if (receiver.get_kind () == TyTy::TypeKind::ADT
251 15691 : && impl_self->get_kind () == TyTy::TypeKind::ADT)
252 : {
253 555 : const auto &receiver_adt
254 : = static_cast<const TyTy::ADTType &> (receiver);
255 555 : const auto &impl_adt
256 : = static_cast<const TyTy::ADTType &> (*impl_self);
257 961 : if (receiver_adt.get_id () != impl_adt.get_id ())
258 149 : continue;
259 : }
260 :
261 : // see:
262 : // https://gcc-rust.zulipchat.com/#narrow/stream/266897-general/topic/Method.20Resolution/near/338646280
263 : // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L650-L660
264 15542 : bool impl_self_is_ptr
265 15542 : = impl_self->get_kind () == TyTy::TypeKind::POINTER;
266 15542 : bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
267 15542 : if (receiver_is_raw_ptr && impl_self_is_ptr)
268 : {
269 0 : const TyTy::PointerType &sptr
270 : = *static_cast<const TyTy::PointerType *> (impl_self);
271 0 : const TyTy::PointerType &ptr
272 0 : = *static_cast<const TyTy::PointerType *> (raw);
273 :
274 : // we could do this via lang-item assemblies if we refactor this
275 0 : bool mut_match = sptr.mutability () == ptr.mutability ();
276 0 : if (!mut_match)
277 0 : continue;
278 : }
279 15542 : else if (receiver_is_ref && impl_self_is_ref)
280 : {
281 295 : const TyTy::ReferenceType &sptr
282 : = *static_cast<const TyTy::ReferenceType *> (impl_self);
283 295 : const TyTy::ReferenceType &ptr
284 295 : = *static_cast<const TyTy::ReferenceType *> (raw);
285 :
286 : // we could do this via lang-item assemblies if we refactor this
287 295 : bool mut_match = sptr.mutability () == ptr.mutability ();
288 295 : if (!mut_match)
289 121 : continue;
290 : }
291 :
292 15421 : TyTy::BaseType *ty = nullptr;
293 15421 : if (!query_type (func->get_mappings ().get_hirid (), &ty))
294 0 : continue;
295 15421 : if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
296 0 : continue;
297 15421 : if (ty->get_kind () != TyTy::TypeKind::FNDEF)
298 0 : continue;
299 :
300 15421 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
301 :
302 15421 : impl_candidates.emplace_back (func, impl, fnty);
303 15421 : return true;
304 : }
305 :
306 1784 : TraitReference *trait_ref = TraitResolver::Resolve (impl->get_trait_ref ());
307 1784 : rust_assert (!trait_ref->is_error ());
308 :
309 1784 : auto item_ref
310 3568 : = trait_ref->lookup_trait_item (segment_name.to_string (),
311 1784 : TraitItemReference::TraitItemType::FN);
312 1784 : if (item_ref->is_error ())
313 : return true;
314 :
315 1448 : const HIR::Trait *trait = trait_ref->get_hir_trait_ref ();
316 1448 : HIR::TraitItem *item = item_ref->get_hir_trait_item ();
317 1448 : if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::FUNC)
318 : return true;
319 :
320 1448 : HIR::TraitItemFunc *func = static_cast<HIR::TraitItemFunc *> (item);
321 1448 : if (!func->get_decl ().is_method ())
322 : return true;
323 :
324 1448 : TyTy::BaseType *ty = item_ref->get_tyty ();
325 1448 : if (ty == nullptr || ty->get_kind () != TyTy::TypeKind::FNDEF)
326 : return true;
327 1448 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
328 :
329 1448 : trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref);
330 :
331 1448 : return true;
332 5095 : };
333 :
334 5095 : if (specified_trait == nullptr)
335 3142 : mappings.iterate_trait_impl_blocks_for_item (segment_name.to_string (),
336 3142 : process_impl);
337 : else
338 3524 : mappings.iterate_trait_impl_blocks (
339 7048 : specified_trait->get_mappings ().get_defid (), process_impl);
340 5095 : }
341 :
342 : bool
343 8246 : MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
344 : {
345 8246 : bool found_possible_candidate = false;
346 9734 : for (const auto &predicate : predicate_items)
347 : {
348 1488 : if (specified_trait != nullptr)
349 : {
350 284 : const TraitReference *parent = predicate.lookup.get_parent ()->get ();
351 284 : if (parent->get_mappings ().get_defid ()
352 568 : != specified_trait->get_mappings ().get_defid ())
353 0 : continue;
354 : }
355 :
356 1488 : const TyTy::FnType *fn = predicate.fntype;
357 2976 : if (!fn->is_method ())
358 0 : continue;
359 :
360 1488 : TyTy::BaseType *fn_self = fn->get_self_type ();
361 1488 : rust_debug ("dot-operator predicate fn_self={%s} can_eq receiver={%s}",
362 : fn_self->debug_str ().c_str (),
363 : receiver.debug_str ().c_str ());
364 :
365 1488 : auto res
366 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
367 : false /*allow-autoderef*/,
368 : false /*is_cast_site*/,
369 1488 : false /*allow_never_coercion*/);
370 1488 : bool ok = !res.is_error ();
371 1488 : if (ok)
372 : {
373 1339 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
374 1339 : const TraitReference *trait_ref
375 1339 : = predicate.lookup.get_parent ()->get ();
376 1339 : const TraitItemReference *trait_item
377 1339 : = predicate.lookup.get_raw_item ();
378 :
379 1339 : PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
380 1339 : nullptr};
381 1339 : auto try_result = MethodCandidate{
382 : PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
383 : fn->clone (), trait_item->get_locus (), c),
384 1339 : adjs};
385 1339 : result.insert (std::move (try_result));
386 1339 : found_possible_candidate = true;
387 1339 : }
388 1488 : }
389 8246 : return found_possible_candidate;
390 : }
391 :
392 : bool
393 8334 : MethodResolver::try_select_inherent_impl_candidates (
394 : TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates,
395 : bool trait_impl_blocks_only)
396 : {
397 8334 : bool found_possible_candidate = false;
398 30790 : for (auto &impl_item : candidates)
399 : {
400 22456 : bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
401 22456 : if (trait_impl_blocks_only && !is_trait_impl_block)
402 0 : continue;
403 22456 : if (!trait_impl_blocks_only && is_trait_impl_block)
404 0 : continue;
405 :
406 22456 : TyTy::FnType *fn = impl_item.ty;
407 44912 : if (!fn->is_method ())
408 0 : continue;
409 :
410 22456 : TyTy::BaseType *fn_self = fn->get_self_type ();
411 :
412 7035 : const char *debug_prefix
413 22456 : = trait_impl_blocks_only ? "trait_impl_item" : "impl_item";
414 22456 : rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}",
415 : debug_prefix, fn_self->debug_str ().c_str (),
416 : receiver.debug_str ().c_str ());
417 :
418 22456 : auto res
419 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
420 : false /*allow-autoderef*/,
421 : false /*is_cast_site*/,
422 22456 : false /*allow_never_coercion*/);
423 22456 : bool ok = !res.is_error ();
424 22456 : if (ok)
425 : {
426 5237 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
427 5237 : PathProbeCandidate::ImplItemCandidate c{impl_item.item,
428 5237 : impl_item.impl_block};
429 5237 : auto try_result = MethodCandidate{
430 : PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
431 5237 : fn, impl_item.item->get_locus (), c),
432 5237 : adjs};
433 5237 : result.insert (std::move (try_result));
434 5237 : found_possible_candidate = true;
435 5237 : }
436 22456 : }
437 8334 : return found_possible_candidate;
438 : }
439 :
440 : bool
441 1921 : MethodResolver::try_select_trait_impl_candidates (
442 : TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates)
443 : {
444 1921 : bool found_possible_candidate = false;
445 2298 : for (auto trait_item : candidates)
446 : {
447 377 : TyTy::FnType *fn = trait_item.ty;
448 754 : if (!fn->is_method ())
449 0 : continue;
450 :
451 377 : TyTy::BaseType *fn_self = fn->get_self_type ();
452 377 : rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}",
453 : fn_self->debug_str ().c_str (),
454 : receiver.debug_str ().c_str ());
455 :
456 377 : auto res
457 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
458 : false /*allow-autoderef*/,
459 : false /*is_cast_site*/,
460 377 : false /*allow_never_coercion*/);
461 377 : bool ok = !res.is_error ();
462 377 : if (ok)
463 : {
464 223 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
465 223 : PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
466 : trait_item.item_ref,
467 223 : nullptr};
468 223 : auto try_result = MethodCandidate{
469 : PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
470 223 : fn, trait_item.item->get_locus (), c),
471 223 : adjs};
472 223 : result.insert (std::move (try_result));
473 223 : found_possible_candidate = true;
474 223 : }
475 377 : }
476 1921 : return found_possible_candidate;
477 : }
478 :
479 : bool
480 8246 : MethodResolver::select (TyTy::BaseType &receiver)
481 : {
482 8246 : rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
483 : receiver.debug_str ().c_str (),
484 : segment_name.to_string ().c_str ());
485 :
486 : // Predicate candidates have the highest priority. Try them before
487 : // assembling impl candidates, which can trigger expensive trait resolution.
488 8246 : if (try_select_predicate_candidates (receiver))
489 : return true;
490 :
491 : // A receiver that is still a bare unresolved generic type parameter can only
492 : // ever satisfy a method through its own trait bounds
493 6907 : if (receiver.destructure ()->get_kind () == TyTy::TypeKind::PARAM)
494 : return false;
495 :
496 : // Assemble candidates
497 6763 : std::vector<impl_item_candidate> inherent_impl_fns;
498 6763 : if (specified_trait == nullptr)
499 : {
500 3239 : inherent_impl_fns = assemble_inherent_impl_candidates (receiver);
501 3239 : if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns,
502 : false))
503 : return true;
504 : }
505 :
506 5095 : std::vector<impl_item_candidate> trait_impl_fns;
507 5095 : std::vector<trait_item_candidate> trait_fns;
508 5095 : assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns);
509 :
510 : // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
511 :
512 5095 : rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
513 : "predicate_items found {%lu}",
514 : (unsigned long) inherent_impl_fns.size (),
515 : (unsigned long) trait_fns.size (),
516 : (unsigned long) predicate_items.size ());
517 :
518 : // Try selection in the priority order defined by Rust's method resolution:
519 :
520 : // 1. Try inherent impl functions from trait impl blocks
521 5095 : if (try_select_inherent_impl_candidates (receiver, trait_impl_fns, true))
522 : return true;
523 :
524 : // 2. Try trait functions (lowest priority)
525 1921 : return try_select_trait_impl_candidates (receiver, trait_fns);
526 11858 : }
527 :
528 : std::vector<MethodResolver::predicate_candidate>
529 9739 : MethodResolver::get_predicate_items (
530 : const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
531 : const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
532 : {
533 9739 : std::vector<predicate_candidate> predicate_items;
534 12219 : for (auto &bound : specified_bounds)
535 : {
536 2480 : tl::optional<TyTy::TypeBoundPredicateItem> lookup
537 2480 : = bound.lookup_associated_item (segment_name.to_string ());
538 2480 : if (!lookup.has_value ())
539 1136 : continue;
540 :
541 1344 : TyTy::BaseType *ty = lookup->get_tyty_for_receiver (&receiver);
542 1344 : if (ty->get_kind () == TyTy::TypeKind::FNDEF)
543 : {
544 1344 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
545 4028 : if (fnty->is_method ())
546 1340 : predicate_items.emplace_back (lookup.value (), fnty);
547 : }
548 2480 : }
549 :
550 9739 : return predicate_items;
551 : }
552 :
553 : std::vector<Adjustment>
554 6799 : MethodResolver::append_adjustments (const std::vector<Adjustment> &adjs) const
555 : {
556 6799 : std::vector<Adjustment> combined;
557 6799 : combined.reserve (adjustments.size () + adjs.size ());
558 :
559 7703 : for (const auto &a : adjustments)
560 904 : combined.push_back (a);
561 6890 : for (const auto &a : adjs)
562 91 : combined.push_back (a);
563 :
564 6799 : return combined;
565 : }
566 :
567 : } // namespace Resolver
568 : } // namespace Rust
|