1use std::assert_matches::debug_assert_matches;
2use std::cell::{Cell, RefCell};
3use std::cmp::max;
4use std::ops::Deref;
5
6use rustc_attr_parsing::is_doc_alias_attrs_contain_symbol;
7use rustc_data_structures::fx::FxHashSet;
8use rustc_data_structures::sso::SsoHashSet;
9use rustc_errors::Applicability;
10use rustc_hir as hir;
11use rustc_hir::HirId;
12use rustc_hir::def::DefKind;
13use rustc_hir_analysis::autoderef::{self, Autoderef};
14use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
15use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
16use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, query};
17use rustc_middle::middle::stability;
18use rustc_middle::ty::elaborate::supertrait_def_ids;
19use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
20use rustc_middle::ty::{
21 self, AssocContainer, AssocItem, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd,
22 Ty, TyCtxt, TypeVisitableExt, Upcast,
23};
24use rustc_middle::{bug, span_bug};
25use rustc_session::lint;
26use rustc_span::def_id::{DefId, LocalDefId};
27use rustc_span::edit_distance::{
28 edit_distance_with_substrings, find_best_match_for_name_with_substrings,
29};
30use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
31use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
32use rustc_trait_selection::infer::InferCtxtExt as _;
33use rustc_trait_selection::solve::Goal;
34use rustc_trait_selection::traits::query::CanonicalMethodAutoderefStepsGoal;
35use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
36use rustc_trait_selection::traits::query::method_autoderef::{
37 CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
38};
39use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
40use smallvec::{SmallVec, smallvec};
41use tracing::{debug, instrument};
42
43use self::CandidateKind::*;
44pub(crate) use self::PickKind::*;
45use super::{CandidateSource, MethodError, NoMatchData, suggest};
46use crate::FnCtxt;
47
48#[derive(Clone, Copy, Debug)]
51pub(crate) struct IsSuggestion(pub bool);
52
53pub(crate) struct ProbeContext<'a, 'tcx> {
54 fcx: &'a FnCtxt<'a, 'tcx>,
55 span: Span,
56 mode: Mode,
57 method_name: Option<Ident>,
58 return_type: Option<Ty<'tcx>>,
59
60 orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
63 steps: &'tcx [CandidateStep<'tcx>],
64
65 inherent_candidates: Vec<Candidate<'tcx>>,
66 extension_candidates: Vec<Candidate<'tcx>>,
67 impl_dups: FxHashSet<DefId>,
68
69 allow_similar_names: bool,
72
73 private_candidates: Vec<Candidate<'tcx>>,
76
77 private_candidate: Cell<Option<(DefKind, DefId)>>,
79
80 static_candidates: RefCell<Vec<CandidateSource>>,
83
84 scope_expr_id: HirId,
85
86 is_suggestion: IsSuggestion,
90}
91
92impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
93 type Target = FnCtxt<'a, 'tcx>;
94 fn deref(&self) -> &Self::Target {
95 self.fcx
96 }
97}
98
99#[derive(Debug, Clone)]
100pub(crate) struct Candidate<'tcx> {
101 pub(crate) item: ty::AssocItem,
102 pub(crate) kind: CandidateKind<'tcx>,
103 pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
104}
105
106#[derive(Debug, Clone)]
107pub(crate) enum CandidateKind<'tcx> {
108 InherentImplCandidate { impl_def_id: DefId, receiver_steps: usize },
109 ObjectCandidate(ty::PolyTraitRef<'tcx>),
110 TraitCandidate(ty::PolyTraitRef<'tcx>),
111 WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
112}
113
114#[derive(Debug, PartialEq, Eq, Copy, Clone)]
115enum ProbeResult {
116 NoMatch,
117 BadReturnType,
118 Match,
119}
120
121#[derive(Debug, PartialEq, Copy, Clone)]
134pub(crate) enum AutorefOrPtrAdjustment {
135 Autoref {
138 mutbl: hir::Mutability,
139
140 unsize: bool,
143 },
144 ToConstPtr,
146
147 ReborrowPin(hir::Mutability),
149}
150
151impl AutorefOrPtrAdjustment {
152 fn get_unsize(&self) -> bool {
153 match self {
154 AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
155 AutorefOrPtrAdjustment::ToConstPtr => false,
156 AutorefOrPtrAdjustment::ReborrowPin(_) => false,
157 }
158 }
159}
160
161#[derive(Debug)]
163struct PickDiagHints<'a, 'tcx> {
164 unstable_candidates: Option<Vec<(Candidate<'tcx>, Symbol)>>,
166
167 unsatisfied_predicates: &'a mut Vec<(
170 ty::Predicate<'tcx>,
171 Option<ty::Predicate<'tcx>>,
172 Option<ObligationCause<'tcx>>,
173 )>,
174}
175
176#[derive(Debug)]
180struct PickConstraintsForShadowed {
181 autoderefs: usize,
182 receiver_steps: Option<usize>,
183 def_id: DefId,
184}
185
186impl PickConstraintsForShadowed {
187 fn may_shadow_based_on_autoderefs(&self, autoderefs: usize) -> bool {
188 autoderefs == self.autoderefs
189 }
190
191 fn candidate_may_shadow(&self, candidate: &Candidate<'_>) -> bool {
192 candidate.item.def_id != self.def_id
194 && match candidate.kind {
198 CandidateKind::InherentImplCandidate { receiver_steps, .. } => match self.receiver_steps {
199 Some(shadowed_receiver_steps) => receiver_steps > shadowed_receiver_steps,
200 _ => false
201 },
202 _ => false
203 }
204 }
205}
206
207#[derive(Debug, Clone)]
208pub(crate) struct Pick<'tcx> {
209 pub item: ty::AssocItem,
210 pub kind: PickKind<'tcx>,
211 pub import_ids: SmallVec<[LocalDefId; 1]>,
212
213 pub autoderefs: usize,
218
219 pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment>,
222 pub self_ty: Ty<'tcx>,
223
224 unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
226
227 pub receiver_steps: Option<usize>,
231
232 pub shadowed_candidates: Vec<ty::AssocItem>,
234}
235
236#[derive(Clone, Debug, PartialEq, Eq)]
237pub(crate) enum PickKind<'tcx> {
238 InherentImplPick,
239 ObjectPick,
240 TraitPick,
241 WhereClausePick(
242 ty::PolyTraitRef<'tcx>,
244 ),
245}
246
247pub(crate) type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;
248
249#[derive(PartialEq, Eq, Copy, Clone, Debug)]
250pub(crate) enum Mode {
251 MethodCall,
255 Path,
259}
260
261#[derive(PartialEq, Eq, Copy, Clone, Debug)]
262pub(crate) enum ProbeScope {
263 Single(DefId),
265
266 TraitsInScope,
268
269 AllTraits,
271}
272
273impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
274 #[instrument(level = "debug", skip(self, candidate_filter))]
281 pub(crate) fn probe_for_return_type_for_diagnostic(
282 &self,
283 span: Span,
284 mode: Mode,
285 return_type: Ty<'tcx>,
286 self_ty: Ty<'tcx>,
287 scope_expr_id: HirId,
288 candidate_filter: impl Fn(&ty::AssocItem) -> bool,
289 ) -> Vec<ty::AssocItem> {
290 let method_names = self
291 .probe_op(
292 span,
293 mode,
294 None,
295 Some(return_type),
296 IsSuggestion(true),
297 self_ty,
298 scope_expr_id,
299 ProbeScope::AllTraits,
300 |probe_cx| Ok(probe_cx.candidate_method_names(candidate_filter)),
301 )
302 .unwrap_or_default();
303 method_names
304 .iter()
305 .flat_map(|&method_name| {
306 self.probe_op(
307 span,
308 mode,
309 Some(method_name),
310 Some(return_type),
311 IsSuggestion(true),
312 self_ty,
313 scope_expr_id,
314 ProbeScope::AllTraits,
315 |probe_cx| probe_cx.pick(),
316 )
317 .ok()
318 .map(|pick| pick.item)
319 })
320 .collect()
321 }
322
323 #[instrument(level = "debug", skip(self))]
324 pub(crate) fn probe_for_name(
325 &self,
326 mode: Mode,
327 item_name: Ident,
328 return_type: Option<Ty<'tcx>>,
329 is_suggestion: IsSuggestion,
330 self_ty: Ty<'tcx>,
331 scope_expr_id: HirId,
332 scope: ProbeScope,
333 ) -> PickResult<'tcx> {
334 self.probe_op(
335 item_name.span,
336 mode,
337 Some(item_name),
338 return_type,
339 is_suggestion,
340 self_ty,
341 scope_expr_id,
342 scope,
343 |probe_cx| probe_cx.pick(),
344 )
345 }
346
347 #[instrument(level = "debug", skip(self))]
348 pub(crate) fn probe_for_name_many(
349 &self,
350 mode: Mode,
351 item_name: Ident,
352 return_type: Option<Ty<'tcx>>,
353 is_suggestion: IsSuggestion,
354 self_ty: Ty<'tcx>,
355 scope_expr_id: HirId,
356 scope: ProbeScope,
357 ) -> Result<Vec<Candidate<'tcx>>, MethodError<'tcx>> {
358 self.probe_op(
359 item_name.span,
360 mode,
361 Some(item_name),
362 return_type,
363 is_suggestion,
364 self_ty,
365 scope_expr_id,
366 scope,
367 |probe_cx| {
368 Ok(probe_cx
369 .inherent_candidates
370 .into_iter()
371 .chain(probe_cx.extension_candidates)
372 .collect())
373 },
374 )
375 }
376
377 pub(crate) fn probe_op<OP, R>(
378 &'a self,
379 span: Span,
380 mode: Mode,
381 method_name: Option<Ident>,
382 return_type: Option<Ty<'tcx>>,
383 is_suggestion: IsSuggestion,
384 self_ty: Ty<'tcx>,
385 scope_expr_id: HirId,
386 scope: ProbeScope,
387 op: OP,
388 ) -> Result<R, MethodError<'tcx>>
389 where
390 OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
391 {
392 let mut orig_values = OriginalQueryValues::default();
393 let predefined_opaques_in_body = if self.next_trait_solver() {
394 self.tcx.mk_predefined_opaques_in_body_from_iter(
395 self.inner.borrow_mut().opaque_types().iter_opaque_types().map(|(k, v)| (k, v.ty)),
396 )
397 } else {
398 ty::List::empty()
399 };
400 let value = query::MethodAutoderefSteps { predefined_opaques_in_body, self_ty };
401 let query_input = self
402 .canonicalize_query(ParamEnvAnd { param_env: self.param_env, value }, &mut orig_values);
403
404 let steps = match mode {
405 Mode::MethodCall => self.tcx.method_autoderef_steps(query_input),
406 Mode::Path => self.probe(|_| {
407 let infcx = &self.infcx;
413 let (ParamEnvAnd { param_env: _, value }, var_values) =
414 infcx.instantiate_canonical(span, &query_input.canonical);
415 let query::MethodAutoderefSteps { predefined_opaques_in_body: _, self_ty } = value;
416 debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
417 MethodAutoderefStepsResult {
418 steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
419 self_ty: self
420 .make_query_response_ignoring_pending_obligations(var_values, self_ty),
421 self_ty_is_opaque: false,
422 autoderefs: 0,
423 from_unsafe_deref: false,
424 unsize: false,
425 reachable_via_deref: true,
426 }]),
427 opt_bad_ty: None,
428 reached_recursion_limit: false,
429 }
430 }),
431 };
432
433 if steps.reached_recursion_limit && !is_suggestion.0 {
437 self.probe(|_| {
438 let ty = &steps
439 .steps
440 .last()
441 .unwrap_or_else(|| span_bug!(span, "reached the recursion limit in 0 steps?"))
442 .self_ty;
443 let ty = self
444 .probe_instantiate_query_response(span, &orig_values, ty)
445 .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
446 autoderef::report_autoderef_recursion_limit_error(self.tcx, span, ty.value);
447 });
448 }
449
450 if let Some(bad_ty) = &steps.opt_bad_ty {
453 if is_suggestion.0 {
454 return Err(MethodError::NoMatch(NoMatchData {
457 static_candidates: Vec::new(),
458 unsatisfied_predicates: Vec::new(),
459 out_of_scope_traits: Vec::new(),
460 similar_candidate: None,
461 mode,
462 }));
463 } else if bad_ty.reached_raw_pointer
464 && !self.tcx.features().arbitrary_self_types_pointers()
465 && !self.tcx.sess.at_least_rust_2018()
466 {
467 self.tcx.node_span_lint(
471 lint::builtin::TYVAR_BEHIND_RAW_POINTER,
472 scope_expr_id,
473 span,
474 |lint| {
475 lint.primary_message("type annotations needed");
476 },
477 );
478 } else {
479 let ty = &bad_ty.ty;
483 let ty = self
484 .probe_instantiate_query_response(span, &orig_values, ty)
485 .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
486 let ty = self.resolve_vars_if_possible(ty.value);
487 let guar = match *ty.kind() {
488 ty::Infer(ty::TyVar(_)) => {
489 let raw_ptr_call = bad_ty.reached_raw_pointer
490 && !self.tcx.features().arbitrary_self_types();
491 let mut err = self.err_ctxt().emit_inference_failure_err(
494 self.body_id,
495 span,
496 ty.into(),
497 TypeAnnotationNeeded::E0282,
498 !raw_ptr_call,
499 );
500 if raw_ptr_call {
501 err.span_label(span, "cannot call a method on a raw pointer with an unknown pointee type");
502 }
503 err.emit()
504 }
505 ty::Error(guar) => guar,
506 _ => bug!("unexpected bad final type in method autoderef"),
507 };
508 self.demand_eqtype(span, ty, Ty::new_error(self.tcx, guar));
509 return Err(MethodError::ErrorReported(guar));
510 }
511 }
512
513 debug!("ProbeContext: steps for self_ty={:?} are {:?}", self_ty, steps);
514
515 self.probe(|_| {
518 let mut probe_cx = ProbeContext::new(
519 self,
520 span,
521 mode,
522 method_name,
523 return_type,
524 &orig_values,
525 steps.steps,
526 scope_expr_id,
527 is_suggestion,
528 );
529
530 match scope {
531 ProbeScope::TraitsInScope => {
532 probe_cx.assemble_inherent_candidates();
533 probe_cx.assemble_extension_candidates_for_traits_in_scope();
534 }
535 ProbeScope::AllTraits => {
536 probe_cx.assemble_inherent_candidates();
537 probe_cx.assemble_extension_candidates_for_all_traits();
538 }
539 ProbeScope::Single(def_id) => {
540 let item = self.tcx.associated_item(def_id);
541 assert_eq!(item.container, AssocContainer::Trait);
543
544 let trait_def_id = self.tcx.parent(def_id);
545 let trait_span = self.tcx.def_span(trait_def_id);
546
547 let trait_args = self.fresh_args_for_item(trait_span, trait_def_id);
548 let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args);
549
550 probe_cx.push_candidate(
551 Candidate {
552 item,
553 kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)),
554 import_ids: smallvec![],
555 },
556 false,
557 );
558 }
559 };
560 op(probe_cx)
561 })
562 }
563}
564
565pub(crate) fn method_autoderef_steps<'tcx>(
566 tcx: TyCtxt<'tcx>,
567 goal: CanonicalMethodAutoderefStepsGoal<'tcx>,
568) -> MethodAutoderefStepsResult<'tcx> {
569 debug!("method_autoderef_steps({:?})", goal);
570
571 let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
572 let ParamEnvAnd {
573 param_env,
574 value: query::MethodAutoderefSteps { predefined_opaques_in_body, self_ty },
575 } = goal;
576 for (key, ty) in predefined_opaques_in_body {
577 let prev =
578 infcx.register_hidden_type_in_storage(key, ty::OpaqueHiddenType { span: DUMMY_SP, ty });
579 if let Some(prev) = prev {
591 debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
592 }
593 }
594
595 let self_ty_is_opaque = |ty: Ty<'_>| {
599 if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
600 infcx.has_opaques_with_sub_unified_hidden_type(vid)
601 } else {
602 false
603 }
604 };
605
606 let mut autoderef_via_deref =
616 Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
617 .include_raw_pointers()
618 .silence_errors();
619
620 let mut reached_raw_pointer = false;
621 let arbitrary_self_types_enabled =
622 tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers();
623 let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled {
624 let reachable_via_deref =
625 autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
626
627 let mut autoderef_via_receiver =
628 Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
629 .include_raw_pointers()
630 .use_receiver_trait()
631 .silence_errors();
632 let steps = autoderef_via_receiver
633 .by_ref()
634 .zip(reachable_via_deref)
635 .map(|((ty, d), reachable_via_deref)| {
636 let step = CandidateStep {
637 self_ty: infcx
638 .make_query_response_ignoring_pending_obligations(inference_vars, ty),
639 self_ty_is_opaque: self_ty_is_opaque(ty),
640 autoderefs: d,
641 from_unsafe_deref: reached_raw_pointer,
642 unsize: false,
643 reachable_via_deref,
644 };
645 if ty.is_raw_ptr() {
646 reached_raw_pointer = true;
648 }
649 step
650 })
651 .collect();
652 (steps, autoderef_via_receiver.reached_recursion_limit())
653 } else {
654 let steps = autoderef_via_deref
655 .by_ref()
656 .map(|(ty, d)| {
657 let step = CandidateStep {
658 self_ty: infcx
659 .make_query_response_ignoring_pending_obligations(inference_vars, ty),
660 self_ty_is_opaque: self_ty_is_opaque(ty),
661 autoderefs: d,
662 from_unsafe_deref: reached_raw_pointer,
663 unsize: false,
664 reachable_via_deref: true,
665 };
666 if ty.is_raw_ptr() {
667 reached_raw_pointer = true;
669 }
670 step
671 })
672 .collect();
673 (steps, autoderef_via_deref.reached_recursion_limit())
674 };
675 let final_ty = autoderef_via_deref.final_ty();
676 let opt_bad_ty = match final_ty.kind() {
677 ty::Infer(ty::TyVar(_)) if !self_ty_is_opaque(final_ty) => Some(MethodAutoderefBadTy {
678 reached_raw_pointer,
679 ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
680 }),
681 ty::Error(_) => Some(MethodAutoderefBadTy {
682 reached_raw_pointer,
683 ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
684 }),
685 ty::Array(elem_ty, _) => {
686 let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
687 steps.push(CandidateStep {
688 self_ty: infcx.make_query_response_ignoring_pending_obligations(
689 inference_vars,
690 Ty::new_slice(infcx.tcx, *elem_ty),
691 ),
692 self_ty_is_opaque: false,
693 autoderefs,
694 from_unsafe_deref: reached_raw_pointer,
697 unsize: true,
698 reachable_via_deref: true, });
701
702 None
703 }
704 _ => None,
705 };
706
707 debug!("method_autoderef_steps: steps={:?} opt_bad_ty={:?}", steps, opt_bad_ty);
708 let _ = infcx.take_opaque_types();
710 MethodAutoderefStepsResult {
711 steps: tcx.arena.alloc_from_iter(steps),
712 opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
713 reached_recursion_limit,
714 }
715}
716
717impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
718 fn new(
719 fcx: &'a FnCtxt<'a, 'tcx>,
720 span: Span,
721 mode: Mode,
722 method_name: Option<Ident>,
723 return_type: Option<Ty<'tcx>>,
724 orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
725 steps: &'tcx [CandidateStep<'tcx>],
726 scope_expr_id: HirId,
727 is_suggestion: IsSuggestion,
728 ) -> ProbeContext<'a, 'tcx> {
729 ProbeContext {
730 fcx,
731 span,
732 mode,
733 method_name,
734 return_type,
735 inherent_candidates: Vec::new(),
736 extension_candidates: Vec::new(),
737 impl_dups: FxHashSet::default(),
738 orig_steps_var_values,
739 steps,
740 allow_similar_names: false,
741 private_candidates: Vec::new(),
742 private_candidate: Cell::new(None),
743 static_candidates: RefCell::new(Vec::new()),
744 scope_expr_id,
745 is_suggestion,
746 }
747 }
748
749 fn reset(&mut self) {
750 self.inherent_candidates.clear();
751 self.extension_candidates.clear();
752 self.impl_dups.clear();
753 self.private_candidates.clear();
754 self.private_candidate.set(None);
755 self.static_candidates.borrow_mut().clear();
756 }
757
758 fn variance(&self) -> ty::Variance {
762 match self.mode {
763 Mode::MethodCall => ty::Covariant,
764 Mode::Path => ty::Invariant,
765 }
766 }
767
768 fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) {
772 let is_accessible = if let Some(name) = self.method_name {
773 let item = candidate.item;
774 let hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
775 let def_scope =
776 self.tcx.adjust_ident_and_get_scope(name, item.container_id(self.tcx), hir_id).1;
777 item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx)
778 } else {
779 true
780 };
781 if is_accessible {
782 if is_inherent {
783 self.inherent_candidates.push(candidate);
784 } else {
785 self.extension_candidates.push(candidate);
786 }
787 } else {
788 self.private_candidates.push(candidate);
789 }
790 }
791
792 fn assemble_inherent_candidates(&mut self) {
793 for step in self.steps.iter() {
794 self.assemble_probe(&step.self_ty, step.autoderefs);
795 }
796 }
797
798 #[instrument(level = "debug", skip(self))]
799 fn assemble_probe(
800 &mut self,
801 self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
802 receiver_steps: usize,
803 ) {
804 let raw_self_ty = self_ty.value.value;
805 match *raw_self_ty.kind() {
806 ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
807 let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) =
825 self.fcx.instantiate_canonical(self.span, self_ty);
826
827 self.assemble_inherent_candidates_from_object(generalized_self_ty);
828 self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps);
829 self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
830 }
831 ty::Adt(def, _) => {
832 let def_id = def.did();
833 self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps);
834 self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
835 }
836 ty::Foreign(did) => {
837 self.assemble_inherent_impl_candidates_for_type(did, receiver_steps);
838 self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
839 }
840 ty::Param(_) => {
841 self.assemble_inherent_candidates_from_param(raw_self_ty);
842 }
843 ty::Bool
844 | ty::Char
845 | ty::Int(_)
846 | ty::Uint(_)
847 | ty::Float(_)
848 | ty::Str
849 | ty::Array(..)
850 | ty::Slice(_)
851 | ty::RawPtr(_, _)
852 | ty::Ref(..)
853 | ty::Never
854 | ty::Tuple(..) => {
855 self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps)
856 }
857 _ => {}
858 }
859 }
860
861 fn assemble_inherent_candidates_for_incoherent_ty(
862 &mut self,
863 self_ty: Ty<'tcx>,
864 receiver_steps: usize,
865 ) {
866 let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
867 bug!("unexpected incoherent type: {:?}", self_ty)
868 };
869 for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() {
870 self.assemble_inherent_impl_probe(impl_def_id, receiver_steps);
871 }
872 }
873
874 fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId, receiver_steps: usize) {
875 let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter();
876 for &impl_def_id in impl_def_ids {
877 self.assemble_inherent_impl_probe(impl_def_id, receiver_steps);
878 }
879 }
880
881 #[instrument(level = "debug", skip(self))]
882 fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId, receiver_steps: usize) {
883 if !self.impl_dups.insert(impl_def_id) {
884 return; }
886
887 for item in self.impl_or_trait_item(impl_def_id) {
888 if !self.has_applicable_self(&item) {
889 self.record_static_candidate(CandidateSource::Impl(impl_def_id));
891 continue;
892 }
893 self.push_candidate(
894 Candidate {
895 item,
896 kind: InherentImplCandidate { impl_def_id, receiver_steps },
897 import_ids: smallvec![],
898 },
899 true,
900 );
901 }
902 }
903
904 #[instrument(level = "debug", skip(self))]
905 fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
906 let principal = match self_ty.kind() {
907 ty::Dynamic(data, ..) => Some(data),
908 _ => None,
909 }
910 .and_then(|data| data.principal())
911 .unwrap_or_else(|| {
912 span_bug!(
913 self.span,
914 "non-object {:?} in assemble_inherent_candidates_from_object",
915 self_ty
916 )
917 });
918
919 let trait_ref = principal.with_self_ty(self.tcx, self_ty);
926 self.assemble_candidates_for_bounds(
927 traits::supertraits(self.tcx, trait_ref),
928 |this, new_trait_ref, item| {
929 this.push_candidate(
930 Candidate {
931 item,
932 kind: ObjectCandidate(new_trait_ref),
933 import_ids: smallvec![],
934 },
935 true,
936 );
937 },
938 );
939 }
940
941 #[instrument(level = "debug", skip(self))]
942 fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) {
943 debug_assert_matches!(param_ty.kind(), ty::Param(_));
944
945 let tcx = self.tcx;
946
947 let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
951 let bound_predicate = predicate.kind();
952 match bound_predicate.skip_binder() {
953 ty::ClauseKind::Trait(trait_predicate) => DeepRejectCtxt::relate_rigid_rigid(tcx)
954 .types_may_unify(param_ty, trait_predicate.trait_ref.self_ty())
955 .then(|| bound_predicate.rebind(trait_predicate.trait_ref)),
956 ty::ClauseKind::RegionOutlives(_)
957 | ty::ClauseKind::TypeOutlives(_)
958 | ty::ClauseKind::Projection(_)
959 | ty::ClauseKind::ConstArgHasType(_, _)
960 | ty::ClauseKind::WellFormed(_)
961 | ty::ClauseKind::ConstEvaluatable(_)
962 | ty::ClauseKind::UnstableFeature(_)
963 | ty::ClauseKind::HostEffect(..) => None,
964 }
965 });
966
967 self.assemble_candidates_for_bounds(bounds, |this, poly_trait_ref, item| {
968 this.push_candidate(
969 Candidate {
970 item,
971 kind: WhereClauseCandidate(poly_trait_ref),
972 import_ids: smallvec![],
973 },
974 true,
975 );
976 });
977 }
978
979 fn assemble_candidates_for_bounds<F>(
982 &mut self,
983 bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
984 mut mk_cand: F,
985 ) where
986 F: for<'b> FnMut(&mut ProbeContext<'b, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssocItem),
987 {
988 for bound_trait_ref in bounds {
989 debug!("elaborate_bounds(bound_trait_ref={:?})", bound_trait_ref);
990 for item in self.impl_or_trait_item(bound_trait_ref.def_id()) {
991 if !self.has_applicable_self(&item) {
992 self.record_static_candidate(CandidateSource::Trait(bound_trait_ref.def_id()));
993 } else {
994 mk_cand(self, bound_trait_ref, item);
995 }
996 }
997 }
998 }
999
1000 #[instrument(level = "debug", skip(self))]
1001 fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
1002 let mut duplicates = FxHashSet::default();
1003 let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
1004 if let Some(applicable_traits) = opt_applicable_traits {
1005 for trait_candidate in applicable_traits.iter() {
1006 let trait_did = trait_candidate.def_id;
1007 if duplicates.insert(trait_did) {
1008 self.assemble_extension_candidates_for_trait(
1009 &trait_candidate.import_ids,
1010 trait_did,
1011 );
1012 }
1013 }
1014 }
1015 }
1016
1017 #[instrument(level = "debug", skip(self))]
1018 fn assemble_extension_candidates_for_all_traits(&mut self) {
1019 let mut duplicates = FxHashSet::default();
1020 for trait_info in suggest::all_traits(self.tcx) {
1021 if duplicates.insert(trait_info.def_id) {
1022 self.assemble_extension_candidates_for_trait(&smallvec![], trait_info.def_id);
1023 }
1024 }
1025 }
1026
1027 fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool {
1028 match method.kind {
1029 ty::AssocKind::Fn { .. } => self.probe(|_| {
1030 let args = self.fresh_args_for_item(self.span, method.def_id);
1031 let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
1032 let fty = self.instantiate_binder_with_fresh_vars(
1033 self.span,
1034 BoundRegionConversionTime::FnCall,
1035 fty,
1036 );
1037 self.can_eq(self.param_env, fty.output(), expected)
1038 }),
1039 _ => false,
1040 }
1041 }
1042
1043 #[instrument(level = "debug", skip(self))]
1044 fn assemble_extension_candidates_for_trait(
1045 &mut self,
1046 import_ids: &SmallVec<[LocalDefId; 1]>,
1047 trait_def_id: DefId,
1048 ) {
1049 let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
1050 let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args);
1051
1052 if self.tcx.is_trait_alias(trait_def_id) {
1053 for (bound_trait_pred, _) in
1055 traits::expand_trait_aliases(self.tcx, [(trait_ref.upcast(self.tcx), self.span)]).0
1056 {
1057 assert_eq!(bound_trait_pred.polarity(), ty::PredicatePolarity::Positive);
1058 let bound_trait_ref = bound_trait_pred.map_bound(|pred| pred.trait_ref);
1059 for item in self.impl_or_trait_item(bound_trait_ref.def_id()) {
1060 if !self.has_applicable_self(&item) {
1061 self.record_static_candidate(CandidateSource::Trait(
1062 bound_trait_ref.def_id(),
1063 ));
1064 } else {
1065 self.push_candidate(
1066 Candidate {
1067 item,
1068 import_ids: import_ids.clone(),
1069 kind: TraitCandidate(bound_trait_ref),
1070 },
1071 false,
1072 );
1073 }
1074 }
1075 }
1076 } else {
1077 debug_assert!(self.tcx.is_trait(trait_def_id));
1078 if self.tcx.trait_is_auto(trait_def_id) {
1079 return;
1080 }
1081 for item in self.impl_or_trait_item(trait_def_id) {
1082 if !self.has_applicable_self(&item) {
1084 debug!("method has inapplicable self");
1085 self.record_static_candidate(CandidateSource::Trait(trait_def_id));
1086 continue;
1087 }
1088 self.push_candidate(
1089 Candidate {
1090 item,
1091 import_ids: import_ids.clone(),
1092 kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
1093 },
1094 false,
1095 );
1096 }
1097 }
1098 }
1099
1100 fn candidate_method_names(
1101 &self,
1102 candidate_filter: impl Fn(&ty::AssocItem) -> bool,
1103 ) -> Vec<Ident> {
1104 let mut set = FxHashSet::default();
1105 let mut names: Vec<_> = self
1106 .inherent_candidates
1107 .iter()
1108 .chain(&self.extension_candidates)
1109 .filter(|candidate| candidate_filter(&candidate.item))
1110 .filter(|candidate| {
1111 if let Some(return_ty) = self.return_type {
1112 self.matches_return_type(candidate.item, return_ty)
1113 } else {
1114 true
1115 }
1116 })
1117 .filter(|candidate| {
1119 !matches!(
1122 self.tcx.eval_stability(candidate.item.def_id, None, DUMMY_SP, None),
1123 stability::EvalResult::Deny { .. }
1124 )
1125 })
1126 .map(|candidate| candidate.item.ident(self.tcx))
1127 .filter(|&name| set.insert(name))
1128 .collect();
1129
1130 names.sort_by(|a, b| a.as_str().cmp(b.as_str()));
1132 names
1133 }
1134
1135 #[instrument(level = "debug", skip(self))]
1139 fn pick(mut self) -> PickResult<'tcx> {
1140 assert!(self.method_name.is_some());
1141
1142 let mut unsatisfied_predicates = Vec::new();
1143
1144 if let Some(r) = self.pick_core(&mut unsatisfied_predicates) {
1145 return r;
1146 }
1147
1148 if self.is_suggestion.0 {
1151 return Err(MethodError::NoMatch(NoMatchData {
1152 static_candidates: vec![],
1153 unsatisfied_predicates: vec![],
1154 out_of_scope_traits: vec![],
1155 similar_candidate: None,
1156 mode: self.mode,
1157 }));
1158 }
1159
1160 debug!("pick: actual search failed, assemble diagnostics");
1161
1162 let static_candidates = std::mem::take(self.static_candidates.get_mut());
1163 let private_candidate = self.private_candidate.take();
1164
1165 self.reset();
1167
1168 let span = self.span;
1169 let tcx = self.tcx;
1170
1171 self.assemble_extension_candidates_for_all_traits();
1172
1173 let out_of_scope_traits = match self.pick_core(&mut Vec::new()) {
1174 Some(Ok(p)) => vec![p.item.container_id(self.tcx)],
1175 Some(Err(MethodError::Ambiguity(v))) => v
1176 .into_iter()
1177 .map(|source| match source {
1178 CandidateSource::Trait(id) => id,
1179 CandidateSource::Impl(impl_id) => match tcx.trait_id_of_impl(impl_id) {
1180 Some(id) => id,
1181 None => span_bug!(span, "found inherent method when looking at traits"),
1182 },
1183 })
1184 .collect(),
1185 Some(Err(MethodError::NoMatch(NoMatchData {
1186 out_of_scope_traits: others, ..
1187 }))) => {
1188 assert!(others.is_empty());
1189 vec![]
1190 }
1191 _ => vec![],
1192 };
1193
1194 if let Some((kind, def_id)) = private_candidate {
1195 return Err(MethodError::PrivateMatch(kind, def_id, out_of_scope_traits));
1196 }
1197 let similar_candidate = self.probe_for_similar_candidate()?;
1198
1199 Err(MethodError::NoMatch(NoMatchData {
1200 static_candidates,
1201 unsatisfied_predicates,
1202 out_of_scope_traits,
1203 similar_candidate,
1204 mode: self.mode,
1205 }))
1206 }
1207
1208 fn pick_core(
1209 &self,
1210 unsatisfied_predicates: &mut Vec<(
1211 ty::Predicate<'tcx>,
1212 Option<ty::Predicate<'tcx>>,
1213 Option<ObligationCause<'tcx>>,
1214 )>,
1215 ) -> Option<PickResult<'tcx>> {
1216 self.pick_all_method(&mut PickDiagHints {
1218 unstable_candidates: Some(Vec::new()),
1221 unsatisfied_predicates,
1224 })
1225 .or_else(|| {
1226 self.pick_all_method(&mut PickDiagHints {
1227 unstable_candidates: None,
1232 unsatisfied_predicates: &mut Vec::new(),
1235 })
1236 })
1237 }
1238
1239 fn pick_all_method<'b>(
1240 &self,
1241 pick_diag_hints: &mut PickDiagHints<'b, 'tcx>,
1242 ) -> Option<PickResult<'tcx>> {
1243 let track_unstable_candidates = pick_diag_hints.unstable_candidates.is_some();
1244 self.steps
1245 .iter()
1246 .filter(|step| step.reachable_via_deref)
1250 .filter(|step| {
1251 debug!("pick_all_method: step={:?}", step);
1252 !step.self_ty.value.references_error() && !step.from_unsafe_deref
1255 })
1256 .find_map(|step| {
1257 let InferOk { value: self_ty, obligations: instantiate_self_ty_obligations } = self
1258 .fcx
1259 .probe_instantiate_query_response(
1260 self.span,
1261 self.orig_steps_var_values,
1262 &step.self_ty,
1263 )
1264 .unwrap_or_else(|_| {
1265 span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty)
1266 });
1267
1268 let by_value_pick = self.pick_by_value_method(
1269 step,
1270 self_ty,
1271 &instantiate_self_ty_obligations,
1272 pick_diag_hints,
1273 );
1274
1275 if let Some(by_value_pick) = by_value_pick {
1277 if let Ok(by_value_pick) = by_value_pick.as_ref() {
1278 if by_value_pick.kind == PickKind::InherentImplPick {
1279 for mutbl in [hir::Mutability::Not, hir::Mutability::Mut] {
1280 if let Err(e) = self.check_for_shadowed_autorefd_method(
1281 by_value_pick,
1282 step,
1283 self_ty,
1284 &instantiate_self_ty_obligations,
1285 mutbl,
1286 track_unstable_candidates,
1287 ) {
1288 return Some(Err(e));
1289 }
1290 }
1291 }
1292 }
1293 return Some(by_value_pick);
1294 }
1295
1296 let autoref_pick = self.pick_autorefd_method(
1297 step,
1298 self_ty,
1299 &instantiate_self_ty_obligations,
1300 hir::Mutability::Not,
1301 pick_diag_hints,
1302 None,
1303 );
1304 if let Some(autoref_pick) = autoref_pick {
1306 if let Ok(autoref_pick) = autoref_pick.as_ref() {
1307 if autoref_pick.kind == PickKind::InherentImplPick {
1309 if let Err(e) = self.check_for_shadowed_autorefd_method(
1310 autoref_pick,
1311 step,
1312 self_ty,
1313 &instantiate_self_ty_obligations,
1314 hir::Mutability::Mut,
1315 track_unstable_candidates,
1316 ) {
1317 return Some(Err(e));
1318 }
1319 }
1320 }
1321 return Some(autoref_pick);
1322 }
1323
1324 self.pick_autorefd_method(
1348 step,
1349 self_ty,
1350 &instantiate_self_ty_obligations,
1351 hir::Mutability::Mut,
1352 pick_diag_hints,
1353 None,
1354 )
1355 .or_else(|| {
1356 self.pick_const_ptr_method(
1357 step,
1358 self_ty,
1359 &instantiate_self_ty_obligations,
1360 pick_diag_hints,
1361 )
1362 })
1363 .or_else(|| {
1364 self.pick_reborrow_pin_method(
1365 step,
1366 self_ty,
1367 &instantiate_self_ty_obligations,
1368 pick_diag_hints,
1369 )
1370 })
1371 })
1372 }
1373
1374 fn check_for_shadowed_autorefd_method(
1390 &self,
1391 possible_shadower: &Pick<'tcx>,
1392 step: &CandidateStep<'tcx>,
1393 self_ty: Ty<'tcx>,
1394 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1395 mutbl: hir::Mutability,
1396 track_unstable_candidates: bool,
1397 ) -> Result<(), MethodError<'tcx>> {
1398 if !self.tcx.features().arbitrary_self_types()
1402 && !self.tcx.features().arbitrary_self_types_pointers()
1403 {
1404 return Ok(());
1405 }
1406
1407 let mut pick_diag_hints = PickDiagHints {
1412 unstable_candidates: if track_unstable_candidates { Some(Vec::new()) } else { None },
1413 unsatisfied_predicates: &mut Vec::new(),
1414 };
1415 let pick_constraints = PickConstraintsForShadowed {
1417 autoderefs: possible_shadower.autoderefs,
1419 receiver_steps: possible_shadower.receiver_steps,
1423 def_id: possible_shadower.item.def_id,
1426 };
1427 let potentially_shadowed_pick = self.pick_autorefd_method(
1457 step,
1458 self_ty,
1459 instantiate_self_ty_obligations,
1460 mutbl,
1461 &mut pick_diag_hints,
1462 Some(&pick_constraints),
1463 );
1464 if let Some(Ok(possible_shadowed)) = potentially_shadowed_pick.as_ref() {
1467 let sources = [possible_shadower, possible_shadowed]
1468 .into_iter()
1469 .map(|p| self.candidate_source_from_pick(p))
1470 .collect();
1471 return Err(MethodError::Ambiguity(sources));
1472 }
1473 Ok(())
1474 }
1475
1476 fn pick_by_value_method(
1483 &self,
1484 step: &CandidateStep<'tcx>,
1485 self_ty: Ty<'tcx>,
1486 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1487 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1488 ) -> Option<PickResult<'tcx>> {
1489 if step.unsize {
1490 return None;
1491 }
1492
1493 self.pick_method(self_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map(|r| {
1494 r.map(|mut pick| {
1495 pick.autoderefs = step.autoderefs;
1496
1497 match *step.self_ty.value.value.kind() {
1498 ty::Ref(_, _, mutbl) => {
1500 pick.autoderefs += 1;
1501 pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
1502 mutbl,
1503 unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
1504 })
1505 }
1506
1507 ty::Adt(def, args)
1508 if self.tcx.features().pin_ergonomics()
1509 && self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) =>
1510 {
1511 if let ty::Ref(_, _, mutbl) = args[0].expect_ty().kind() {
1513 pick.autoref_or_ptr_adjustment =
1514 Some(AutorefOrPtrAdjustment::ReborrowPin(*mutbl));
1515 }
1516 }
1517
1518 _ => (),
1519 }
1520
1521 pick
1522 })
1523 })
1524 }
1525
1526 fn pick_autorefd_method(
1527 &self,
1528 step: &CandidateStep<'tcx>,
1529 self_ty: Ty<'tcx>,
1530 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1531 mutbl: hir::Mutability,
1532 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1533 pick_constraints: Option<&PickConstraintsForShadowed>,
1534 ) -> Option<PickResult<'tcx>> {
1535 let tcx = self.tcx;
1536
1537 if let Some(pick_constraints) = pick_constraints {
1538 if !pick_constraints.may_shadow_based_on_autoderefs(step.autoderefs) {
1539 return None;
1540 }
1541 }
1542
1543 let region = tcx.lifetimes.re_erased;
1545
1546 let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl);
1547 self.pick_method(
1548 autoref_ty,
1549 instantiate_self_ty_obligations,
1550 pick_diag_hints,
1551 pick_constraints,
1552 )
1553 .map(|r| {
1554 r.map(|mut pick| {
1555 pick.autoderefs = step.autoderefs;
1556 pick.autoref_or_ptr_adjustment =
1557 Some(AutorefOrPtrAdjustment::Autoref { mutbl, unsize: step.unsize });
1558 pick
1559 })
1560 })
1561 }
1562
1563 #[instrument(level = "debug", skip(self, step, pick_diag_hints))]
1565 fn pick_reborrow_pin_method(
1566 &self,
1567 step: &CandidateStep<'tcx>,
1568 self_ty: Ty<'tcx>,
1569 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1570 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1571 ) -> Option<PickResult<'tcx>> {
1572 if !self.tcx.features().pin_ergonomics() {
1573 return None;
1574 }
1575
1576 let inner_ty = match self_ty.kind() {
1578 ty::Adt(def, args) if self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) => {
1579 match args[0].expect_ty().kind() {
1580 ty::Ref(_, ty, hir::Mutability::Mut) => *ty,
1581 _ => {
1582 return None;
1583 }
1584 }
1585 }
1586 _ => return None,
1587 };
1588
1589 let region = self.tcx.lifetimes.re_erased;
1590 let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not);
1591 self.pick_method(autopin_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map(
1592 |r| {
1593 r.map(|mut pick| {
1594 pick.autoderefs = step.autoderefs;
1595 pick.autoref_or_ptr_adjustment =
1596 Some(AutorefOrPtrAdjustment::ReborrowPin(hir::Mutability::Not));
1597 pick
1598 })
1599 },
1600 )
1601 }
1602
1603 fn pick_const_ptr_method(
1607 &self,
1608 step: &CandidateStep<'tcx>,
1609 self_ty: Ty<'tcx>,
1610 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1611 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1612 ) -> Option<PickResult<'tcx>> {
1613 if step.unsize {
1615 return None;
1616 }
1617
1618 let &ty::RawPtr(ty, hir::Mutability::Mut) = self_ty.kind() else {
1619 return None;
1620 };
1621
1622 let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty);
1623 self.pick_method(const_ptr_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map(
1624 |r| {
1625 r.map(|mut pick| {
1626 pick.autoderefs = step.autoderefs;
1627 pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
1628 pick
1629 })
1630 },
1631 )
1632 }
1633
1634 fn pick_method(
1635 &self,
1636 self_ty: Ty<'tcx>,
1637 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1638 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1639 pick_constraints: Option<&PickConstraintsForShadowed>,
1640 ) -> Option<PickResult<'tcx>> {
1641 debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
1642
1643 for (kind, candidates) in
1644 [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
1645 {
1646 debug!("searching {} candidates", kind);
1647 let res = self.consider_candidates(
1648 self_ty,
1649 instantiate_self_ty_obligations,
1650 candidates,
1651 pick_diag_hints,
1652 pick_constraints,
1653 );
1654 if let Some(pick) = res {
1655 return Some(pick);
1656 }
1657 }
1658
1659 if self.private_candidate.get().is_none() {
1660 if let Some(Ok(pick)) = self.consider_candidates(
1661 self_ty,
1662 instantiate_self_ty_obligations,
1663 &self.private_candidates,
1664 &mut PickDiagHints {
1665 unstable_candidates: None,
1666 unsatisfied_predicates: &mut vec![],
1667 },
1668 None,
1669 ) {
1670 self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id)));
1671 }
1672 }
1673 None
1674 }
1675
1676 fn consider_candidates(
1677 &self,
1678 self_ty: Ty<'tcx>,
1679 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1680 candidates: &[Candidate<'tcx>],
1681 pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
1682 pick_constraints: Option<&PickConstraintsForShadowed>,
1683 ) -> Option<PickResult<'tcx>> {
1684 let mut applicable_candidates: Vec<_> = candidates
1685 .iter()
1686 .filter(|candidate| {
1687 pick_constraints
1688 .map(|pick_constraints| pick_constraints.candidate_may_shadow(&candidate))
1689 .unwrap_or(true)
1690 })
1691 .map(|probe| {
1692 (
1693 probe,
1694 self.consider_probe(
1695 self_ty,
1696 instantiate_self_ty_obligations,
1697 probe,
1698 &mut pick_diag_hints.unsatisfied_predicates,
1699 ),
1700 )
1701 })
1702 .filter(|&(_, status)| status != ProbeResult::NoMatch)
1703 .collect();
1704
1705 debug!("applicable_candidates: {:?}", applicable_candidates);
1706
1707 if applicable_candidates.len() > 1 {
1708 if let Some(pick) =
1709 self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates)
1710 {
1711 return Some(Ok(pick));
1712 }
1713 }
1714
1715 if let Some(uc) = &mut pick_diag_hints.unstable_candidates {
1716 applicable_candidates.retain(|&(candidate, _)| {
1717 if let stability::EvalResult::Deny { feature, .. } =
1718 self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
1719 {
1720 uc.push((candidate.clone(), feature));
1721 return false;
1722 }
1723 true
1724 });
1725 }
1726
1727 if applicable_candidates.len() > 1 {
1728 if self.tcx.features().supertrait_item_shadowing() {
1732 if let Some(pick) =
1733 self.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
1734 {
1735 return Some(Ok(pick));
1736 }
1737 }
1738
1739 let sources =
1740 applicable_candidates.iter().map(|p| self.candidate_source(p.0, self_ty)).collect();
1741 return Some(Err(MethodError::Ambiguity(sources)));
1742 }
1743
1744 applicable_candidates.pop().map(|(probe, status)| match status {
1745 ProbeResult::Match => Ok(probe.to_unadjusted_pick(
1746 self_ty,
1747 pick_diag_hints.unstable_candidates.clone().unwrap_or_default(),
1748 )),
1749 ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType),
1750 })
1751 }
1752}
1753
1754impl<'tcx> Pick<'tcx> {
1755 pub(crate) fn differs_from(&self, other: &Self) -> bool {
1760 let Self {
1761 item: AssocItem { def_id, kind: _, container: _ },
1762 kind: _,
1763 import_ids: _,
1764 autoderefs: _,
1765 autoref_or_ptr_adjustment: _,
1766 self_ty,
1767 unstable_candidates: _,
1768 receiver_steps: _,
1769 shadowed_candidates: _,
1770 } = *self;
1771 self_ty != other.self_ty || def_id != other.item.def_id
1772 }
1773
1774 pub(crate) fn maybe_emit_unstable_name_collision_hint(
1776 &self,
1777 tcx: TyCtxt<'tcx>,
1778 span: Span,
1779 scope_expr_id: HirId,
1780 ) {
1781 if self.unstable_candidates.is_empty() {
1782 return;
1783 }
1784 let def_kind = self.item.as_def_kind();
1785 tcx.node_span_lint(lint::builtin::UNSTABLE_NAME_COLLISIONS, scope_expr_id, span, |lint| {
1786 lint.primary_message(format!(
1787 "{} {} with this name may be added to the standard library in the future",
1788 tcx.def_kind_descr_article(def_kind, self.item.def_id),
1789 tcx.def_kind_descr(def_kind, self.item.def_id),
1790 ));
1791
1792 match (self.item.kind, self.item.container) {
1793 (ty::AssocKind::Fn { .. }, _) => {
1794 lint.help(format!(
1799 "call with fully qualified syntax `{}(...)` to keep using the current \
1800 method",
1801 tcx.def_path_str(self.item.def_id),
1802 ));
1803 }
1804 (ty::AssocKind::Const { name }, ty::AssocContainer::Trait) => {
1805 let def_id = self.item.container_id(tcx);
1806 lint.span_suggestion(
1807 span,
1808 "use the fully qualified path to the associated const",
1809 format!("<{} as {}>::{}", self.self_ty, tcx.def_path_str(def_id), name),
1810 Applicability::MachineApplicable,
1811 );
1812 }
1813 _ => {}
1814 }
1815 tcx.disabled_nightly_features(
1816 lint,
1817 self.unstable_candidates.iter().map(|(candidate, feature)| {
1818 (format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), *feature)
1819 }),
1820 );
1821 });
1822 }
1823}
1824
1825impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1826 fn select_trait_candidate(
1827 &self,
1828 trait_ref: ty::TraitRef<'tcx>,
1829 ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
1830 let obligation =
1831 traits::Obligation::new(self.tcx, self.misc(self.span), self.param_env, trait_ref);
1832 traits::SelectionContext::new(self).select(&obligation)
1833 }
1834
1835 fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
1838 match candidate.kind {
1839 InherentImplCandidate { .. } => {
1840 CandidateSource::Impl(candidate.item.container_id(self.tcx))
1841 }
1842 ObjectCandidate(_) | WhereClauseCandidate(_) => {
1843 CandidateSource::Trait(candidate.item.container_id(self.tcx))
1844 }
1845 TraitCandidate(trait_ref) => self.probe(|_| {
1846 let trait_ref = self.instantiate_binder_with_fresh_vars(
1847 self.span,
1848 BoundRegionConversionTime::FnCall,
1849 trait_ref,
1850 );
1851 let (xform_self_ty, _) =
1852 self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args);
1853 let _ = self.at(&ObligationCause::dummy(), self.param_env).sup(
1856 DefineOpaqueTypes::Yes,
1857 xform_self_ty,
1858 self_ty,
1859 );
1860 match self.select_trait_candidate(trait_ref) {
1861 Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
1862 CandidateSource::Impl(impl_data.impl_def_id)
1865 }
1866 _ => CandidateSource::Trait(candidate.item.container_id(self.tcx)),
1867 }
1868 }),
1869 }
1870 }
1871
1872 fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource {
1873 match pick.kind {
1874 InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)),
1875 ObjectPick | WhereClausePick(_) | TraitPick => {
1876 CandidateSource::Trait(pick.item.container_id(self.tcx))
1877 }
1878 }
1879 }
1880
1881 #[instrument(level = "debug", skip(self, possibly_unsatisfied_predicates), ret)]
1882 fn consider_probe(
1883 &self,
1884 self_ty: Ty<'tcx>,
1885 instantiate_self_ty_obligations: &[PredicateObligation<'tcx>],
1886 probe: &Candidate<'tcx>,
1887 possibly_unsatisfied_predicates: &mut Vec<(
1888 ty::Predicate<'tcx>,
1889 Option<ty::Predicate<'tcx>>,
1890 Option<ObligationCause<'tcx>>,
1891 )>,
1892 ) -> ProbeResult {
1893 self.probe(|snapshot| {
1894 let outer_universe = self.universe();
1895
1896 let mut result = ProbeResult::Match;
1897 let cause = &self.misc(self.span);
1898 let ocx = ObligationCtxt::new_with_diagnostics(self);
1899
1900 if self.next_trait_solver() {
1908 ocx.register_obligations(instantiate_self_ty_obligations.iter().cloned());
1909 let errors = ocx.select_where_possible();
1910 if !errors.is_empty() {
1911 unreachable!("unexpected autoderef error {errors:?}");
1912 }
1913 }
1914
1915 let mut trait_predicate = None;
1916 let (mut xform_self_ty, mut xform_ret_ty);
1917
1918 match probe.kind {
1919 InherentImplCandidate { impl_def_id, .. } => {
1920 let impl_args = self.fresh_args_for_item(self.span, impl_def_id);
1921 let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
1922 (xform_self_ty, xform_ret_ty) =
1923 self.xform_self_ty(probe.item, impl_ty, impl_args);
1924 xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1925 match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
1926 {
1927 Ok(()) => {}
1928 Err(err) => {
1929 debug!("--> cannot relate self-types {:?}", err);
1930 return ProbeResult::NoMatch;
1931 }
1932 }
1933 xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty);
1935 let impl_def_id = probe.item.container_id(self.tcx);
1937 let impl_bounds =
1938 self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
1939 let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
1940 ocx.register_obligations(traits::predicates_for_generics(
1942 |idx, span| {
1943 let code = ObligationCauseCode::WhereClauseInExpr(
1944 impl_def_id,
1945 span,
1946 self.scope_expr_id,
1947 idx,
1948 );
1949 self.cause(self.span, code)
1950 },
1951 self.param_env,
1952 impl_bounds,
1953 ));
1954 }
1955 TraitCandidate(poly_trait_ref) => {
1956 if let Some(method_name) = self.method_name {
1959 if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
1960 let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
1961 if trait_def.skip_array_during_method_dispatch {
1962 return ProbeResult::NoMatch;
1963 }
1964 }
1965
1966 if self_ty.boxed_ty().is_some_and(Ty::is_slice)
1969 && !method_name.span.at_least_rust_2024()
1970 {
1971 let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
1972 if trait_def.skip_boxed_slice_during_method_dispatch {
1973 return ProbeResult::NoMatch;
1974 }
1975 }
1976 }
1977
1978 let trait_ref = self.instantiate_binder_with_fresh_vars(
1979 self.span,
1980 BoundRegionConversionTime::FnCall,
1981 poly_trait_ref,
1982 );
1983 let trait_ref = ocx.normalize(cause, self.param_env, trait_ref);
1984 (xform_self_ty, xform_ret_ty) =
1985 self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
1986 xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1987 match self_ty.kind() {
1988 ty::Alias(ty::Opaque, alias_ty)
1992 if !self.next_trait_solver()
1993 && self.infcx.can_define_opaque_ty(alias_ty.def_id)
1994 && !xform_self_ty.is_ty_var() =>
1995 {
1996 return ProbeResult::NoMatch;
1997 }
1998 _ => match ocx.relate(
1999 cause,
2000 self.param_env,
2001 self.variance(),
2002 self_ty,
2003 xform_self_ty,
2004 ) {
2005 Ok(()) => {}
2006 Err(err) => {
2007 debug!("--> cannot relate self-types {:?}", err);
2008 return ProbeResult::NoMatch;
2009 }
2010 },
2011 }
2012 let obligation = traits::Obligation::new(
2013 self.tcx,
2014 cause.clone(),
2015 self.param_env,
2016 ty::Binder::dummy(trait_ref),
2017 );
2018
2019 if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation)
2021 {
2022 ocx.register_obligation(obligation);
2023 } else {
2024 result = ProbeResult::NoMatch;
2025 if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref) {
2026 for nested_obligation in candidate.nested_obligations() {
2027 if !self.infcx.predicate_may_hold(&nested_obligation) {
2028 possibly_unsatisfied_predicates.push((
2029 self.resolve_vars_if_possible(nested_obligation.predicate),
2030 Some(self.resolve_vars_if_possible(obligation.predicate)),
2031 Some(nested_obligation.cause),
2032 ));
2033 }
2034 }
2035 }
2036 }
2037
2038 trait_predicate = Some(trait_ref.upcast(self.tcx));
2039 }
2040 ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => {
2041 let trait_ref = self.instantiate_binder_with_fresh_vars(
2042 self.span,
2043 BoundRegionConversionTime::FnCall,
2044 poly_trait_ref,
2045 );
2046 (xform_self_ty, xform_ret_ty) =
2047 self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
2048
2049 if matches!(probe.kind, WhereClauseCandidate(_)) {
2050 match ocx.structurally_normalize_ty(
2054 cause,
2055 self.param_env,
2056 trait_ref.self_ty(),
2057 ) {
2058 Ok(ty) => {
2059 if !matches!(ty.kind(), ty::Param(_)) {
2060 debug!("--> not a param ty: {xform_self_ty:?}");
2061 return ProbeResult::NoMatch;
2062 }
2063 }
2064 Err(errors) => {
2065 debug!("--> cannot relate self-types {:?}", errors);
2066 return ProbeResult::NoMatch;
2067 }
2068 }
2069 }
2070
2071 xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
2072 match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
2073 {
2074 Ok(()) => {}
2075 Err(err) => {
2076 debug!("--> cannot relate self-types {:?}", err);
2077 return ProbeResult::NoMatch;
2078 }
2079 }
2080 }
2081 }
2082
2083 if let Some(xform_ret_ty) = xform_ret_ty
2095 && self.infcx.next_trait_solver()
2096 {
2097 ocx.register_obligation(traits::Obligation::new(
2098 self.tcx,
2099 cause.clone(),
2100 self.param_env,
2101 ty::ClauseKind::WellFormed(xform_ret_ty.into()),
2102 ));
2103 }
2104
2105 for error in ocx.select_where_possible() {
2107 result = ProbeResult::NoMatch;
2108 let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
2109 if let Some(trait_predicate) = trait_predicate
2110 && nested_predicate == self.resolve_vars_if_possible(trait_predicate)
2111 {
2112 } else {
2116 possibly_unsatisfied_predicates.push((
2117 nested_predicate,
2118 Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
2119 .filter(|root_predicate| *root_predicate != nested_predicate),
2120 Some(error.obligation.cause),
2121 ));
2122 }
2123 }
2124
2125 if let ProbeResult::Match = result
2126 && let Some(return_ty) = self.return_type
2127 && let Some(mut xform_ret_ty) = xform_ret_ty
2128 {
2129 if !matches!(probe.kind, InherentImplCandidate { .. }) {
2134 xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty);
2135 }
2136
2137 debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty);
2138 match ocx.relate(cause, self.param_env, self.variance(), xform_ret_ty, return_ty) {
2139 Ok(()) => {}
2140 Err(_) => {
2141 result = ProbeResult::BadReturnType;
2142 }
2143 }
2144
2145 for error in ocx.select_where_possible() {
2147 result = ProbeResult::NoMatch;
2148 possibly_unsatisfied_predicates.push((
2149 error.obligation.predicate,
2150 Some(error.root_obligation.predicate)
2151 .filter(|predicate| *predicate != error.obligation.predicate),
2152 Some(error.root_obligation.cause),
2153 ));
2154 }
2155 }
2156
2157 if self.infcx.next_trait_solver() {
2158 if self.should_reject_candidate_due_to_opaque_treated_as_rigid(trait_predicate) {
2159 result = ProbeResult::NoMatch;
2160 }
2161 }
2162
2163 if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) {
2169 result = ProbeResult::NoMatch;
2170 }
2171
2172 result
2173 })
2174 }
2175
2176 #[instrument(level = "debug", skip(self), ret)]
2191 fn should_reject_candidate_due_to_opaque_treated_as_rigid(
2192 &self,
2193 trait_predicate: Option<ty::Predicate<'tcx>>,
2194 ) -> bool {
2195 if let Some(predicate) = trait_predicate {
2207 let goal = Goal { param_env: self.param_env, predicate };
2208 if !self.infcx.goal_may_hold_opaque_types_jank(goal) {
2209 return true;
2210 }
2211 }
2212
2213 for step in self.steps {
2216 if step.self_ty_is_opaque {
2217 debug!(?step.autoderefs, ?step.self_ty, "self_type_is_opaque");
2218 let constrained_opaque = self.probe(|_| {
2219 let Ok(ok) = self.fcx.probe_instantiate_query_response(
2224 self.span,
2225 self.orig_steps_var_values,
2226 &step.self_ty,
2227 ) else {
2228 debug!("failed to instantiate self_ty");
2229 return false;
2230 };
2231 let ocx = ObligationCtxt::new(self);
2232 let self_ty = ocx.register_infer_ok_obligations(ok);
2233 if !ocx.select_where_possible().is_empty() {
2234 debug!("failed to prove instantiate self_ty obligations");
2235 return false;
2236 }
2237
2238 !self.resolve_vars_if_possible(self_ty).is_ty_var()
2239 });
2240 if constrained_opaque {
2241 debug!("opaque type has been constrained");
2242 return true;
2243 }
2244 }
2245 }
2246
2247 false
2248 }
2249
2250 fn collapse_candidates_to_trait_pick(
2268 &self,
2269 self_ty: Ty<'tcx>,
2270 probes: &[(&Candidate<'tcx>, ProbeResult)],
2271 ) -> Option<Pick<'tcx>> {
2272 let container = probes[0].0.item.trait_container(self.tcx)?;
2274 for (p, _) in &probes[1..] {
2275 let p_container = p.item.trait_container(self.tcx)?;
2276 if p_container != container {
2277 return None;
2278 }
2279 }
2280
2281 Some(Pick {
2284 item: probes[0].0.item,
2285 kind: TraitPick,
2286 import_ids: probes[0].0.import_ids.clone(),
2287 autoderefs: 0,
2288 autoref_or_ptr_adjustment: None,
2289 self_ty,
2290 unstable_candidates: vec![],
2291 receiver_steps: None,
2292 shadowed_candidates: vec![],
2293 })
2294 }
2295
2296 fn collapse_candidates_to_subtrait_pick(
2302 &self,
2303 self_ty: Ty<'tcx>,
2304 probes: &[(&Candidate<'tcx>, ProbeResult)],
2305 ) -> Option<Pick<'tcx>> {
2306 let mut child_candidate = probes[0].0;
2307 let mut child_trait = child_candidate.item.trait_container(self.tcx)?;
2308 let mut supertraits: SsoHashSet<_> = supertrait_def_ids(self.tcx, child_trait).collect();
2309
2310 let mut remaining_candidates: Vec<_> = probes[1..].iter().map(|&(p, _)| p).collect();
2311 while !remaining_candidates.is_empty() {
2312 let mut made_progress = false;
2313 let mut next_round = vec![];
2314
2315 for remaining_candidate in remaining_candidates {
2316 let remaining_trait = remaining_candidate.item.trait_container(self.tcx)?;
2317 if supertraits.contains(&remaining_trait) {
2318 made_progress = true;
2319 continue;
2320 }
2321
2322 let remaining_trait_supertraits: SsoHashSet<_> =
2328 supertrait_def_ids(self.tcx, remaining_trait).collect();
2329 if remaining_trait_supertraits.contains(&child_trait) {
2330 child_candidate = remaining_candidate;
2331 child_trait = remaining_trait;
2332 supertraits = remaining_trait_supertraits;
2333 made_progress = true;
2334 continue;
2335 }
2336
2337 next_round.push(remaining_candidate);
2343 }
2344
2345 if made_progress {
2346 remaining_candidates = next_round;
2348 } else {
2349 return None;
2352 }
2353 }
2354
2355 Some(Pick {
2356 item: child_candidate.item,
2357 kind: TraitPick,
2358 import_ids: child_candidate.import_ids.clone(),
2359 autoderefs: 0,
2360 autoref_or_ptr_adjustment: None,
2361 self_ty,
2362 unstable_candidates: vec![],
2363 shadowed_candidates: probes
2364 .iter()
2365 .map(|(c, _)| c.item)
2366 .filter(|item| item.def_id != child_candidate.item.def_id)
2367 .collect(),
2368 receiver_steps: None,
2369 })
2370 }
2371
2372 #[instrument(level = "debug", skip(self))]
2376 pub(crate) fn probe_for_similar_candidate(
2377 &mut self,
2378 ) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
2379 debug!("probing for method names similar to {:?}", self.method_name);
2380
2381 self.probe(|_| {
2382 let mut pcx = ProbeContext::new(
2383 self.fcx,
2384 self.span,
2385 self.mode,
2386 self.method_name,
2387 self.return_type,
2388 self.orig_steps_var_values,
2389 self.steps,
2390 self.scope_expr_id,
2391 IsSuggestion(true),
2392 );
2393 pcx.allow_similar_names = true;
2394 pcx.assemble_inherent_candidates();
2395 pcx.assemble_extension_candidates_for_all_traits();
2396
2397 let method_names = pcx.candidate_method_names(|_| true);
2398 pcx.allow_similar_names = false;
2399 let applicable_close_candidates: Vec<ty::AssocItem> = method_names
2400 .iter()
2401 .filter_map(|&method_name| {
2402 pcx.reset();
2403 pcx.method_name = Some(method_name);
2404 pcx.assemble_inherent_candidates();
2405 pcx.assemble_extension_candidates_for_all_traits();
2406 pcx.pick_core(&mut Vec::new()).and_then(|pick| pick.ok()).map(|pick| pick.item)
2407 })
2408 .collect();
2409
2410 if applicable_close_candidates.is_empty() {
2411 Ok(None)
2412 } else {
2413 let best_name = {
2414 let names = applicable_close_candidates
2415 .iter()
2416 .map(|cand| cand.name())
2417 .collect::<Vec<Symbol>>();
2418 find_best_match_for_name_with_substrings(
2419 &names,
2420 self.method_name.unwrap().name,
2421 None,
2422 )
2423 }
2424 .or_else(|| {
2425 applicable_close_candidates
2426 .iter()
2427 .find(|cand| self.matches_by_doc_alias(cand.def_id))
2428 .map(|cand| cand.name())
2429 });
2430 Ok(best_name.and_then(|best_name| {
2431 applicable_close_candidates
2432 .into_iter()
2433 .find(|method| method.name() == best_name)
2434 }))
2435 }
2436 })
2437 }
2438
2439 fn has_applicable_self(&self, item: &ty::AssocItem) -> bool {
2442 match self.mode {
2448 Mode::MethodCall => item.is_method(),
2449 Mode::Path => match item.kind {
2450 ty::AssocKind::Type { .. } => false,
2451 ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => true,
2452 },
2453 }
2454 }
2461
2462 fn record_static_candidate(&self, source: CandidateSource) {
2463 self.static_candidates.borrow_mut().push(source);
2464 }
2465
2466 #[instrument(level = "debug", skip(self))]
2467 fn xform_self_ty(
2468 &self,
2469 item: ty::AssocItem,
2470 impl_ty: Ty<'tcx>,
2471 args: GenericArgsRef<'tcx>,
2472 ) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
2473 if item.is_fn() && self.mode == Mode::MethodCall {
2474 let sig = self.xform_method_sig(item.def_id, args);
2475 (sig.inputs()[0], Some(sig.output()))
2476 } else {
2477 (impl_ty, None)
2478 }
2479 }
2480
2481 #[instrument(level = "debug", skip(self))]
2482 fn xform_method_sig(&self, method: DefId, args: GenericArgsRef<'tcx>) -> ty::FnSig<'tcx> {
2483 let fn_sig = self.tcx.fn_sig(method);
2484 debug!(?fn_sig);
2485
2486 assert!(!args.has_escaping_bound_vars());
2487
2488 let generics = self.tcx.generics_of(method);
2494 assert_eq!(args.len(), generics.parent_count);
2495
2496 let xform_fn_sig = if generics.is_own_empty() {
2497 fn_sig.instantiate(self.tcx, args)
2498 } else {
2499 let args = GenericArgs::for_item(self.tcx, method, |param, _| {
2500 let i = param.index as usize;
2501 if i < args.len() {
2502 args[i]
2503 } else {
2504 match param.kind {
2505 GenericParamDefKind::Lifetime => {
2506 self.tcx.lifetimes.re_erased.into()
2508 }
2509 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
2510 self.var_for_def(self.span, param)
2511 }
2512 }
2513 }
2514 });
2515 fn_sig.instantiate(self.tcx, args)
2516 };
2517
2518 self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig)
2519 }
2520
2521 fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
2523 match (self.mode, kind) {
2524 (Mode::MethodCall, ty::AssocKind::Fn { .. }) => true,
2525 (Mode::Path, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. }) => true,
2526 _ => false,
2527 }
2528 }
2529
2530 fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
2533 let Some(method) = self.method_name else {
2534 return false;
2535 };
2536 let Some(local_def_id) = def_id.as_local() else {
2537 return false;
2538 };
2539 let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
2540 let attrs = self.fcx.tcx.hir_attrs(hir_id);
2541
2542 if is_doc_alias_attrs_contain_symbol(attrs.into_iter(), method.name) {
2543 return true;
2544 }
2545
2546 for attr in attrs {
2547 if attr.has_name(sym::rustc_confusables) {
2548 let Some(confusables) = attr.meta_item_list() else {
2549 continue;
2550 };
2551 for n in confusables {
2553 if let Some(lit) = n.lit()
2554 && method.name == lit.symbol
2555 {
2556 return true;
2557 }
2558 }
2559 }
2560 }
2561 false
2562 }
2563
2564 fn impl_or_trait_item(&self, def_id: DefId) -> SmallVec<[ty::AssocItem; 1]> {
2569 if let Some(name) = self.method_name {
2570 if self.allow_similar_names {
2571 let max_dist = max(name.as_str().len(), 3) / 3;
2572 self.tcx
2573 .associated_items(def_id)
2574 .in_definition_order()
2575 .filter(|x| {
2576 if !self.is_relevant_kind_for_mode(x.kind) {
2577 return false;
2578 }
2579 if let Some(d) = edit_distance_with_substrings(
2580 name.as_str(),
2581 x.name().as_str(),
2582 max_dist,
2583 ) {
2584 return d > 0;
2585 }
2586 self.matches_by_doc_alias(x.def_id)
2587 })
2588 .copied()
2589 .collect()
2590 } else {
2591 self.fcx
2592 .associated_value(def_id, name)
2593 .filter(|x| self.is_relevant_kind_for_mode(x.kind))
2594 .map_or_else(SmallVec::new, |x| SmallVec::from_buf([x]))
2595 }
2596 } else {
2597 self.tcx
2598 .associated_items(def_id)
2599 .in_definition_order()
2600 .filter(|x| self.is_relevant_kind_for_mode(x.kind))
2601 .copied()
2602 .collect()
2603 }
2604 }
2605}
2606
2607impl<'tcx> Candidate<'tcx> {
2608 fn to_unadjusted_pick(
2609 &self,
2610 self_ty: Ty<'tcx>,
2611 unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
2612 ) -> Pick<'tcx> {
2613 Pick {
2614 item: self.item,
2615 kind: match self.kind {
2616 InherentImplCandidate { .. } => InherentImplPick,
2617 ObjectCandidate(_) => ObjectPick,
2618 TraitCandidate(_) => TraitPick,
2619 WhereClauseCandidate(trait_ref) => {
2620 assert!(
2626 !trait_ref.skip_binder().args.has_infer()
2627 && !trait_ref.skip_binder().args.has_placeholders()
2628 );
2629
2630 WhereClausePick(trait_ref)
2631 }
2632 },
2633 import_ids: self.import_ids.clone(),
2634 autoderefs: 0,
2635 autoref_or_ptr_adjustment: None,
2636 self_ty,
2637 unstable_candidates,
2638 receiver_steps: match self.kind {
2639 InherentImplCandidate { receiver_steps, .. } => Some(receiver_steps),
2640 _ => None,
2641 },
2642 shadowed_candidates: vec![],
2643 }
2644 }
2645}