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 6397 : MethodResolver::MethodResolver (bool autoderef_flag,
30 : const HIR::PathIdentSegment &segment_name,
31 : const HIR::Trait *specified_trait)
32 6397 : : AutoderefCycle (autoderef_flag), segment_name (segment_name),
33 6397 : specified_trait (specified_trait), result ()
34 6397 : {}
35 :
36 : std::set<MethodCandidate>
37 6397 : MethodResolver::Probe (TyTy::BaseType *receiver,
38 : const HIR::PathIdentSegment &segment_name,
39 : bool autoderef_flag, const HIR::Trait *specified_trait)
40 : {
41 6397 : MethodResolver resolver (autoderef_flag, segment_name, specified_trait);
42 6397 : resolver.cycle (receiver);
43 6397 : return resolver.result;
44 6397 : }
45 :
46 : std::set<MethodCandidate>
47 3178 : MethodResolver::Select (std::set<MethodCandidate> &candidates,
48 : TyTy::BaseType *receiver,
49 : std::vector<TyTy::BaseType *> arguments,
50 : TyTy::BaseType *result_type)
51 : {
52 3178 : std::set<MethodCandidate> selected;
53 5142 : for (auto &candidate : candidates)
54 : {
55 1964 : TyTy::BaseType *candidate_type = candidate.candidate.ty;
56 1964 : rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
57 1964 : if (candidate_type == nullptr
58 1964 : || candidate_type->get_kind () != TyTy::TypeKind::FNDEF)
59 0 : continue;
60 1964 : TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type);
61 :
62 : // match the number of arguments
63 1964 : if (fn.num_params () != (arguments.size () + 1))
64 0 : continue;
65 :
66 : // match the arguments
67 3497 : bool failed = false;
68 3497 : for (size_t i = 0; i < arguments.size (); i++)
69 : {
70 1630 : TyTy::BaseType *arg = arguments.at (i);
71 1630 : TyTy::BaseType *param = fn.get_params ().at (i + 1).get_type ();
72 1630 : TyTy::BaseType *coerced
73 1630 : = try_coercion (0, TyTy::TyWithLocation (param),
74 1630 : TyTy::TyWithLocation (arg), UNDEF_LOCATION);
75 1630 : if (coerced->get_kind () == TyTy::TypeKind::ERROR)
76 : {
77 : failed = true;
78 : break;
79 : }
80 : }
81 :
82 1964 : 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 1964 : if (!failed)
98 1786 : selected.insert (candidate);
99 : }
100 :
101 3178 : return selected;
102 : }
103 :
104 : void
105 6639 : MethodResolver::try_hook (const TyTy::BaseType &r)
106 : {
107 6639 : rust_debug ("MethodResolver::try_hook get_predicate_items: [%s]",
108 : r.debug_str ().c_str ());
109 6639 : const auto &specified_bounds = r.get_specified_bounds ();
110 6639 : predicate_items = get_predicate_items (segment_name, r, specified_bounds);
111 :
112 6639 : if (predicate_items.size () > 0)
113 : return;
114 :
115 6343 : if (r.get_kind () == TyTy::TypeKind::REF)
116 : {
117 3044 : const auto &ref = static_cast<const TyTy::ReferenceType &> (r);
118 3044 : const auto &element = ref.get_var_element_type ();
119 3044 : const auto &element_ty = *element.get_tyty ();
120 3044 : const auto &specified_bounds = element_ty.get_specified_bounds ();
121 3044 : predicate_items
122 3044 : = get_predicate_items (segment_name, element_ty, specified_bounds);
123 : }
124 3299 : else if (auto inner
125 3299 : = TyTy::try_get_box_inner_type (const_cast<TyTy::BaseType *> (&r)))
126 : {
127 7 : const auto &specified_bounds = (*inner)->get_specified_bounds ();
128 7 : predicate_items
129 7 : = get_predicate_items (segment_name, **inner, specified_bounds);
130 : }
131 : }
132 :
133 : std::vector<MethodResolver::impl_item_candidate>
134 3213 : MethodResolver::assemble_inherent_impl_candidates (
135 : const TyTy::BaseType &receiver)
136 : {
137 3213 : std::vector<impl_item_candidate> inherent_impl_fns;
138 3213 : const TyTy::BaseType *raw = receiver.destructure ();
139 3213 : bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
140 3213 : bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
141 :
142 : // Assemble inherent impl items (non-trait impl blocks).
143 3213 : mappings.iterate_inherent_impl_items (
144 3213 : segment_name.to_string (),
145 3213 : [&] (HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
146 7188 : HIR::Function *func = static_cast<HIR::Function *> (item);
147 :
148 7188 : TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl);
149 :
150 7188 : if (impl_self == nullptr
151 7188 : || impl_self->get_kind () == TyTy::TypeKind::ERROR)
152 : return true;
153 :
154 7188 : if (receiver.get_kind () == TyTy::TypeKind::ADT
155 7188 : && impl_self->get_kind () == TyTy::TypeKind::ADT)
156 : {
157 335 : const auto &receiver_adt
158 : = static_cast<const TyTy::ADTType &> (receiver);
159 335 : const auto &impl_adt
160 : = static_cast<const TyTy::ADTType &> (*impl_self);
161 640 : 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 7158 : bool impl_self_is_ptr = impl_self->get_kind () == TyTy::TypeKind::POINTER;
169 7158 : bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
170 7158 : 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 6585 : 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 7017 : TyTy::BaseType *ty = nullptr;
196 7017 : if (!query_type (func->get_mappings ().get_hirid (), &ty))
197 : return true;
198 7017 : if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
199 : return true;
200 7017 : if (ty->get_kind () != TyTy::TypeKind::FNDEF)
201 : return true;
202 :
203 7017 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
204 7017 : inherent_impl_fns.emplace_back (func, impl, fnty);
205 7017 : return true;
206 : });
207 :
208 3213 : return inherent_impl_fns;
209 : }
210 :
211 : void
212 4986 : 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 4986 : const TyTy::BaseType *raw = receiver.destructure ();
218 4986 : bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
219 4986 : bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
220 :
221 22080 : auto process_impl = [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
222 17094 : bool is_trait_impl = impl->has_trait_ref ();
223 17094 : if (!is_trait_impl)
224 : return true;
225 :
226 : // look for impl implementation else lookup the associated trait item
227 32869 : for (auto &impl_item : impl->get_impl_items ())
228 : {
229 31087 : bool is_fn = impl_item->get_impl_item_type ()
230 31087 : == HIR::ImplItem::ImplItemType::FUNCTION;
231 31087 : if (!is_fn)
232 15775 : continue;
233 :
234 22143 : HIR::Function *func = static_cast<HIR::Function *> (impl_item.get ());
235 22143 : if (!func->is_method ())
236 0 : continue;
237 :
238 22143 : bool name_matches = func->get_function_name ().as_string ().compare (
239 44286 : segment_name.to_string ())
240 22143 : == 0;
241 22143 : if (!name_matches)
242 6563 : continue;
243 :
244 15580 : TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl);
245 :
246 15580 : if (impl_self == nullptr
247 15580 : || impl_self->get_kind () == TyTy::TypeKind::ERROR)
248 0 : continue;
249 :
250 15580 : if (receiver.get_kind () == TyTy::TypeKind::ADT
251 15580 : && impl_self->get_kind () == TyTy::TypeKind::ADT)
252 : {
253 545 : const auto &receiver_adt
254 : = static_cast<const TyTy::ADTType &> (receiver);
255 545 : const auto &impl_adt
256 : = static_cast<const TyTy::ADTType &> (*impl_self);
257 943 : if (receiver_adt.get_id () != impl_adt.get_id ())
258 147 : 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 15433 : bool impl_self_is_ptr
265 15433 : = impl_self->get_kind () == TyTy::TypeKind::POINTER;
266 15433 : bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
267 15433 : 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 15433 : else if (receiver_is_ref && impl_self_is_ref)
280 : {
281 291 : const TyTy::ReferenceType &sptr
282 : = *static_cast<const TyTy::ReferenceType *> (impl_self);
283 291 : const TyTy::ReferenceType &ptr
284 291 : = *static_cast<const TyTy::ReferenceType *> (raw);
285 :
286 : // we could do this via lang-item assemblies if we refactor this
287 291 : bool mut_match = sptr.mutability () == ptr.mutability ();
288 291 : if (!mut_match)
289 121 : continue;
290 : }
291 :
292 15312 : TyTy::BaseType *ty = nullptr;
293 15312 : if (!query_type (func->get_mappings ().get_hirid (), &ty))
294 0 : continue;
295 15312 : if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
296 0 : continue;
297 15312 : if (ty->get_kind () != TyTy::TypeKind::FNDEF)
298 0 : continue;
299 :
300 15312 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
301 :
302 15312 : impl_candidates.emplace_back (func, impl, fnty);
303 15312 : return true;
304 : }
305 :
306 1782 : TraitReference *trait_ref = TraitResolver::Resolve (impl->get_trait_ref ());
307 1782 : rust_assert (!trait_ref->is_error ());
308 :
309 1782 : auto item_ref
310 3564 : = trait_ref->lookup_trait_item (segment_name.to_string (),
311 1782 : TraitItemReference::TraitItemType::FN);
312 1782 : if (item_ref->is_error ())
313 : return true;
314 :
315 1446 : const HIR::Trait *trait = trait_ref->get_hir_trait_ref ();
316 1446 : HIR::TraitItem *item = item_ref->get_hir_trait_item ();
317 1446 : if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::FUNC)
318 : return true;
319 :
320 1446 : HIR::TraitItemFunc *func = static_cast<HIR::TraitItemFunc *> (item);
321 1446 : if (!func->get_decl ().is_method ())
322 : return true;
323 :
324 1446 : TyTy::BaseType *ty = item_ref->get_tyty ();
325 1446 : if (ty == nullptr || ty->get_kind () != TyTy::TypeKind::FNDEF)
326 : return true;
327 1446 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
328 :
329 1446 : trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref);
330 :
331 1446 : return true;
332 4986 : };
333 :
334 4986 : if (specified_trait == nullptr)
335 3106 : mappings.iterate_trait_impl_blocks_for_item (segment_name.to_string (),
336 3106 : process_impl);
337 : else
338 3433 : mappings.iterate_trait_impl_blocks (
339 6866 : specified_trait->get_mappings ().get_defid (), process_impl);
340 4986 : }
341 :
342 : bool
343 8126 : MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
344 : {
345 8126 : bool found_possible_candidate = false;
346 9608 : for (const auto &predicate : predicate_items)
347 : {
348 1482 : 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 1482 : const TyTy::FnType *fn = predicate.fntype;
357 2964 : if (!fn->is_method ())
358 0 : continue;
359 :
360 1482 : TyTy::BaseType *fn_self = fn->get_self_type ();
361 1482 : 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 1482 : auto res
366 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
367 1482 : false /*allow-autoderef*/);
368 1482 : bool ok = !res.is_error ();
369 1482 : if (ok)
370 : {
371 1337 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
372 1337 : const TraitReference *trait_ref
373 1337 : = predicate.lookup.get_parent ()->get ();
374 1337 : const TraitItemReference *trait_item
375 1337 : = predicate.lookup.get_raw_item ();
376 :
377 1337 : PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
378 1337 : nullptr};
379 1337 : auto try_result = MethodCandidate{
380 : PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
381 : fn->clone (), trait_item->get_locus (), c),
382 1337 : adjs};
383 1337 : result.insert (std::move (try_result));
384 1337 : found_possible_candidate = true;
385 1337 : }
386 1482 : }
387 8126 : return found_possible_candidate;
388 : }
389 :
390 : bool
391 8199 : MethodResolver::try_select_inherent_impl_candidates (
392 : TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates,
393 : bool trait_impl_blocks_only)
394 : {
395 8199 : bool found_possible_candidate = false;
396 30528 : for (auto &impl_item : candidates)
397 : {
398 22329 : bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
399 22329 : if (trait_impl_blocks_only && !is_trait_impl_block)
400 0 : continue;
401 22329 : if (!trait_impl_blocks_only && is_trait_impl_block)
402 0 : continue;
403 :
404 22329 : TyTy::FnType *fn = impl_item.ty;
405 44658 : if (!fn->is_method ())
406 0 : continue;
407 :
408 22329 : TyTy::BaseType *fn_self = fn->get_self_type ();
409 :
410 7017 : const char *debug_prefix
411 22329 : = trait_impl_blocks_only ? "trait_impl_item" : "impl_item";
412 22329 : rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}",
413 : debug_prefix, fn_self->debug_str ().c_str (),
414 : receiver.debug_str ().c_str ());
415 :
416 22329 : auto res
417 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
418 22329 : false /*allow-autoderef*/);
419 22329 : bool ok = !res.is_error ();
420 22329 : if (ok)
421 : {
422 5220 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
423 5220 : PathProbeCandidate::ImplItemCandidate c{impl_item.item,
424 5220 : impl_item.impl_block};
425 5220 : auto try_result = MethodCandidate{
426 : PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
427 5220 : fn, impl_item.item->get_locus (), c),
428 5220 : adjs};
429 5220 : result.insert (std::move (try_result));
430 5220 : found_possible_candidate = true;
431 5220 : }
432 22329 : }
433 8199 : return found_possible_candidate;
434 : }
435 :
436 : bool
437 1821 : MethodResolver::try_select_trait_impl_candidates (
438 : TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates)
439 : {
440 1821 : bool found_possible_candidate = false;
441 2196 : for (auto trait_item : candidates)
442 : {
443 375 : TyTy::FnType *fn = trait_item.ty;
444 750 : if (!fn->is_method ())
445 0 : continue;
446 :
447 375 : TyTy::BaseType *fn_self = fn->get_self_type ();
448 375 : rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}",
449 : fn_self->debug_str ().c_str (),
450 : receiver.debug_str ().c_str ());
451 :
452 375 : auto res
453 : = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
454 375 : false /*allow-autoderef*/);
455 375 : bool ok = !res.is_error ();
456 375 : if (ok)
457 : {
458 223 : std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
459 223 : PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
460 : trait_item.item_ref,
461 223 : nullptr};
462 223 : auto try_result = MethodCandidate{
463 : PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
464 223 : fn, trait_item.item->get_locus (), c),
465 223 : adjs};
466 223 : result.insert (std::move (try_result));
467 223 : found_possible_candidate = true;
468 223 : }
469 375 : }
470 1821 : return found_possible_candidate;
471 : }
472 :
473 : bool
474 8126 : MethodResolver::select (TyTy::BaseType &receiver)
475 : {
476 8126 : rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
477 : receiver.debug_str ().c_str (),
478 : segment_name.to_string ().c_str ());
479 :
480 : // Predicate candidates have the highest priority. Try them before
481 : // assembling impl candidates, which can trigger expensive trait resolution.
482 8126 : if (try_select_predicate_candidates (receiver))
483 : return true;
484 :
485 : // A receiver that is still a bare unresolved generic type parameter can only
486 : // ever satisfy a method through its own trait bounds
487 6789 : if (receiver.destructure ()->get_kind () == TyTy::TypeKind::PARAM)
488 : return false;
489 :
490 : // Assemble candidates
491 6646 : std::vector<impl_item_candidate> inherent_impl_fns;
492 6646 : if (specified_trait == nullptr)
493 : {
494 3213 : inherent_impl_fns = assemble_inherent_impl_candidates (receiver);
495 3213 : if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns,
496 : false))
497 : return true;
498 : }
499 :
500 4986 : std::vector<impl_item_candidate> trait_impl_fns;
501 4986 : std::vector<trait_item_candidate> trait_fns;
502 4986 : assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns);
503 :
504 : // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
505 :
506 4986 : rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
507 : "predicate_items found {%lu}",
508 : (unsigned long) inherent_impl_fns.size (),
509 : (unsigned long) trait_fns.size (),
510 : (unsigned long) predicate_items.size ());
511 :
512 : // Try selection in the priority order defined by Rust's method resolution:
513 :
514 : // 1. Try inherent impl functions from trait impl blocks
515 4986 : if (try_select_inherent_impl_candidates (receiver, trait_impl_fns, true))
516 : return true;
517 :
518 : // 2. Try trait functions (lowest priority)
519 1821 : return try_select_trait_impl_candidates (receiver, trait_fns);
520 11632 : }
521 :
522 : std::vector<MethodResolver::predicate_candidate>
523 9690 : MethodResolver::get_predicate_items (
524 : const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
525 : const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
526 : {
527 9690 : std::vector<predicate_candidate> predicate_items;
528 12165 : for (auto &bound : specified_bounds)
529 : {
530 2475 : tl::optional<TyTy::TypeBoundPredicateItem> lookup
531 2475 : = bound.lookup_associated_item (segment_name.to_string ());
532 2475 : if (!lookup.has_value ())
533 1133 : continue;
534 :
535 1342 : TyTy::BaseType *ty = lookup->get_tyty_for_receiver (&receiver);
536 1342 : if (ty->get_kind () == TyTy::TypeKind::FNDEF)
537 : {
538 1342 : TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
539 4022 : if (fnty->is_method ())
540 1338 : predicate_items.emplace_back (lookup.value (), fnty);
541 : }
542 2475 : }
543 :
544 9690 : return predicate_items;
545 : }
546 :
547 : std::vector<Adjustment>
548 6780 : MethodResolver::append_adjustments (const std::vector<Adjustment> &adjs) const
549 : {
550 6780 : std::vector<Adjustment> combined;
551 6780 : combined.reserve (adjustments.size () + adjs.size ());
552 :
553 7672 : for (const auto &a : adjustments)
554 892 : combined.push_back (a);
555 6871 : for (const auto &a : adjs)
556 91 : combined.push_back (a);
557 :
558 6780 : return combined;
559 : }
560 :
561 : } // namespace Resolver
562 : } // namespace Rust
|