• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
3 
4 use crate::errors;
5 use crate::errors::CandidateTraitNote;
6 use crate::errors::NoAssociatedItem;
7 use crate::Expectation;
8 use crate::FnCtxt;
9 use rustc_ast::ast::Mutability;
10 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11 use rustc_errors::StashKey;
12 use rustc_errors::{
13     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
14     MultiSpan,
15 };
16 use rustc_hir as hir;
17 use rustc_hir::def::DefKind;
18 use rustc_hir::def_id::DefId;
19 use rustc_hir::lang_items::LangItem;
20 use rustc_hir::PatKind::Binding;
21 use rustc_hir::PathSegment;
22 use rustc_hir::{ExprKind, Node, QPath};
23 use rustc_infer::infer::{
24     type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
25     RegionVariableOrigin,
26 };
27 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
28 use rustc_middle::traits::util::supertraits;
29 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
30 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
31 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
32 use rustc_middle::ty::IsSuggestable;
33 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
34 use rustc_span::symbol::{kw, sym, Ident};
35 use rustc_span::Symbol;
36 use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
37 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
38 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
39 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
40 use rustc_trait_selection::traits::{
41     FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
42 };
43 use std::borrow::Cow;
44 
45 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
46 use super::{CandidateSource, MethodError, NoMatchData};
47 use rustc_hir::intravisit::Visitor;
48 use std::cmp::{self, Ordering};
49 use std::iter;
50 
51 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool52     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
53         let tcx = self.tcx;
54         match ty.kind() {
55             // Not all of these (e.g., unsafe fns) implement `FnOnce`,
56             // so we look for these beforehand.
57             ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
58             // If it's not a simple function, look for things which implement `FnOnce`.
59             _ => {
60                 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
61                     return false;
62                 };
63 
64                 // This conditional prevents us from asking to call errors and unresolved types.
65                 // It might seem that we can use `predicate_must_hold_modulo_regions`,
66                 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
67                 // type resolution always gives a "maybe" here.
68                 if self.autoderef(span, ty).any(|(ty, _)| {
69                     info!("check deref {:?} error", ty);
70                     matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
71                 }) {
72                     return false;
73                 }
74 
75                 self.autoderef(span, ty).any(|(ty, _)| {
76                     info!("check deref {:?} impl FnOnce", ty);
77                     self.probe(|_| {
78                         let trait_ref = ty::TraitRef::new(
79                             tcx,
80                             fn_once,
81                             [
82                                 ty,
83                                 self.next_ty_var(TypeVariableOrigin {
84                                     kind: TypeVariableOriginKind::MiscVariable,
85                                     span,
86                                 }),
87                             ],
88                         );
89                         let poly_trait_ref = ty::Binder::dummy(trait_ref);
90                         let obligation = Obligation::misc(
91                             tcx,
92                             span,
93                             self.body_id,
94                             self.param_env,
95                             poly_trait_ref.without_const(),
96                         );
97                         self.predicate_may_hold(&obligation)
98                     })
99                 })
100             }
101         }
102     }
103 
is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool104     fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
105         self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
106     }
107 
108     #[instrument(level = "debug", skip(self))]
report_method_error( &self, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>>109     pub fn report_method_error(
110         &self,
111         span: Span,
112         rcvr_ty: Ty<'tcx>,
113         item_name: Ident,
114         source: SelfSource<'tcx>,
115         error: MethodError<'tcx>,
116         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
117         expected: Expectation<'tcx>,
118         trait_missing_method: bool,
119     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
120         // Avoid suggestions when we don't know what's going on.
121         if rcvr_ty.references_error() {
122             return None;
123         }
124 
125         let sugg_span = if let SelfSource::MethodCall(expr) = source {
126             // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
127             self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)).span
128         } else {
129             span
130         };
131 
132         match error {
133             MethodError::NoMatch(mut no_match_data) => {
134                 return self.report_no_match_method_error(
135                     span,
136                     rcvr_ty,
137                     item_name,
138                     source,
139                     args,
140                     sugg_span,
141                     &mut no_match_data,
142                     expected,
143                     trait_missing_method,
144                 );
145             }
146 
147             MethodError::Ambiguity(mut sources) => {
148                 let mut err = struct_span_err!(
149                     self.sess(),
150                     item_name.span,
151                     E0034,
152                     "multiple applicable items in scope"
153                 );
154                 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
155 
156                 self.note_candidates_on_method_error(
157                     rcvr_ty,
158                     item_name,
159                     args,
160                     span,
161                     &mut err,
162                     &mut sources,
163                     Some(sugg_span),
164                 );
165                 err.emit();
166             }
167 
168             MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
169                 let kind = self.tcx.def_kind_descr(kind, def_id);
170                 let mut err = struct_span_err!(
171                     self.tcx.sess,
172                     item_name.span,
173                     E0624,
174                     "{} `{}` is private",
175                     kind,
176                     item_name
177                 );
178                 err.span_label(item_name.span, format!("private {}", kind));
179                 let sp = self
180                     .tcx
181                     .hir()
182                     .span_if_local(def_id)
183                     .unwrap_or_else(|| self.tcx.def_span(def_id));
184                 err.span_label(sp, format!("private {} defined here", kind));
185                 self.suggest_valid_traits(&mut err, out_of_scope_traits);
186                 err.emit();
187             }
188 
189             MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
190                 let msg = if needs_mut {
191                     with_forced_trimmed_paths!(format!(
192                         "the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
193                     ))
194                 } else {
195                     format!("the `{item_name}` method cannot be invoked on a trait object")
196                 };
197                 let mut err = self.sess().struct_span_err(span, msg);
198                 if !needs_mut {
199                     err.span_label(bound_span, "this has a `Sized` requirement");
200                 }
201                 if !candidates.is_empty() {
202                     let help = format!(
203                         "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
204                          add a `use` for {one_of_them}:",
205                         an = if candidates.len() == 1 { "an" } else { "" },
206                         s = pluralize!(candidates.len()),
207                         were = pluralize!("was", candidates.len()),
208                         one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
209                     );
210                     self.suggest_use_candidates(&mut err, help, candidates);
211                 }
212                 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
213                     if needs_mut {
214                         let trait_type = Ty::new_ref(
215                             self.tcx,
216                             *region,
217                             ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
218                         );
219                         let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
220                         let mut kind = &self_expr.kind;
221                         while let hir::ExprKind::AddrOf(_, _, expr)
222                         | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
223                         {
224                             kind = &expr.kind;
225                         }
226                         if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
227                             && let hir::def::Res::Local(hir_id) = path.res
228                             && let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
229                             && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
230                             && let Some(node) = self.tcx.hir().find_parent(p.hir_id)
231                             && let Some(decl) = node.fn_decl()
232                             && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
233                             && let hir::TyKind::Ref(_, mut_ty) = &ty.kind
234                             && let hir::Mutability::Not = mut_ty.mutbl
235                         {
236                             err.span_suggestion_verbose(
237                                 mut_ty.ty.span.shrink_to_lo(),
238                                 msg,
239                                 "mut ",
240                                 Applicability::MachineApplicable,
241                             );
242                         } else {
243                             err.help(msg);
244                         }
245                     }
246                 }
247                 err.emit();
248             }
249 
250             MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
251         }
252         None
253     }
254 
suggest_missing_writer( &self, rcvr_ty: Ty<'tcx>, args: (&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>]), ) -> DiagnosticBuilder<'_, ErrorGuaranteed>255     fn suggest_missing_writer(
256         &self,
257         rcvr_ty: Ty<'tcx>,
258         args: (&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>]),
259     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
260         let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
261         let mut err =
262             struct_span_err!(self.tcx.sess, args.0.span, E0599, "cannot write into `{}`", ty_str);
263         err.span_note(
264             args.0.span,
265             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
266         );
267         if let ExprKind::Lit(_) = args.0.kind {
268             err.span_help(
269                 args.0.span.shrink_to_lo(),
270                 "a writer is needed before this format string",
271             );
272         };
273 
274         err
275     }
276 
report_no_match_method_error( &self, mut span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, sugg_span: Span, no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>>277     pub fn report_no_match_method_error(
278         &self,
279         mut span: Span,
280         rcvr_ty: Ty<'tcx>,
281         item_name: Ident,
282         source: SelfSource<'tcx>,
283         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
284         sugg_span: Span,
285         no_match_data: &mut NoMatchData<'tcx>,
286         expected: Expectation<'tcx>,
287         trait_missing_method: bool,
288     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
289         let mode = no_match_data.mode;
290         let tcx = self.tcx;
291         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
292         let ((mut ty_str, ty_file), short_ty_str) = if trait_missing_method
293             && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
294                 ((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
295             } else {
296                 (tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
297             };
298         let is_method = mode == Mode::MethodCall;
299         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
300         let similar_candidate = no_match_data.similar_candidate;
301         let item_kind = if is_method {
302             "method"
303         } else if rcvr_ty.is_enum() {
304             "variant or associated item"
305         } else {
306             match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
307                 (Some(name), false) if name.is_lowercase() => "function or associated item",
308                 (Some(_), false) => "associated item",
309                 (Some(_), true) | (None, false) => "variant or associated item",
310                 (None, true) => "variant",
311             }
312         };
313 
314         // We could pass the file for long types into these two, but it isn't strictly necessary
315         // given how targeted they are.
316         if self.suggest_wrapping_range_with_parens(
317             tcx,
318             rcvr_ty,
319             source,
320             span,
321             item_name,
322             &short_ty_str,
323         ) || self.suggest_constraining_numerical_ty(
324             tcx,
325             rcvr_ty,
326             source,
327             span,
328             item_kind,
329             item_name,
330             &short_ty_str,
331         ) {
332             return None;
333         }
334         span = item_name.span;
335 
336         // Don't show generic arguments when the method can't be found in any implementation (#81576).
337         let mut ty_str_reported = ty_str.clone();
338         if let ty::Adt(_, generics) = rcvr_ty.kind() {
339             if generics.len() > 0 {
340                 let mut autoderef = self.autoderef(span, rcvr_ty);
341                 let candidate_found = autoderef.any(|(ty, _)| {
342                     if let ty::Adt(adt_def, _) = ty.kind() {
343                         self.tcx
344                             .inherent_impls(adt_def.did())
345                             .iter()
346                             .any(|def_id| self.associated_value(*def_id, item_name).is_some())
347                     } else {
348                         false
349                     }
350                 });
351                 let has_deref = autoderef.step_count() > 0;
352                 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
353                     if let Some((path_string, _)) = ty_str.split_once('<') {
354                         ty_str_reported = path_string.to_string();
355                     }
356                 }
357             }
358         }
359 
360         let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
361             tcx.is_diagnostic_item(sym::write_macro, def_id)
362                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
363         }) && item_name.name == Symbol::intern("write_fmt");
364         let mut err = if is_write
365             && let Some(args) = args
366         {
367             self.suggest_missing_writer(rcvr_ty, args)
368         } else {
369             tcx.sess.create_err(NoAssociatedItem {
370                 span,
371                 item_kind,
372                 item_name,
373                 ty_prefix: if trait_missing_method {
374                     // FIXME(mu001999) E0599 maybe not suitable here because it is for types
375                     Cow::from("trait")
376                 } else {
377                     rcvr_ty.prefix_string(self.tcx)
378                 },
379                 ty_str: ty_str_reported,
380                 trait_missing_method,
381             })
382         };
383         if tcx.sess.source_map().is_multiline(sugg_span) {
384             err.span_label(sugg_span.with_hi(span.lo()), "");
385         }
386 
387         if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
388             ty_str = short_ty_str;
389         }
390 
391         if let Some(file) = ty_file {
392             err.note(format!("the full type name has been written to '{}'", file.display(),));
393         }
394         if rcvr_ty.references_error() {
395             err.downgrade_to_delayed_bug();
396         }
397 
398         if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
399             err.help(format!(
400                 "method `poll` found on `Pin<&mut {ty_str}>`, \
401                 see documentation for `std::pin::Pin`"
402             ));
403             err.help("self type must be pinned to call `Future::poll`, \
404                 see https://rust-lang.github.io/async-book/04_pinning/01_chapter.html#pinning-in-practice"
405             );
406         }
407 
408         if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
409             self.suggest_await_before_method(
410                 &mut err, item_name, rcvr_ty, cal, span, expected.only_has_type(self),
411             );
412         }
413         if let Some(span) =
414             tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
415         {
416             err.span_suggestion(
417                 span.shrink_to_lo(),
418                 "you are looking for the module in `std`, not the primitive type",
419                 "std::",
420                 Applicability::MachineApplicable,
421             );
422         }
423         if let ty::RawPtr(_) = &rcvr_ty.kind() {
424             err.note(
425                 "try using `<*const T>::as_ref()` to get a reference to the \
426                  type behind the pointer: https://doc.rust-lang.org/std/\
427                  primitive.pointer.html#method.as_ref",
428             );
429             err.note(
430                 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
431                  to invalid or uninitialized memory is undefined behavior",
432             );
433         }
434 
435         let ty_span = match rcvr_ty.kind() {
436             ty::Param(param_type) => {
437                 Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
438             }
439             ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
440             _ => None,
441         };
442         if let Some(span) = ty_span {
443             err.span_label(
444                 span,
445                 format!(
446                     "{item_kind} `{item_name}` not found for this {}",
447                     rcvr_ty.prefix_string(self.tcx)
448                 ),
449             );
450         }
451 
452         if let SelfSource::MethodCall(rcvr_expr) = source {
453             self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
454                 let call_expr =
455                     self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id));
456                 let probe = self.lookup_probe_for_diagnostic(
457                     item_name,
458                     output_ty,
459                     call_expr,
460                     ProbeScope::AllTraits,
461                     expected.only_has_type(self),
462                 );
463                 probe.is_ok()
464             });
465 
466             self.note_internal_mutation_in_method(
467                 &mut err,
468                 rcvr_expr,
469                 expected.to_option(&self),
470                 rcvr_ty,
471             );
472         }
473 
474         let mut custom_span_label = false;
475 
476         let static_candidates = &mut no_match_data.static_candidates;
477 
478         // `static_candidates` may have same candidates appended by
479         // inherent and extension, which may result in incorrect
480         // diagnostic.
481         static_candidates.dedup();
482 
483         if !static_candidates.is_empty() {
484             err.note(
485                 "found the following associated functions; to be used as methods, \
486                  functions must have a `self` parameter",
487             );
488             err.span_label(span, "this is an associated function, not a method");
489             custom_span_label = true;
490         }
491         if static_candidates.len() == 1 {
492             self.suggest_associated_call_syntax(
493                 &mut err,
494                 &static_candidates,
495                 rcvr_ty,
496                 source,
497                 item_name,
498                 args,
499                 sugg_span,
500             );
501             self.note_candidates_on_method_error(
502                 rcvr_ty,
503                 item_name,
504                 args,
505                 span,
506                 &mut err,
507                 static_candidates,
508                 None,
509             );
510         } else if static_candidates.len() > 1 {
511             self.note_candidates_on_method_error(
512                 rcvr_ty,
513                 item_name,
514                 args,
515                 span,
516                 &mut err,
517                 static_candidates,
518                 Some(sugg_span),
519             );
520         }
521 
522         let mut bound_spans = vec![];
523         let mut restrict_type_params = false;
524         let mut unsatisfied_bounds = false;
525         if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
526             let msg = "consider using `len` instead";
527             if let SelfSource::MethodCall(_expr) = source {
528                 err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
529             } else {
530                 err.span_label(span, msg);
531             }
532             if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
533                 let iterator_trait = self.tcx.def_path_str(iterator_trait);
534                 err.note(format!(
535                     "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
536                 ));
537             }
538         } else if !unsatisfied_predicates.is_empty() {
539             let mut type_params = FxHashMap::default();
540 
541             // Pick out the list of unimplemented traits on the receiver.
542             // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
543             let mut unimplemented_traits = FxHashMap::default();
544             let mut unimplemented_traits_only = true;
545             for (predicate, _parent_pred, cause) in unsatisfied_predicates {
546                 if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) =
547                     (predicate.kind().skip_binder(), cause.as_ref())
548                 {
549                     if p.trait_ref.self_ty() != rcvr_ty {
550                         // This is necessary, not just to keep the errors clean, but also
551                         // because our derived obligations can wind up with a trait ref that
552                         // requires a different param_env to be correctly compared.
553                         continue;
554                     }
555                     unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
556                         predicate.kind().rebind(p.trait_ref),
557                         Obligation {
558                             cause: cause.clone(),
559                             param_env: self.param_env,
560                             predicate: *predicate,
561                             recursion_depth: 0,
562                         },
563                     ));
564                 }
565             }
566 
567             // Make sure that, if any traits other than the found ones were involved,
568             // we don't don't report an unimplemented trait.
569             // We don't want to say that `iter::Cloned` is not an iterator, just
570             // because of some non-Clone item being iterated over.
571             for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
572                 match predicate.kind().skip_binder() {
573                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))
574                         if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
575                     _ => {
576                         unimplemented_traits_only = false;
577                         break;
578                     }
579                 }
580             }
581 
582             let mut collect_type_param_suggestions =
583                 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
584                     // We don't care about regions here, so it's fine to skip the binder here.
585                     if let (ty::Param(_), ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))) =
586                         (self_ty.kind(), parent_pred.kind().skip_binder())
587                     {
588                         let hir = self.tcx.hir();
589                         let node = match p.trait_ref.self_ty().kind() {
590                             ty::Param(_) => {
591                                 // Account for `fn` items like in `issue-35677.rs` to
592                                 // suggest restricting its type params.
593                                 Some(hir.get_by_def_id(self.body_id))
594                             }
595                             ty::Adt(def, _) => {
596                                 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
597                             }
598                             _ => None,
599                         };
600                         if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
601                             && let Some(g) = kind.generics()
602                         {
603                             let key = (
604                                 g.tail_span_for_predicate_suggestion(),
605                                 g.add_where_or_trailing_comma(),
606                             );
607                             type_params
608                                 .entry(key)
609                                 .or_insert_with(FxHashSet::default)
610                                 .insert(obligation.to_owned());
611                             return true;
612                         }
613                     }
614                     false
615                 };
616             let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
617                 let msg = format!(
618                     "doesn't satisfy `{}`",
619                     if obligation.len() > 50 { quiet } else { obligation }
620                 );
621                 match &self_ty.kind() {
622                     // Point at the type that couldn't satisfy the bound.
623                     ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
624                     // Point at the trait object that couldn't satisfy the bound.
625                     ty::Dynamic(preds, _, _) => {
626                         for pred in preds.iter() {
627                             match pred.skip_binder() {
628                                 ty::ExistentialPredicate::Trait(tr) => {
629                                     bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
630                                 }
631                                 ty::ExistentialPredicate::Projection(_)
632                                 | ty::ExistentialPredicate::AutoTrait(_) => {}
633                             }
634                         }
635                     }
636                     // Point at the closure that couldn't satisfy the bound.
637                     ty::Closure(def_id, _) => bound_spans
638                         .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
639                     _ => {}
640                 }
641             };
642             let mut format_pred = |pred: ty::Predicate<'tcx>| {
643                 let bound_predicate = pred.kind();
644                 match bound_predicate.skip_binder() {
645                     ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
646                         let pred = bound_predicate.rebind(pred);
647                         // `<Foo as Iterator>::Item = String`.
648                         let projection_ty = pred.skip_binder().projection_ty;
649 
650                         let substs_with_infer_self = tcx.mk_substs_from_iter(
651                             iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into())
652                                 .chain(projection_ty.substs.iter().skip(1)),
653                         );
654 
655                         let quiet_projection_ty =
656                             tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
657 
658                         let term = pred.skip_binder().term;
659 
660                         let obligation = format!("{} = {}", projection_ty, term);
661                         let quiet = with_forced_trimmed_paths!(format!(
662                             "{} = {}",
663                             quiet_projection_ty, term
664                         ));
665 
666                         bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
667                         Some((obligation, projection_ty.self_ty()))
668                     }
669                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
670                         let p = poly_trait_ref.trait_ref;
671                         let self_ty = p.self_ty();
672                         let path = p.print_only_trait_path();
673                         let obligation = format!("{}: {}", self_ty, path);
674                         let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
675                         bound_span_label(self_ty, &obligation, &quiet);
676                         Some((obligation, self_ty))
677                     }
678                     _ => None,
679                 }
680             };
681 
682             // Find all the requirements that come from a local `impl` block.
683             let mut skip_list: FxHashSet<_> = Default::default();
684             let mut spanned_predicates = FxHashMap::default();
685             for (p, parent_p, cause) in unsatisfied_predicates {
686                 // Extract the predicate span and parent def id of the cause,
687                 // if we have one.
688                 let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) {
689                     Some(ObligationCauseCode::ImplDerivedObligation(data)) => {
690                         (data.impl_or_alias_def_id, data.span)
691                     }
692                     Some(
693                         ObligationCauseCode::ExprBindingObligation(def_id, span, _, _)
694                         | ObligationCauseCode::BindingObligation(def_id, span),
695                     ) => (*def_id, *span),
696                     _ => continue,
697                 };
698 
699                 // Don't point out the span of `WellFormed` predicates.
700                 if !matches!(
701                     p.kind().skip_binder(),
702                     ty::PredicateKind::Clause(
703                         ty::ClauseKind::Projection(..) | ty::ClauseKind::Trait(..)
704                     )
705                 ) {
706                     continue;
707                 };
708 
709                 match self.tcx.hir().get_if_local(item_def_id) {
710                     // Unmet obligation comes from a `derive` macro, point at it once to
711                     // avoid multiple span labels pointing at the same place.
712                     Some(Node::Item(hir::Item {
713                         kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
714                         ..
715                     })) if matches!(
716                         self_ty.span.ctxt().outer_expn_data().kind,
717                         ExpnKind::Macro(MacroKind::Derive, _)
718                     ) || matches!(
719                         of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
720                         Some(ExpnKind::Macro(MacroKind::Derive, _))
721                     ) =>
722                     {
723                         let span = self_ty.span.ctxt().outer_expn_data().call_site;
724                         let entry = spanned_predicates.entry(span);
725                         let entry = entry.or_insert_with(|| {
726                             (FxHashSet::default(), FxHashSet::default(), Vec::new())
727                         });
728                         entry.0.insert(span);
729                         entry.1.insert((
730                             span,
731                             "unsatisfied trait bound introduced in this `derive` macro",
732                         ));
733                         entry.2.push(p);
734                         skip_list.insert(p);
735                     }
736 
737                     // Unmet obligation coming from an `impl`.
738                     Some(Node::Item(hir::Item {
739                         kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
740                         span: item_span,
741                         ..
742                     })) => {
743                         let sized_pred =
744                             unsatisfied_predicates.iter().any(|(pred, _, _)| {
745                                 match pred.kind().skip_binder() {
746                                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
747                                         Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
748                                             && pred.polarity == ty::ImplPolarity::Positive
749                                     }
750                                     _ => false,
751                                 }
752                             });
753                         for param in generics.params {
754                             if param.span == cause_span && sized_pred {
755                                 let (sp, sugg) = match param.colon_span {
756                                     Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
757                                     None => (param.span.shrink_to_hi(), ": ?Sized"),
758                                 };
759                                 err.span_suggestion_verbose(
760                                     sp,
761                                     "consider relaxing the type parameter's implicit `Sized` bound",
762                                     sugg,
763                                     Applicability::MachineApplicable,
764                                 );
765                             }
766                         }
767                         if let Some(pred) = parent_p {
768                             // Done to add the "doesn't satisfy" `span_label`.
769                             let _ = format_pred(*pred);
770                         }
771                         skip_list.insert(p);
772                         let entry = spanned_predicates.entry(self_ty.span);
773                         let entry = entry.or_insert_with(|| {
774                             (FxHashSet::default(), FxHashSet::default(), Vec::new())
775                         });
776                         entry.2.push(p);
777                         if cause_span != *item_span {
778                             entry.0.insert(cause_span);
779                             entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
780                         } else {
781                             if let Some(trait_ref) = of_trait {
782                                 entry.0.insert(trait_ref.path.span);
783                             }
784                             entry.0.insert(self_ty.span);
785                         };
786                         if let Some(trait_ref) = of_trait {
787                             entry.1.insert((trait_ref.path.span, ""));
788                         }
789                         entry.1.insert((self_ty.span, ""));
790                     }
791                     Some(Node::Item(hir::Item {
792                         kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
793                         span: item_span,
794                         ..
795                     })) => {
796                         tcx.sess.delay_span_bug(
797                             *item_span,
798                             "auto trait is invoked with no method error, but no error reported?",
799                         );
800                     }
801                     Some(Node::Item(hir::Item {
802                         ident,
803                         kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
804                         ..
805                     })) => {
806                         skip_list.insert(p);
807                         let entry = spanned_predicates.entry(ident.span);
808                         let entry = entry.or_insert_with(|| {
809                             (FxHashSet::default(), FxHashSet::default(), Vec::new())
810                         });
811                         entry.0.insert(cause_span);
812                         entry.1.insert((ident.span, ""));
813                         entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
814                         entry.2.push(p);
815                     }
816                     Some(node) => unreachable!("encountered `{node:?}`"),
817                     None => (),
818                 }
819             }
820             let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
821             spanned_predicates.sort_by_key(|(span, _)| *span);
822             for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
823                 let mut preds: Vec<_> = predicates
824                     .iter()
825                     .filter_map(|pred| format_pred(**pred))
826                     .map(|(p, _)| format!("`{}`", p))
827                     .collect();
828                 preds.sort();
829                 preds.dedup();
830                 let msg = if let [pred] = &preds[..] {
831                     format!("trait bound {} was not satisfied", pred)
832                 } else {
833                     format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
834                 };
835                 let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
836                 for (sp, label) in span_labels {
837                     span.push_span_label(sp, label);
838                 }
839                 err.span_note(span, msg);
840                 unsatisfied_bounds = true;
841             }
842 
843             let mut suggested_bounds = FxHashSet::default();
844             // The requirements that didn't have an `impl` span to show.
845             let mut bound_list = unsatisfied_predicates
846                 .iter()
847                 .filter_map(|(pred, parent_pred, _cause)| {
848                     let mut suggested = false;
849                     format_pred(*pred).map(|(p, self_ty)| {
850                         if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
851                             // We don't suggest `PartialEq` when we already suggest `Eq`.
852                         } else if !suggested_bounds.contains(pred) {
853                             if collect_type_param_suggestions(self_ty, *pred, &p) {
854                                 suggested = true;
855                                 suggested_bounds.insert(pred);
856                             }
857                         }
858                         (
859                             match parent_pred {
860                                 None => format!("`{}`", &p),
861                                 Some(parent_pred) => match format_pred(*parent_pred) {
862                                     None => format!("`{}`", &p),
863                                     Some((parent_p, _)) => {
864                                         if !suggested
865                                             && !suggested_bounds.contains(pred)
866                                             && !suggested_bounds.contains(parent_pred)
867                                         {
868                                             if collect_type_param_suggestions(
869                                                 self_ty,
870                                                 *parent_pred,
871                                                 &p,
872                                             ) {
873                                                 suggested_bounds.insert(pred);
874                                             }
875                                         }
876                                         format!("`{}`\nwhich is required by `{}`", p, parent_p)
877                                     }
878                                 },
879                             },
880                             *pred,
881                         )
882                     })
883                 })
884                 .filter(|(_, pred)| !skip_list.contains(&pred))
885                 .map(|(t, _)| t)
886                 .enumerate()
887                 .collect::<Vec<(usize, String)>>();
888 
889             for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
890                 restrict_type_params = true;
891                 // #74886: Sort here so that the output is always the same.
892                 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
893                 obligations.sort();
894                 err.span_suggestion_verbose(
895                     span,
896                     format!(
897                         "consider restricting the type parameter{s} to satisfy the \
898                          trait bound{s}",
899                         s = pluralize!(obligations.len())
900                     ),
901                     format!("{} {}", add_where_or_comma, obligations.join(", ")),
902                     Applicability::MaybeIncorrect,
903                 );
904             }
905 
906             bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
907             bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
908             bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
909 
910             if !bound_list.is_empty() || !skip_list.is_empty() {
911                 let bound_list =
912                     bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
913                 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
914                 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
915                 let (primary_message, label) = if unimplemented_traits.len() == 1
916                     && unimplemented_traits_only
917                 {
918                     unimplemented_traits
919                         .into_iter()
920                         .next()
921                         .map(|(_, (trait_ref, obligation))| {
922                             if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
923                             {
924                                 // Avoid crashing.
925                                 return (None, None);
926                             }
927                             let OnUnimplementedNote { message, label, .. } =
928                                 self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
929                             (message, label)
930                         })
931                         .unwrap()
932                 } else {
933                     (None, None)
934                 };
935                 let primary_message = primary_message.unwrap_or_else(|| {
936                     format!(
937                         "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
938                          but its trait bounds were not satisfied"
939                     )
940                 });
941                 err.set_primary_message(primary_message);
942                 if let Some(label) = label {
943                     custom_span_label = true;
944                     err.span_label(span, label);
945                 }
946                 if !bound_list.is_empty() {
947                     err.note(format!(
948                         "the following trait bounds were not satisfied:\n{bound_list}"
949                     ));
950                 }
951                 self.suggest_derive(&mut err, &unsatisfied_predicates);
952 
953                 unsatisfied_bounds = true;
954             }
955         }
956 
957         let label_span_not_found = |err: &mut Diagnostic| {
958             if unsatisfied_predicates.is_empty() {
959                 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
960                 let is_string_or_ref_str = match rcvr_ty.kind() {
961                     ty::Ref(_, ty, _) => {
962                         ty.is_str()
963                             || matches!(
964                                 ty.kind(),
965                                 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
966                             )
967                     }
968                     ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
969                     _ => false,
970                 };
971                 if is_string_or_ref_str && item_name.name == sym::iter {
972                     err.span_suggestion_verbose(
973                         item_name.span,
974                         "because of the in-memory representation of `&str`, to obtain \
975                          an `Iterator` over each of its codepoint use method `chars`",
976                         "chars",
977                         Applicability::MachineApplicable,
978                     );
979                 }
980                 if let ty::Adt(adt, _) = rcvr_ty.kind() {
981                     let mut inherent_impls_candidate = self
982                         .tcx
983                         .inherent_impls(adt.did())
984                         .iter()
985                         .copied()
986                         .filter(|def_id| {
987                             if let Some(assoc) = self.associated_value(*def_id, item_name) {
988                                 // Check for both mode is the same so we avoid suggesting
989                                 // incorrect associated item.
990                                 match (mode, assoc.fn_has_self_parameter, source) {
991                                     (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
992                                         // We check that the suggest type is actually
993                                         // different from the received one
994                                         // So we avoid suggestion method with Box<Self>
995                                         // for instance
996                                         self.tcx.at(span).type_of(*def_id).subst_identity()
997                                             != rcvr_ty
998                                             && self.tcx.at(span).type_of(*def_id).subst_identity()
999                                                 != rcvr_ty
1000                                     }
1001                                     (Mode::Path, false, _) => true,
1002                                     _ => false,
1003                                 }
1004                             } else {
1005                                 false
1006                             }
1007                         })
1008                         .collect::<Vec<_>>();
1009                     if !inherent_impls_candidate.is_empty() {
1010                         inherent_impls_candidate.sort();
1011                         inherent_impls_candidate.dedup();
1012 
1013                         // number of type to shows at most.
1014                         let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
1015                         let type_candidates = inherent_impls_candidate
1016                             .iter()
1017                             .take(limit)
1018                             .map(|impl_item| {
1019                                 format!(
1020                                     "- `{}`",
1021                                     self.tcx.at(span).type_of(*impl_item).subst_identity()
1022                                 )
1023                             })
1024                             .collect::<Vec<_>>()
1025                             .join("\n");
1026                         let additional_types = if inherent_impls_candidate.len() > limit {
1027                             format!("\nand {} more types", inherent_impls_candidate.len() - limit)
1028                         } else {
1029                             "".to_string()
1030                         };
1031                         err.note(format!(
1032                             "the {item_kind} was found for\n{}{}",
1033                             type_candidates, additional_types
1034                         ));
1035                     }
1036                 }
1037             } else {
1038                 let ty_str =
1039                     if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
1040                 err.span_label(
1041                     span,
1042                     format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
1043                 );
1044             }
1045         };
1046 
1047         // If the method name is the name of a field with a function or closure type,
1048         // give a helping note that it has to be called as `(x.f)(...)`.
1049         if let SelfSource::MethodCall(expr) = source {
1050             if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
1051                 && similar_candidate.is_none()
1052                 && !custom_span_label
1053             {
1054                 label_span_not_found(&mut err);
1055             }
1056         } else if !custom_span_label {
1057             label_span_not_found(&mut err);
1058         }
1059 
1060         // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
1061         // can't be called due to `typeof(expr): Clone` not holding.
1062         if unsatisfied_predicates.is_empty() {
1063             self.suggest_calling_method_on_field(
1064                 &mut err,
1065                 source,
1066                 span,
1067                 rcvr_ty,
1068                 item_name,
1069                 expected.only_has_type(self),
1070             );
1071         }
1072 
1073         self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name);
1074 
1075         bound_spans.sort();
1076         bound_spans.dedup();
1077         for (span, msg) in bound_spans.into_iter() {
1078             err.span_label(span, msg);
1079         }
1080 
1081         if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
1082         } else {
1083             self.suggest_traits_to_import(
1084                 &mut err,
1085                 span,
1086                 rcvr_ty,
1087                 item_name,
1088                 args.map(|(_, args)| args.len() + 1),
1089                 source,
1090                 no_match_data.out_of_scope_traits.clone(),
1091                 &unsatisfied_predicates,
1092                 &static_candidates,
1093                 unsatisfied_bounds,
1094                 expected.only_has_type(self),
1095                 trait_missing_method,
1096             );
1097         }
1098 
1099         // Don't emit a suggestion if we found an actual method
1100         // that had unsatisfied trait bounds
1101         if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
1102             let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
1103             if let Some(suggestion) = edit_distance::find_best_match_for_name(
1104                 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1105                 item_name.name,
1106                 None,
1107             ) {
1108                 err.span_suggestion(
1109                     span,
1110                     "there is a variant with a similar name",
1111                     suggestion,
1112                     Applicability::MaybeIncorrect,
1113                 );
1114             }
1115         }
1116 
1117         if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
1118             let msg = "remove this method call";
1119             let mut fallback_span = true;
1120             if let SelfSource::MethodCall(expr) = source {
1121                 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1122                 if let Some(span) = call_expr.span.trim_start(expr.span) {
1123                     err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1124                     fallback_span = false;
1125                 }
1126             }
1127             if fallback_span {
1128                 err.span_label(span, msg);
1129             }
1130         } else if let Some(similar_candidate) = similar_candidate {
1131             // Don't emit a suggestion if we found an actual method
1132             // that had unsatisfied trait bounds
1133             if unsatisfied_predicates.is_empty() {
1134                 let def_kind = similar_candidate.kind.as_def_kind();
1135                 // Methods are defined within the context of a struct and their first parameter is always self,
1136                 // which represents the instance of the struct the method is being called on
1137                 // Associated functions don’t take self as a parameter and
1138                 // they are not methods because they don’t have an instance of the struct to work with.
1139                 if def_kind == DefKind::AssocFn && similar_candidate.fn_has_self_parameter {
1140                     err.span_suggestion(
1141                         span,
1142                         "there is a method with a similar name",
1143                         similar_candidate.name,
1144                         Applicability::MaybeIncorrect,
1145                     );
1146                 } else {
1147                     err.span_suggestion(
1148                         span,
1149                         format!(
1150                             "there is {} {} with a similar name",
1151                             self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id),
1152                             self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
1153                         ),
1154                         similar_candidate.name,
1155                         Applicability::MaybeIncorrect,
1156                     );
1157                 }
1158             }
1159         }
1160 
1161         self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
1162         return Some(err);
1163     }
1164 
note_candidates_on_method_error( &self, rcvr_ty: Ty<'tcx>, item_name: Ident, args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, span: Span, err: &mut Diagnostic, sources: &mut Vec<CandidateSource>, sugg_span: Option<Span>, )1165     fn note_candidates_on_method_error(
1166         &self,
1167         rcvr_ty: Ty<'tcx>,
1168         item_name: Ident,
1169         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1170         span: Span,
1171         err: &mut Diagnostic,
1172         sources: &mut Vec<CandidateSource>,
1173         sugg_span: Option<Span>,
1174     ) {
1175         sources.sort();
1176         sources.dedup();
1177         // Dynamic limit to avoid hiding just one candidate, which is silly.
1178         let limit = if sources.len() == 5 { 5 } else { 4 };
1179 
1180         for (idx, source) in sources.iter().take(limit).enumerate() {
1181             match *source {
1182                 CandidateSource::Impl(impl_did) => {
1183                     // Provide the best span we can. Use the item, if local to crate, else
1184                     // the impl, if local to crate (item may be defaulted), else nothing.
1185                     let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
1186                         let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
1187                         self.associated_value(impl_trait_ref.skip_binder().def_id, item_name)
1188                     }) else {
1189                         continue;
1190                     };
1191 
1192                     let note_span = if item.def_id.is_local() {
1193                         Some(self.tcx.def_span(item.def_id))
1194                     } else if impl_did.is_local() {
1195                         Some(self.tcx.def_span(impl_did))
1196                     } else {
1197                         None
1198                     };
1199 
1200                     let impl_ty = self.tcx.at(span).type_of(impl_did).subst_identity();
1201 
1202                     let insertion = match self.tcx.impl_trait_ref(impl_did) {
1203                         None => String::new(),
1204                         Some(trait_ref) => {
1205                             format!(
1206                                 " of the trait `{}`",
1207                                 self.tcx.def_path_str(trait_ref.skip_binder().def_id)
1208                             )
1209                         }
1210                     };
1211 
1212                     let (note_str, idx) = if sources.len() > 1 {
1213                         (
1214                             format!(
1215                                 "candidate #{} is defined in an impl{} for the type `{}`",
1216                                 idx + 1,
1217                                 insertion,
1218                                 impl_ty,
1219                             ),
1220                             Some(idx + 1),
1221                         )
1222                     } else {
1223                         (
1224                             format!(
1225                                 "the candidate is defined in an impl{} for the type `{}`",
1226                                 insertion, impl_ty,
1227                             ),
1228                             None,
1229                         )
1230                     };
1231                     if let Some(note_span) = note_span {
1232                         // We have a span pointing to the method. Show note with snippet.
1233                         err.span_note(note_span, note_str);
1234                     } else {
1235                         err.note(note_str);
1236                     }
1237                     if let Some(sugg_span) = sugg_span
1238                         && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
1239                         let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
1240 
1241                         let ty = match item.kind {
1242                             ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
1243                             ty::AssocKind::Fn => self
1244                                 .tcx
1245                                 .fn_sig(item.def_id)
1246                                 .subst_identity()
1247                                 .inputs()
1248                                 .skip_binder()
1249                                 .get(0)
1250                                 .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref())
1251                                 .copied()
1252                                 .unwrap_or(rcvr_ty),
1253                         };
1254                         print_disambiguation_help(
1255                             item_name,
1256                             args,
1257                             err,
1258                             path,
1259                             ty,
1260                             item.kind,
1261                             self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
1262                             sugg_span,
1263                             idx,
1264                             self.tcx.sess.source_map(),
1265                             item.fn_has_self_parameter,
1266                         );
1267                     }
1268                 }
1269                 CandidateSource::Trait(trait_did) => {
1270                     let Some(item) = self.associated_value(trait_did, item_name) else { continue };
1271                     let item_span = self.tcx.def_span(item.def_id);
1272                     let idx = if sources.len() > 1 {
1273                         let msg = format!(
1274                             "candidate #{} is defined in the trait `{}`",
1275                             idx + 1,
1276                             self.tcx.def_path_str(trait_did)
1277                         );
1278                         err.span_note(item_span, msg);
1279                         Some(idx + 1)
1280                     } else {
1281                         let msg = format!(
1282                             "the candidate is defined in the trait `{}`",
1283                             self.tcx.def_path_str(trait_did)
1284                         );
1285                         err.span_note(item_span, msg);
1286                         None
1287                     };
1288                     if let Some(sugg_span) = sugg_span {
1289                         let path = self.tcx.def_path_str(trait_did);
1290                         print_disambiguation_help(
1291                             item_name,
1292                             args,
1293                             err,
1294                             path,
1295                             rcvr_ty,
1296                             item.kind,
1297                             self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
1298                             sugg_span,
1299                             idx,
1300                             self.tcx.sess.source_map(),
1301                             item.fn_has_self_parameter,
1302                         );
1303                     }
1304                 }
1305             }
1306         }
1307         if sources.len() > limit {
1308             err.note(format!("and {} others", sources.len() - limit));
1309         }
1310     }
1311 
1312     /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1313     /// doesn't take a `self` receiver.
suggest_associated_call_syntax( &self, err: &mut Diagnostic, static_candidates: &Vec<CandidateSource>, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>, sugg_span: Span, )1314     fn suggest_associated_call_syntax(
1315         &self,
1316         err: &mut Diagnostic,
1317         static_candidates: &Vec<CandidateSource>,
1318         rcvr_ty: Ty<'tcx>,
1319         source: SelfSource<'tcx>,
1320         item_name: Ident,
1321         args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1322         sugg_span: Span,
1323     ) {
1324         let mut has_unsuggestable_args = false;
1325         let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1326             // When the "method" is resolved through dereferencing, we really want the
1327             // original type that has the associated function for accurate suggestions.
1328             // (#61411)
1329             let impl_ty = self.tcx.type_of(*impl_did).subst_identity();
1330             let target_ty = self
1331                 .autoderef(sugg_span, rcvr_ty)
1332                 .find(|(rcvr_ty, _)| {
1333                     DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }
1334                         .types_may_unify(*rcvr_ty, impl_ty)
1335                 })
1336                 .map_or(impl_ty, |(ty, _)| ty)
1337                 .peel_refs();
1338             if let ty::Adt(def, substs) = target_ty.kind() {
1339                 // If there are any inferred arguments, (`{integer}`), we should replace
1340                 // them with underscores to allow the compiler to infer them
1341                 let infer_substs = self.tcx.mk_substs_from_iter(substs.into_iter().map(|arg| {
1342                     if !arg.is_suggestable(self.tcx, true) {
1343                         has_unsuggestable_args = true;
1344                         match arg.unpack() {
1345                             GenericArgKind::Lifetime(_) => self
1346                                 .next_region_var(RegionVariableOrigin::MiscVariable(
1347                                     rustc_span::DUMMY_SP,
1348                                 ))
1349                                 .into(),
1350                             GenericArgKind::Type(_) => self
1351                                 .next_ty_var(TypeVariableOrigin {
1352                                     span: rustc_span::DUMMY_SP,
1353                                     kind: TypeVariableOriginKind::MiscVariable,
1354                                 })
1355                                 .into(),
1356                             GenericArgKind::Const(arg) => self
1357                                 .next_const_var(
1358                                     arg.ty(),
1359                                     ConstVariableOrigin {
1360                                         span: rustc_span::DUMMY_SP,
1361                                         kind: ConstVariableOriginKind::MiscVariable,
1362                                     },
1363                                 )
1364                                 .into(),
1365                         }
1366                     } else {
1367                         arg
1368                     }
1369                 }));
1370 
1371                 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1372             } else {
1373                 self.ty_to_value_string(target_ty)
1374             }
1375         } else {
1376             self.ty_to_value_string(rcvr_ty.peel_refs())
1377         };
1378         if let SelfSource::MethodCall(_) = source {
1379             let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1380                 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1381                 && assoc.kind == ty::AssocKind::Fn
1382             {
1383                 let sig = self.tcx.fn_sig(assoc.def_id).subst_identity();
1384                 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1385                     None
1386                 } else {
1387                     Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1388                 })
1389             } else {
1390                 None
1391             };
1392             let mut applicability = Applicability::MachineApplicable;
1393             let args = if let Some((receiver, args)) = args {
1394                 // The first arg is the same kind as the receiver
1395                 let explicit_args = if first_arg.is_some() {
1396                     std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1397                 } else {
1398                     // There is no `Self` kind to infer the arguments from
1399                     if has_unsuggestable_args {
1400                         applicability = Applicability::HasPlaceholders;
1401                     }
1402                     args.iter().collect()
1403                 };
1404                 format!(
1405                     "({}{})",
1406                     first_arg.unwrap_or(""),
1407                     explicit_args
1408                         .iter()
1409                         .map(|arg| self
1410                             .tcx
1411                             .sess
1412                             .source_map()
1413                             .span_to_snippet(arg.span)
1414                             .unwrap_or_else(|_| {
1415                                 applicability = Applicability::HasPlaceholders;
1416                                 "_".to_owned()
1417                             }))
1418                         .collect::<Vec<_>>()
1419                         .join(", "),
1420                 )
1421             } else {
1422                 applicability = Applicability::HasPlaceholders;
1423                 "(...)".to_owned()
1424             };
1425             err.span_suggestion(
1426                 sugg_span,
1427                 "use associated function syntax instead",
1428                 format!("{}::{}{}", ty_str, item_name, args),
1429                 applicability,
1430             );
1431         } else {
1432             err.help(format!("try with `{}::{}`", ty_str, item_name,));
1433         }
1434     }
1435 
1436     /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1437     /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
suggest_calling_field_as_fn( &self, span: Span, rcvr_ty: Ty<'tcx>, expr: &hir::Expr<'_>, item_name: Ident, err: &mut Diagnostic, ) -> bool1438     fn suggest_calling_field_as_fn(
1439         &self,
1440         span: Span,
1441         rcvr_ty: Ty<'tcx>,
1442         expr: &hir::Expr<'_>,
1443         item_name: Ident,
1444         err: &mut Diagnostic,
1445     ) -> bool {
1446         let tcx = self.tcx;
1447         let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1448             ty::Adt(def, substs) if !def.is_enum() => {
1449                 let variant = &def.non_enum_variant();
1450                 tcx.find_field_index(item_name, variant).map(|index| {
1451                     let field = &variant.fields[index];
1452                     let field_ty = field.ty(tcx, substs);
1453                     (field, field_ty)
1454                 })
1455             }
1456             _ => None,
1457         });
1458         if let Some((field, field_ty)) = field_receiver {
1459             let scope = tcx.parent_module_from_def_id(self.body_id);
1460             let is_accessible = field.vis.is_accessible_from(scope, tcx);
1461 
1462             if is_accessible {
1463                 if self.is_fn_ty(field_ty, span) {
1464                     let expr_span = expr.span.to(item_name.span);
1465                     err.multipart_suggestion(
1466                         format!(
1467                             "to call the function stored in `{}`, \
1468                                          surround the field access with parentheses",
1469                             item_name,
1470                         ),
1471                         vec![
1472                             (expr_span.shrink_to_lo(), '('.to_string()),
1473                             (expr_span.shrink_to_hi(), ')'.to_string()),
1474                         ],
1475                         Applicability::MachineApplicable,
1476                     );
1477                 } else {
1478                     let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1479 
1480                     if let Some(span) = call_expr.span.trim_start(item_name.span) {
1481                         err.span_suggestion(
1482                             span,
1483                             "remove the arguments",
1484                             "",
1485                             Applicability::MaybeIncorrect,
1486                         );
1487                     }
1488                 }
1489             }
1490 
1491             let field_kind = if is_accessible { "field" } else { "private field" };
1492             err.span_label(item_name.span, format!("{}, not a method", field_kind));
1493             return true;
1494         }
1495         false
1496     }
1497 
1498     /// Suggest possible range with adding parentheses, for example:
1499     /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
suggest_wrapping_range_with_parens( &self, tcx: TyCtxt<'tcx>, actual: Ty<'tcx>, source: SelfSource<'tcx>, span: Span, item_name: Ident, ty_str: &str, ) -> bool1500     fn suggest_wrapping_range_with_parens(
1501         &self,
1502         tcx: TyCtxt<'tcx>,
1503         actual: Ty<'tcx>,
1504         source: SelfSource<'tcx>,
1505         span: Span,
1506         item_name: Ident,
1507         ty_str: &str,
1508     ) -> bool {
1509         if let SelfSource::MethodCall(expr) = source {
1510             for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1511                 if let Node::Expr(parent_expr) = parent {
1512                     let lang_item = match parent_expr.kind {
1513                         ExprKind::Struct(ref qpath, _, _) => match **qpath {
1514                             QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1515                             QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1516                             QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1517                                 Some(LangItem::RangeToInclusive)
1518                             }
1519                             _ => None,
1520                         },
1521                         ExprKind::Call(ref func, _) => match func.kind {
1522                             // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1523                             ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1524                                 Some(LangItem::RangeInclusiveStruct)
1525                             }
1526                             _ => None,
1527                         },
1528                         _ => None,
1529                     };
1530 
1531                     if lang_item.is_none() {
1532                         continue;
1533                     }
1534 
1535                     let span_included = match parent_expr.kind {
1536                         hir::ExprKind::Struct(_, eps, _) => {
1537                             eps.len() > 0 && eps.last().is_some_and(|ep| ep.span.contains(span))
1538                         }
1539                         // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1540                         hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1541                         _ => false,
1542                     };
1543 
1544                     if !span_included {
1545                         continue;
1546                     }
1547 
1548                     let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1549                     let range_ty = self.tcx.type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1550 
1551                     let pick = self.lookup_probe_for_diagnostic(
1552                         item_name,
1553                         range_ty,
1554                         expr,
1555                         ProbeScope::AllTraits,
1556                         None,
1557                     );
1558                     if pick.is_ok() {
1559                         let range_span = parent_expr.span.with_hi(expr.span.hi());
1560                         tcx.sess.emit_err(errors::MissingParenthesesInRange {
1561                             span,
1562                             ty_str: ty_str.to_string(),
1563                             method_name: item_name.as_str().to_string(),
1564                             add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1565                                 func_name: item_name.name.as_str().to_string(),
1566                                 left: range_span.shrink_to_lo(),
1567                                 right: range_span.shrink_to_hi(),
1568                             }),
1569                         });
1570                         return true;
1571                     }
1572                 }
1573             }
1574         }
1575         false
1576     }
1577 
suggest_constraining_numerical_ty( &self, tcx: TyCtxt<'tcx>, actual: Ty<'tcx>, source: SelfSource<'_>, span: Span, item_kind: &str, item_name: Ident, ty_str: &str, ) -> bool1578     fn suggest_constraining_numerical_ty(
1579         &self,
1580         tcx: TyCtxt<'tcx>,
1581         actual: Ty<'tcx>,
1582         source: SelfSource<'_>,
1583         span: Span,
1584         item_kind: &str,
1585         item_name: Ident,
1586         ty_str: &str,
1587     ) -> bool {
1588         let found_candidate = all_traits(self.tcx)
1589             .into_iter()
1590             .any(|info| self.associated_value(info.def_id, item_name).is_some());
1591         let found_assoc = |ty: Ty<'tcx>| {
1592             simplify_type(tcx, ty, TreatParams::AsCandidateKey)
1593                 .and_then(|simp| {
1594                     tcx.incoherent_impls(simp)
1595                         .iter()
1596                         .find_map(|&id| self.associated_value(id, item_name))
1597                 })
1598                 .is_some()
1599         };
1600         let found_candidate = found_candidate
1601             || found_assoc(tcx.types.i8)
1602             || found_assoc(tcx.types.i16)
1603             || found_assoc(tcx.types.i32)
1604             || found_assoc(tcx.types.i64)
1605             || found_assoc(tcx.types.i128)
1606             || found_assoc(tcx.types.u8)
1607             || found_assoc(tcx.types.u16)
1608             || found_assoc(tcx.types.u32)
1609             || found_assoc(tcx.types.u64)
1610             || found_assoc(tcx.types.u128)
1611             || found_assoc(tcx.types.f32)
1612             || found_assoc(tcx.types.f32);
1613         if found_candidate
1614             && actual.is_numeric()
1615             && !actual.has_concrete_skeleton()
1616             && let SelfSource::MethodCall(expr) = source
1617         {
1618             let mut err = struct_span_err!(
1619                 tcx.sess,
1620                 span,
1621                 E0689,
1622                 "can't call {} `{}` on ambiguous numeric type `{}`",
1623                 item_kind,
1624                 item_name,
1625                 ty_str
1626             );
1627             let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1628             match expr.kind {
1629                 ExprKind::Lit(ref lit) => {
1630                     // numeric literal
1631                     let snippet = tcx
1632                         .sess
1633                         .source_map()
1634                         .span_to_snippet(lit.span)
1635                         .unwrap_or_else(|_| "<numeric literal>".to_owned());
1636 
1637                     // If this is a floating point literal that ends with '.',
1638                     // get rid of it to stop this from becoming a member access.
1639                     let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1640                     err.span_suggestion(
1641                         lit.span,
1642                         format!(
1643                             "you must specify a concrete type for this numeric value, \
1644                                          like `{}`",
1645                             concrete_type
1646                         ),
1647                         format!("{snippet}_{concrete_type}"),
1648                         Applicability::MaybeIncorrect,
1649                     );
1650                 }
1651                 ExprKind::Path(QPath::Resolved(_, path)) => {
1652                     // local binding
1653                     if let hir::def::Res::Local(hir_id) = path.res {
1654                         let span = tcx.hir().span(hir_id);
1655                         let filename = tcx.sess.source_map().span_to_filename(span);
1656 
1657                         let parent_node =
1658                             self.tcx.hir().get_parent(hir_id);
1659                         let msg = format!(
1660                             "you must specify a type for this binding, like `{}`",
1661                             concrete_type,
1662                         );
1663 
1664                         match (filename, parent_node) {
1665                             (
1666                                 FileName::Real(_),
1667                                 Node::Local(hir::Local {
1668                                     source: hir::LocalSource::Normal,
1669                                     ty,
1670                                     ..
1671                                 }),
1672                             ) => {
1673                                 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1674                                 err.span_suggestion(
1675                                     // account for `let x: _ = 42;`
1676                                     //                   ^^^
1677                                     type_span,
1678                                     msg,
1679                                     format!(": {concrete_type}"),
1680                                     Applicability::MaybeIncorrect,
1681                                 );
1682                             }
1683                             _ => {
1684                                 err.span_label(span, msg);
1685                             }
1686                         }
1687                     }
1688                 }
1689                 _ => {}
1690             }
1691             err.emit();
1692             return true;
1693         }
1694         false
1695     }
1696 
1697     /// For code `rect::area(...)`,
1698     /// if `rect` is a local variable and `area` is a valid assoc method for it,
1699     /// we try to suggest `rect.area()`
suggest_assoc_method_call(&self, segs: &[PathSegment<'_>])1700     pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1701         debug!("suggest_assoc_method_call segs: {:?}", segs);
1702         let [seg1, seg2] = segs else { return; };
1703         let Some(mut diag) =
1704                 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1705                 else { return };
1706 
1707         let map = self.infcx.tcx.hir();
1708         let body_id = self.tcx.hir().body_owned_by(self.body_id);
1709         let body = map.body(body_id);
1710         struct LetVisitor<'a> {
1711             result: Option<&'a hir::Expr<'a>>,
1712             ident_name: Symbol,
1713         }
1714 
1715         // FIXME: This really should be taking scoping, etc into account.
1716         impl<'v> Visitor<'v> for LetVisitor<'v> {
1717             fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1718                 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1719                     && let Binding(_, _, ident, ..) = pat.kind
1720                     && ident.name == self.ident_name
1721                 {
1722                     self.result = *init;
1723                 } else {
1724                     hir::intravisit::walk_stmt(self, ex);
1725                 }
1726             }
1727         }
1728 
1729         let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1730         visitor.visit_body(&body);
1731 
1732         let parent = self.tcx.hir().parent_id(seg1.hir_id);
1733         if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1734             && let Some(expr) = visitor.result
1735             && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1736         {
1737             let probe = self.lookup_probe_for_diagnostic(
1738                 seg2.ident,
1739                 self_ty,
1740                 call_expr,
1741                 ProbeScope::TraitsInScope,
1742                 None,
1743             );
1744             if probe.is_ok() {
1745                 let sm = self.infcx.tcx.sess.source_map();
1746                 diag.span_suggestion_verbose(
1747                     sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1748                     "you may have meant to call an instance method",
1749                     ".".to_string(),
1750                     Applicability::MaybeIncorrect,
1751                 );
1752             }
1753         }
1754         diag.emit();
1755     }
1756 
1757     /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
suggest_calling_method_on_field( &self, err: &mut Diagnostic, source: SelfSource<'tcx>, span: Span, actual: Ty<'tcx>, item_name: Ident, return_type: Option<Ty<'tcx>>, )1758     fn suggest_calling_method_on_field(
1759         &self,
1760         err: &mut Diagnostic,
1761         source: SelfSource<'tcx>,
1762         span: Span,
1763         actual: Ty<'tcx>,
1764         item_name: Ident,
1765         return_type: Option<Ty<'tcx>>,
1766     ) {
1767         if let SelfSource::MethodCall(expr) = source
1768         && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1769         && let Some((fields, substs)) =
1770             self.get_field_candidates_considering_privacy(span, actual, mod_id)
1771         {
1772             let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1773 
1774             let lang_items = self.tcx.lang_items();
1775             let never_mention_traits = [
1776                 lang_items.clone_trait(),
1777                 lang_items.deref_trait(),
1778                 lang_items.deref_mut_trait(),
1779                 self.tcx.get_diagnostic_item(sym::AsRef),
1780                 self.tcx.get_diagnostic_item(sym::AsMut),
1781                 self.tcx.get_diagnostic_item(sym::Borrow),
1782                 self.tcx.get_diagnostic_item(sym::BorrowMut),
1783             ];
1784             let candidate_fields: Vec<_> = fields
1785                 .filter_map(|candidate_field| {
1786                     self.check_for_nested_field_satisfying(
1787                         span,
1788                         &|_, field_ty| {
1789                             self.lookup_probe_for_diagnostic(
1790                                 item_name,
1791                                 field_ty,
1792                                 call_expr,
1793                                 ProbeScope::TraitsInScope,
1794                                 return_type,
1795                             )
1796                             .is_ok_and(|pick| {
1797                                 !never_mention_traits
1798                                     .iter()
1799                                     .flatten()
1800                                     .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1801                             })
1802                         },
1803                         candidate_field,
1804                         substs,
1805                         vec![],
1806                         mod_id,
1807                     )
1808                 })
1809                 .map(|field_path| {
1810                     field_path
1811                         .iter()
1812                         .map(|id| id.name.to_ident_string())
1813                         .collect::<Vec<String>>()
1814                         .join(".")
1815                 })
1816                 .collect();
1817 
1818             let len = candidate_fields.len();
1819             if len > 0 {
1820                 err.span_suggestions(
1821                     item_name.span.shrink_to_lo(),
1822                     format!(
1823                         "{} of the expressions' fields {} a method of the same name",
1824                         if len > 1 { "some" } else { "one" },
1825                         if len > 1 { "have" } else { "has" },
1826                     ),
1827                     candidate_fields.iter().map(|path| format!("{path}.")),
1828                     Applicability::MaybeIncorrect,
1829                 );
1830             }
1831         }
1832     }
1833 
suggest_unwrapping_inner_self( &self, err: &mut Diagnostic, source: SelfSource<'tcx>, actual: Ty<'tcx>, item_name: Ident, )1834     fn suggest_unwrapping_inner_self(
1835         &self,
1836         err: &mut Diagnostic,
1837         source: SelfSource<'tcx>,
1838         actual: Ty<'tcx>,
1839         item_name: Ident,
1840     ) {
1841         let tcx = self.tcx;
1842         let SelfSource::MethodCall(expr) = source else { return; };
1843         let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1844 
1845         let ty::Adt(kind, substs) = actual.kind() else { return; };
1846         match kind.adt_kind() {
1847             ty::AdtKind::Enum => {
1848                 let matching_variants: Vec<_> = kind
1849                     .variants()
1850                     .iter()
1851                     .flat_map(|variant| {
1852                         let [field] = &variant.fields.raw[..] else { return None; };
1853                         let field_ty = field.ty(tcx, substs);
1854 
1855                         // Skip `_`, since that'll just lead to ambiguity.
1856                         if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1857                             return None;
1858                         }
1859 
1860                         self.lookup_probe_for_diagnostic(
1861                             item_name,
1862                             field_ty,
1863                             call_expr,
1864                             ProbeScope::TraitsInScope,
1865                             None,
1866                         )
1867                         .ok()
1868                         .map(|pick| (variant, field, pick))
1869                     })
1870                     .collect();
1871 
1872                 let ret_ty_matches = |diagnostic_item| {
1873                     if let Some(ret_ty) = self
1874                         .ret_coercion
1875                         .as_ref()
1876                         .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1877                         && let ty::Adt(kind, _) = ret_ty.kind()
1878                         && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1879                     {
1880                         true
1881                     } else {
1882                         false
1883                     }
1884                 };
1885 
1886                 match &matching_variants[..] {
1887                     [(_, field, pick)] => {
1888                         let self_ty = field.ty(tcx, substs);
1889                         err.span_note(
1890                             tcx.def_span(pick.item.def_id),
1891                             format!("the method `{item_name}` exists on the type `{self_ty}`"),
1892                         );
1893                         let (article, kind, variant, question) =
1894                             if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1895                                 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1896                             } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1897                                 ("an", "Option", "None", ret_ty_matches(sym::Option))
1898                             } else {
1899                                 return;
1900                             };
1901                         if question {
1902                             err.span_suggestion_verbose(
1903                                 expr.span.shrink_to_hi(),
1904                                 format!(
1905                                     "use the `?` operator to extract the `{self_ty}` value, propagating \
1906                                     {article} `{kind}::{variant}` value to the caller"
1907                                 ),
1908                                 "?",
1909                                 Applicability::MachineApplicable,
1910                             );
1911                         } else {
1912                             err.span_suggestion_verbose(
1913                                 expr.span.shrink_to_hi(),
1914                                 format!(
1915                                     "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1916                                     panicking if the value is {article} `{kind}::{variant}`"
1917                                 ),
1918                                 ".expect(\"REASON\")",
1919                                 Applicability::HasPlaceholders,
1920                             );
1921                         }
1922                     }
1923                     // FIXME(compiler-errors): Support suggestions for other matching enum variants
1924                     _ => {}
1925                 }
1926             }
1927             // Target wrapper types - types that wrap or pretend to wrap another type,
1928             // perhaps this inner type is meant to be called?
1929             ty::AdtKind::Struct | ty::AdtKind::Union => {
1930                 let [first] = ***substs else { return; };
1931                 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1932                 let Ok(pick) = self.lookup_probe_for_diagnostic(
1933                     item_name,
1934                     ty,
1935                     call_expr,
1936                     ProbeScope::TraitsInScope,
1937                     None,
1938                 )  else { return; };
1939 
1940                 let name = self.ty_to_value_string(actual);
1941                 let inner_id = kind.did();
1942                 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1943                     pick.autoref_or_ptr_adjustment
1944                 {
1945                     Some(mutbl)
1946                 } else {
1947                     None
1948                 };
1949 
1950                 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1951                     err.help("use `with` or `try_with` to access thread local storage");
1952                 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1953                     err.help(format!(
1954                         "if this `{name}` has been initialized, \
1955                         use one of the `assume_init` methods to access the inner value"
1956                     ));
1957                 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1958                     let (suggestion, borrow_kind, panic_if) = match mutable {
1959                         Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1960                         Some(Mutability::Mut) => {
1961                             (".borrow_mut()", "mutably borrow", "any borrows exist")
1962                         }
1963                         None => return,
1964                     };
1965                     err.span_suggestion_verbose(
1966                         expr.span.shrink_to_hi(),
1967                         format!(
1968                             "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1969                             panicking if {panic_if}"
1970                         ),
1971                         suggestion,
1972                         Applicability::MaybeIncorrect,
1973                     );
1974                 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1975                     err.span_suggestion_verbose(
1976                         expr.span.shrink_to_hi(),
1977                         format!(
1978                             "use `.lock().unwrap()` to borrow the `{ty}`, \
1979                             blocking the current thread until it can be acquired"
1980                         ),
1981                         ".lock().unwrap()",
1982                         Applicability::MaybeIncorrect,
1983                     );
1984                 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1985                     let (suggestion, borrow_kind) = match mutable {
1986                         Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1987                         Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1988                         None => return,
1989                     };
1990                     err.span_suggestion_verbose(
1991                         expr.span.shrink_to_hi(),
1992                         format!(
1993                             "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1994                             blocking the current thread until it can be acquired"
1995                         ),
1996                         suggestion,
1997                         Applicability::MaybeIncorrect,
1998                     );
1999                 } else {
2000                     return;
2001                 };
2002 
2003                 err.span_note(
2004                     tcx.def_span(pick.item.def_id),
2005                     format!("the method `{item_name}` exists on the type `{ty}`"),
2006                 );
2007             }
2008         }
2009     }
2010 
note_unmet_impls_on_type( &self, err: &mut Diagnostic, errors: Vec<FulfillmentError<'tcx>>, )2011     pub(crate) fn note_unmet_impls_on_type(
2012         &self,
2013         err: &mut Diagnostic,
2014         errors: Vec<FulfillmentError<'tcx>>,
2015     ) {
2016         let all_local_types_needing_impls =
2017             errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
2018                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
2019                     match pred.self_ty().kind() {
2020                         ty::Adt(def, _) => def.did().is_local(),
2021                         _ => false,
2022                     }
2023                 }
2024                 _ => false,
2025             });
2026         let mut preds: Vec<_> = errors
2027             .iter()
2028             .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
2029                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred),
2030                 _ => None,
2031             })
2032             .collect();
2033         preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
2034         let def_ids = preds
2035             .iter()
2036             .filter_map(|pred| match pred.self_ty().kind() {
2037                 ty::Adt(def, _) => Some(def.did()),
2038                 _ => None,
2039             })
2040             .collect::<FxHashSet<_>>();
2041         let mut spans: MultiSpan = def_ids
2042             .iter()
2043             .filter_map(|def_id| {
2044                 let span = self.tcx.def_span(*def_id);
2045                 if span.is_dummy() { None } else { Some(span) }
2046             })
2047             .collect::<Vec<_>>()
2048             .into();
2049 
2050         for pred in &preds {
2051             match pred.self_ty().kind() {
2052                 ty::Adt(def, _) if def.did().is_local() => {
2053                     spans.push_span_label(
2054                         self.tcx.def_span(def.did()),
2055                         format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
2056                     );
2057                 }
2058                 _ => {}
2059             }
2060         }
2061 
2062         if all_local_types_needing_impls && spans.primary_span().is_some() {
2063             let msg = if preds.len() == 1 {
2064                 format!(
2065                     "an implementation of `{}` might be missing for `{}`",
2066                     preds[0].trait_ref.print_only_trait_path(),
2067                     preds[0].self_ty()
2068                 )
2069             } else {
2070                 format!(
2071                     "the following type{} would have to `impl` {} required trait{} for this \
2072                      operation to be valid",
2073                     pluralize!(def_ids.len()),
2074                     if def_ids.len() == 1 { "its" } else { "their" },
2075                     pluralize!(preds.len()),
2076                 )
2077             };
2078             err.span_note(spans, msg);
2079         }
2080 
2081         let preds: Vec<_> = errors
2082             .iter()
2083             .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
2084             .collect();
2085         self.suggest_derive(err, &preds);
2086     }
2087 
suggest_derive( &self, err: &mut Diagnostic, unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, )], )2088     pub fn suggest_derive(
2089         &self,
2090         err: &mut Diagnostic,
2091         unsatisfied_predicates: &[(
2092             ty::Predicate<'tcx>,
2093             Option<ty::Predicate<'tcx>>,
2094             Option<ObligationCause<'tcx>>,
2095         )],
2096     ) {
2097         let mut derives = Vec::<(String, Span, Symbol)>::new();
2098         let mut traits = Vec::new();
2099         for (pred, _, _) in unsatisfied_predicates {
2100             let Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) =
2101                 pred.kind().no_bound_vars()
2102             else {
2103                 continue
2104             };
2105             let adt = match trait_pred.self_ty().ty_adt_def() {
2106                 Some(adt) if adt.did().is_local() => adt,
2107                 _ => continue,
2108             };
2109             if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
2110                 let can_derive = match diagnostic_name {
2111                     sym::Default => !adt.is_enum(),
2112                     sym::Eq
2113                     | sym::PartialEq
2114                     | sym::Ord
2115                     | sym::PartialOrd
2116                     | sym::Clone
2117                     | sym::Copy
2118                     | sym::Hash
2119                     | sym::Debug => true,
2120                     _ => false,
2121                 };
2122                 if can_derive {
2123                     let self_name = trait_pred.self_ty().to_string();
2124                     let self_span = self.tcx.def_span(adt.did());
2125                     for super_trait in
2126                         supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
2127                     {
2128                         if let Some(parent_diagnostic_name) =
2129                             self.tcx.get_diagnostic_name(super_trait.def_id())
2130                         {
2131                             derives.push((self_name.clone(), self_span, parent_diagnostic_name));
2132                         }
2133                     }
2134                     derives.push((self_name, self_span, diagnostic_name));
2135                 } else {
2136                     traits.push(trait_pred.def_id());
2137                 }
2138             } else {
2139                 traits.push(trait_pred.def_id());
2140             }
2141         }
2142         traits.sort();
2143         traits.dedup();
2144 
2145         derives.sort();
2146         derives.dedup();
2147 
2148         let mut derives_grouped = Vec::<(String, Span, String)>::new();
2149         for (self_name, self_span, trait_name) in derives.into_iter() {
2150             if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2151             {
2152                 if last_self_name == &self_name {
2153                     last_trait_names.push_str(format!(", {}", trait_name).as_str());
2154                     continue;
2155                 }
2156             }
2157             derives_grouped.push((self_name, self_span, trait_name.to_string()));
2158         }
2159 
2160         let len = traits.len();
2161         if len > 0 {
2162             let span =
2163                 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
2164             let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
2165             for (i, &did) in traits.iter().enumerate().skip(1) {
2166                 if len > 2 {
2167                     names.push_str(", ");
2168                 }
2169                 if i == len - 1 {
2170                     names.push_str(" and ");
2171                 }
2172                 names.push('`');
2173                 names.push_str(&self.tcx.def_path_str(did));
2174                 names.push('`');
2175             }
2176             err.span_note(
2177                 span,
2178                 format!("the trait{} {} must be implemented", pluralize!(len), names),
2179             );
2180         }
2181 
2182         for (self_name, self_span, traits) in &derives_grouped {
2183             err.span_suggestion_verbose(
2184                 self_span.shrink_to_lo(),
2185                 format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
2186                 format!("#[derive({})]\n", traits),
2187                 Applicability::MaybeIncorrect,
2188             );
2189         }
2190     }
2191 
note_derefed_ty_has_method( &self, err: &mut Diagnostic, self_source: SelfSource<'tcx>, rcvr_ty: Ty<'tcx>, item_name: Ident, expected: Expectation<'tcx>, )2192     fn note_derefed_ty_has_method(
2193         &self,
2194         err: &mut Diagnostic,
2195         self_source: SelfSource<'tcx>,
2196         rcvr_ty: Ty<'tcx>,
2197         item_name: Ident,
2198         expected: Expectation<'tcx>,
2199     ) {
2200         let SelfSource::QPath(ty) = self_source else { return; };
2201         for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
2202             if let Ok(pick) = self.probe_for_name(
2203                 Mode::Path,
2204                 item_name,
2205                 expected.only_has_type(self),
2206                 IsSuggestion(true),
2207                 deref_ty,
2208                 ty.hir_id,
2209                 ProbeScope::TraitsInScope,
2210             ) {
2211                 if deref_ty.is_suggestable(self.tcx, true)
2212                     // If this method receives `&self`, then the provided
2213                     // argument _should_ coerce, so it's valid to suggest
2214                     // just changing the path.
2215                     && pick.item.fn_has_self_parameter
2216                     && let Some(self_ty) =
2217                         self.tcx.fn_sig(pick.item.def_id).subst_identity().inputs().skip_binder().get(0)
2218                     && self_ty.is_ref()
2219                 {
2220                     let suggested_path = match deref_ty.kind() {
2221                         ty::Bool
2222                         | ty::Char
2223                         | ty::Int(_)
2224                         | ty::Uint(_)
2225                         | ty::Float(_)
2226                         | ty::Adt(_, _)
2227                         | ty::Str
2228                         | ty::Alias(ty::Projection | ty::Inherent, _)
2229                         | ty::Param(_) => format!("{deref_ty}"),
2230                         // we need to test something like  <&[_]>::len or <(&[u32])>::len
2231                         // and Vec::function();
2232                         // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2233                         // but for Adt type like Vec::function()
2234                         // we would suggest <[_]>::function();
2235                         _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span)  => format!("{deref_ty}"),
2236                         _ => format!("<{deref_ty}>"),
2237                     };
2238                     err.span_suggestion_verbose(
2239                         ty.span,
2240                         format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2241                         suggested_path,
2242                         Applicability::MaybeIncorrect,
2243                     );
2244                 } else {
2245                     err.span_note(
2246                         ty.span,
2247                         format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2248                     );
2249                 }
2250                 return;
2251             }
2252         }
2253     }
2254 
2255     /// Print out the type for use in value namespace.
ty_to_value_string(&self, ty: Ty<'tcx>) -> String2256     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2257         match ty.kind() {
2258             ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2259             _ => self.ty_to_string(ty),
2260         }
2261     }
2262 
suggest_await_before_method( &self, err: &mut Diagnostic, item_name: Ident, ty: Ty<'tcx>, call: &hir::Expr<'_>, span: Span, return_type: Option<Ty<'tcx>>, )2263     fn suggest_await_before_method(
2264         &self,
2265         err: &mut Diagnostic,
2266         item_name: Ident,
2267         ty: Ty<'tcx>,
2268         call: &hir::Expr<'_>,
2269         span: Span,
2270         return_type: Option<Ty<'tcx>>,
2271     ) {
2272         let output_ty = match self.get_impl_future_output_ty(ty) {
2273             Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2274             _ => return,
2275         };
2276         let method_exists =
2277             self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
2278         debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2279         if method_exists {
2280             err.span_suggestion_verbose(
2281                 span.shrink_to_lo(),
2282                 "consider `await`ing on the `Future` and calling the method on its `Output`",
2283                 "await.",
2284                 Applicability::MaybeIncorrect,
2285             );
2286         }
2287     }
2288 
suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>)2289     fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2290         let parent_map = self.tcx.visible_parent_map(());
2291 
2292         // Separate out candidates that must be imported with a glob, because they are named `_`
2293         // and cannot be referred with their identifier.
2294         let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2295             if let Some(parent_did) = parent_map.get(trait_did) {
2296                 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2297                 if *parent_did != self.tcx.parent(*trait_did)
2298                     && self
2299                         .tcx
2300                         .module_children(*parent_did)
2301                         .iter()
2302                         .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2303                         .all(|child| child.ident.name == kw::Underscore)
2304                 {
2305                     return false;
2306                 }
2307             }
2308 
2309             true
2310         });
2311 
2312         let module_did = self.tcx.parent_module_from_def_id(self.body_id);
2313         let (module, _, _) = self.tcx.hir().get_module(module_did);
2314         let span = module.spans.inject_use_span;
2315 
2316         let path_strings = candidates.iter().map(|trait_did| {
2317             format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2318         });
2319 
2320         let glob_path_strings = globs.iter().map(|trait_did| {
2321             let parent_did = parent_map.get(trait_did).unwrap();
2322             format!(
2323                 "use {}::*; // trait {}\n",
2324                 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2325                 self.tcx.item_name(*trait_did),
2326             )
2327         });
2328 
2329         err.span_suggestions(
2330             span,
2331             msg,
2332             path_strings.chain(glob_path_strings),
2333             Applicability::MaybeIncorrect,
2334         );
2335     }
2336 
suggest_valid_traits( &self, err: &mut Diagnostic, valid_out_of_scope_traits: Vec<DefId>, ) -> bool2337     fn suggest_valid_traits(
2338         &self,
2339         err: &mut Diagnostic,
2340         valid_out_of_scope_traits: Vec<DefId>,
2341     ) -> bool {
2342         if !valid_out_of_scope_traits.is_empty() {
2343             let mut candidates = valid_out_of_scope_traits;
2344             candidates.sort();
2345             candidates.dedup();
2346 
2347             // `TryFrom` and `FromIterator` have no methods
2348             let edition_fix = candidates
2349                 .iter()
2350                 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2351                 .copied();
2352 
2353             err.help("items from traits can only be used if the trait is in scope");
2354             let msg = format!(
2355                 "the following {traits_are} implemented but not in scope; \
2356                  perhaps add a `use` for {one_of_them}:",
2357                 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2358                 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2359             );
2360 
2361             self.suggest_use_candidates(err, msg, candidates);
2362             if let Some(did) = edition_fix {
2363                 err.note(format!(
2364                     "'{}' is included in the prelude starting in Edition 2021",
2365                     with_crate_prefix!(self.tcx.def_path_str(did))
2366                 ));
2367             }
2368 
2369             true
2370         } else {
2371             false
2372         }
2373     }
2374 
suggest_traits_to_import( &self, err: &mut Diagnostic, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, inputs_len: Option<usize>, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec<DefId>, unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, )], static_candidates: &[CandidateSource], unsatisfied_bounds: bool, return_type: Option<Ty<'tcx>>, trait_missing_method: bool, )2375     fn suggest_traits_to_import(
2376         &self,
2377         err: &mut Diagnostic,
2378         span: Span,
2379         rcvr_ty: Ty<'tcx>,
2380         item_name: Ident,
2381         inputs_len: Option<usize>,
2382         source: SelfSource<'tcx>,
2383         valid_out_of_scope_traits: Vec<DefId>,
2384         unsatisfied_predicates: &[(
2385             ty::Predicate<'tcx>,
2386             Option<ty::Predicate<'tcx>>,
2387             Option<ObligationCause<'tcx>>,
2388         )],
2389         static_candidates: &[CandidateSource],
2390         unsatisfied_bounds: bool,
2391         return_type: Option<Ty<'tcx>>,
2392         trait_missing_method: bool,
2393     ) {
2394         let mut alt_rcvr_sugg = false;
2395         if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2396             debug!(
2397                 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2398                 span, item_name, rcvr_ty, rcvr
2399             );
2400             let skippable = [
2401                 self.tcx.lang_items().clone_trait(),
2402                 self.tcx.lang_items().deref_trait(),
2403                 self.tcx.lang_items().deref_mut_trait(),
2404                 self.tcx.lang_items().drop_trait(),
2405                 self.tcx.get_diagnostic_item(sym::AsRef),
2406             ];
2407             // Try alternative arbitrary self types that could fulfill this call.
2408             // FIXME: probe for all types that *could* be arbitrary self-types, not
2409             // just this list.
2410             for (rcvr_ty, post) in &[
2411                 (rcvr_ty, ""),
2412                 (Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2413                 (Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2414             ] {
2415                 match self.lookup_probe_for_diagnostic(
2416                     item_name,
2417                     *rcvr_ty,
2418                     rcvr,
2419                     ProbeScope::AllTraits,
2420                     return_type,
2421                 ) {
2422                     Ok(pick) => {
2423                         // If the method is defined for the receiver we have, it likely wasn't `use`d.
2424                         // We point at the method, but we just skip the rest of the check for arbitrary
2425                         // self types and rely on the suggestion to `use` the trait from
2426                         // `suggest_valid_traits`.
2427                         let did = Some(pick.item.container_id(self.tcx));
2428                         let skip = skippable.contains(&did);
2429                         if pick.autoderefs == 0 && !skip {
2430                             err.span_label(
2431                                 pick.item.ident(self.tcx).span,
2432                                 format!("the method is available for `{}` here", rcvr_ty),
2433                             );
2434                         }
2435                         break;
2436                     }
2437                     Err(MethodError::Ambiguity(_)) => {
2438                         // If the method is defined (but ambiguous) for the receiver we have, it is also
2439                         // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2440                         // the receiver, then it might disambiguate this method, but I think these
2441                         // suggestions are generally misleading (see #94218).
2442                         break;
2443                     }
2444                     Err(_) => (),
2445                 }
2446 
2447                 for (rcvr_ty, pre) in &[
2448                     (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"),
2449                     (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"),
2450                     (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Arc), "Arc::new"),
2451                     (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Rc), "Rc::new"),
2452                 ] {
2453                     if let Some(new_rcvr_t) = *rcvr_ty
2454                         && let Ok(pick) = self.lookup_probe_for_diagnostic(
2455                             item_name,
2456                             new_rcvr_t,
2457                             rcvr,
2458                             ProbeScope::AllTraits,
2459                             return_type,
2460                         )
2461                     {
2462                         debug!("try_alt_rcvr: pick candidate {:?}", pick);
2463                         let did = Some(pick.item.container_id(self.tcx));
2464                         // We don't want to suggest a container type when the missing
2465                         // method is `.clone()` or `.deref()` otherwise we'd suggest
2466                         // `Arc::new(foo).clone()`, which is far from what the user wants.
2467                         // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2468                         // implement the `AsRef` trait.
2469                         let skip = skippable.contains(&did)
2470                             || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2471                             || inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
2472                         // Make sure the method is defined for the *actual* receiver: we don't
2473                         // want to treat `Box<Self>` as a receiver if it only works because of
2474                         // an autoderef to `&self`
2475                         if pick.autoderefs == 0 && !skip {
2476                             err.span_label(
2477                                 pick.item.ident(self.tcx).span,
2478                                 format!("the method is available for `{}` here", new_rcvr_t),
2479                             );
2480                             err.multipart_suggestion(
2481                                 "consider wrapping the receiver expression with the \
2482                                     appropriate type",
2483                                 vec![
2484                                     (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2485                                     (rcvr.span.shrink_to_hi(), ")".to_string()),
2486                                 ],
2487                                 Applicability::MaybeIncorrect,
2488                             );
2489                             // We don't care about the other suggestions.
2490                             alt_rcvr_sugg = true;
2491                         }
2492                     }
2493                 }
2494             }
2495         }
2496         if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2497             return;
2498         }
2499 
2500         let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2501 
2502         let mut arbitrary_rcvr = vec![];
2503         // There are no traits implemented, so lets suggest some traits to
2504         // implement, by finding ones that have the item name, and are
2505         // legal to implement.
2506         let mut candidates = all_traits(self.tcx)
2507             .into_iter()
2508             // Don't issue suggestions for unstable traits since they're
2509             // unlikely to be implementable anyway
2510             .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2511                 Some(attr) => attr.level.is_stable(),
2512                 None => true,
2513             })
2514             .filter(|info| {
2515                 // Static candidates are already implemented, and known not to work
2516                 // Do not suggest them again
2517                 static_candidates.iter().all(|sc| match *sc {
2518                     CandidateSource::Trait(def_id) => def_id != info.def_id,
2519                     CandidateSource::Impl(def_id) => {
2520                         self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2521                     }
2522                 })
2523             })
2524             .filter(|info| {
2525                 // We approximate the coherence rules to only suggest
2526                 // traits that are legal to implement by requiring that
2527                 // either the type or trait is local. Multi-dispatch means
2528                 // this isn't perfect (that is, there are cases when
2529                 // implementing a trait would be legal but is rejected
2530                 // here).
2531                 unsatisfied_predicates.iter().all(|(p, _, _)| {
2532                     match p.kind().skip_binder() {
2533                         // Hide traits if they are present in predicates as they can be fixed without
2534                         // having to implement them.
2535                         ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
2536                             t.def_id() == info.def_id
2537                         }
2538                         ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
2539                             p.projection_ty.def_id == info.def_id
2540                         }
2541                         _ => false,
2542                     }
2543                 }) && (type_is_local || info.def_id.is_local())
2544                     && !self.tcx.trait_is_auto(info.def_id)
2545                     && self
2546                         .associated_value(info.def_id, item_name)
2547                         .filter(|item| {
2548                             if let ty::AssocKind::Fn = item.kind {
2549                                 let id = item
2550                                     .def_id
2551                                     .as_local()
2552                                     .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2553                                 if let Some(hir::Node::TraitItem(hir::TraitItem {
2554                                     kind: hir::TraitItemKind::Fn(fn_sig, method),
2555                                     ..
2556                                 })) = id.map(|id| self.tcx.hir().get(id))
2557                                 {
2558                                     let self_first_arg = match method {
2559                                         hir::TraitFn::Required([ident, ..]) => {
2560                                             ident.name == kw::SelfLower
2561                                         }
2562                                         hir::TraitFn::Provided(body_id) => {
2563                                             self.tcx.hir().body(*body_id).params.first().map_or(
2564                                                 false,
2565                                                 |param| {
2566                                                     matches!(
2567                                                         param.pat.kind,
2568                                                         hir::PatKind::Binding(_, _, ident, _)
2569                                                             if ident.name == kw::SelfLower
2570                                                     )
2571                                                 },
2572                                             )
2573                                         }
2574                                         _ => false,
2575                                     };
2576 
2577                                     if !fn_sig.decl.implicit_self.has_implicit_self()
2578                                         && self_first_arg
2579                                     {
2580                                         if let Some(ty) = fn_sig.decl.inputs.get(0) {
2581                                             arbitrary_rcvr.push(ty.span);
2582                                         }
2583                                         return false;
2584                                     }
2585                                 }
2586                             }
2587                             // We only want to suggest public or local traits (#45781).
2588                             item.visibility(self.tcx).is_public() || info.def_id.is_local()
2589                         })
2590                         .is_some()
2591             })
2592             .collect::<Vec<_>>();
2593         for span in &arbitrary_rcvr {
2594             err.span_label(
2595                 *span,
2596                 "the method might not be found because of this arbitrary self type",
2597             );
2598         }
2599         if alt_rcvr_sugg {
2600             return;
2601         }
2602 
2603         if !candidates.is_empty() {
2604             // Sort from most relevant to least relevant.
2605             candidates.sort_by_key(|&info| cmp::Reverse(info));
2606             candidates.dedup();
2607 
2608             let param_type = match rcvr_ty.kind() {
2609                 ty::Param(param) => Some(param),
2610                 ty::Ref(_, ty, _) => match ty.kind() {
2611                     ty::Param(param) => Some(param),
2612                     _ => None,
2613                 },
2614                 _ => None,
2615             };
2616             if !trait_missing_method {
2617                 err.help(if param_type.is_some() {
2618                     "items from traits can only be used if the type parameter is bounded by the trait"
2619                 } else {
2620                     "items from traits can only be used if the trait is implemented and in scope"
2621                 });
2622             }
2623 
2624             let candidates_len = candidates.len();
2625             let message = |action| {
2626                 format!(
2627                     "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2628                      {one_of_them}:",
2629                     traits_define =
2630                         if candidates_len == 1 { "trait defines" } else { "traits define" },
2631                     action = action,
2632                     one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2633                     name = item_name,
2634                 )
2635             };
2636             // Obtain the span for `param` and use it for a structured suggestion.
2637             if let Some(param) = param_type {
2638                 let generics = self.tcx.generics_of(self.body_id.to_def_id());
2639                 let type_param = generics.type_param(param, self.tcx);
2640                 let hir = self.tcx.hir();
2641                 if let Some(def_id) = type_param.def_id.as_local() {
2642                     let id = hir.local_def_id_to_hir_id(def_id);
2643                     // Get the `hir::Param` to verify whether it already has any bounds.
2644                     // We do this to avoid suggesting code that ends up as `T: FooBar`,
2645                     // instead we suggest `T: Foo + Bar` in that case.
2646                     match hir.get(id) {
2647                         Node::GenericParam(param) => {
2648                             enum Introducer {
2649                                 Plus,
2650                                 Colon,
2651                                 Nothing,
2652                             }
2653                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2654                             let trait_def_ids: FxHashSet<DefId> = ast_generics
2655                                 .bounds_for_param(def_id)
2656                                 .flat_map(|bp| bp.bounds.iter())
2657                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2658                                 .collect();
2659                             if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2660                                 return;
2661                             }
2662                             let msg = message(format!(
2663                                 "restrict type parameter `{}` with",
2664                                 param.name.ident(),
2665                             ));
2666                             let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
2667                             if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
2668                                 err.multipart_suggestions(
2669                                     msg,
2670                                     candidates.iter().map(|t| {
2671                                         vec![
2672                                             (param.span.shrink_to_lo(), "(".to_string()),
2673                                             (
2674                                                 bounds_span.unwrap(),
2675                                                 format!(" + {})", self.tcx.def_path_str(t.def_id)),
2676                                             ),
2677                                         ]
2678                                     }),
2679                                     Applicability::MaybeIncorrect,
2680                                 );
2681                                 return;
2682                             }
2683 
2684                             let (sp, introducer) = if let Some(span) = bounds_span {
2685                                 (span, Introducer::Plus)
2686                             } else if let Some(colon_span) = param.colon_span {
2687                                 (colon_span.shrink_to_hi(), Introducer::Nothing)
2688                             } else if param.is_impl_trait() {
2689                                 (param.span.shrink_to_hi(), Introducer::Plus)
2690                             } else {
2691                                 (param.span.shrink_to_hi(), Introducer::Colon)
2692                             };
2693 
2694                             err.span_suggestions(
2695                                 sp,
2696                                 msg,
2697                                 candidates.iter().map(|t| {
2698                                     format!(
2699                                         "{} {}",
2700                                         match introducer {
2701                                             Introducer::Plus => " +",
2702                                             Introducer::Colon => ":",
2703                                             Introducer::Nothing => "",
2704                                         },
2705                                         self.tcx.def_path_str(t.def_id)
2706                                     )
2707                                 }),
2708                                 Applicability::MaybeIncorrect,
2709                             );
2710                             return;
2711                         }
2712                         Node::Item(hir::Item {
2713                             kind: hir::ItemKind::Trait(.., bounds, _),
2714                             ident,
2715                             ..
2716                         }) => {
2717                             let (sp, sep, article) = if bounds.is_empty() {
2718                                 (ident.span.shrink_to_hi(), ":", "a")
2719                             } else {
2720                                 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2721                             };
2722                             err.span_suggestions(
2723                                 sp,
2724                                 message(format!("add {} supertrait for", article)),
2725                                 candidates.iter().map(|t| {
2726                                     format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2727                                 }),
2728                                 Applicability::MaybeIncorrect,
2729                             );
2730                             return;
2731                         }
2732                         _ => {}
2733                     }
2734                 }
2735             }
2736 
2737             let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2738                 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2739                 // cases where a positive bound implies a negative impl.
2740                 (candidates, Vec::new())
2741             } else if let Some(simp_rcvr_ty) =
2742                 simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup)
2743             {
2744                 let mut potential_candidates = Vec::new();
2745                 let mut explicitly_negative = Vec::new();
2746                 for candidate in candidates {
2747                     // Check if there's a negative impl of `candidate` for `rcvr_ty`
2748                     if self
2749                         .tcx
2750                         .all_impls(candidate.def_id)
2751                         .filter(|imp_did| {
2752                             self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2753                         })
2754                         .any(|imp_did| {
2755                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
2756                             let imp_simp =
2757                                 simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
2758                             imp_simp.is_some_and(|s| s == simp_rcvr_ty)
2759                         })
2760                     {
2761                         explicitly_negative.push(candidate);
2762                     } else {
2763                         potential_candidates.push(candidate);
2764                     }
2765                 }
2766                 (potential_candidates, explicitly_negative)
2767             } else {
2768                 // We don't know enough about `recv_ty` to make proper suggestions.
2769                 (candidates, Vec::new())
2770             };
2771 
2772             match &potential_candidates[..] {
2773                 [] => {}
2774                 [trait_info] if trait_info.def_id.is_local() => {
2775                     err.subdiagnostic(CandidateTraitNote {
2776                         span: self.tcx.def_span(trait_info.def_id),
2777                         trait_name: self.tcx.def_path_str(trait_info.def_id),
2778                         item_name,
2779                         action_or_ty: if trait_missing_method {
2780                             "NONE".to_string()
2781                         } else {
2782                             param_type.map_or_else(
2783                                 || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
2784                                 ToString::to_string,
2785                             )
2786                         },
2787                     });
2788                 }
2789                 trait_infos => {
2790                     let mut msg = message(param_type.map_or_else(
2791                         || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
2792                         |param| format!("restrict type parameter `{}` with", param),
2793                     ));
2794                     for (i, trait_info) in trait_infos.iter().enumerate() {
2795                         msg.push_str(&format!(
2796                             "\ncandidate #{}: `{}`",
2797                             i + 1,
2798                             self.tcx.def_path_str(trait_info.def_id),
2799                         ));
2800                     }
2801                     err.note(msg);
2802                 }
2803             }
2804             match &explicitly_negative[..] {
2805                 [] => {}
2806                 [trait_info] => {
2807                     let msg = format!(
2808                         "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2809                         self.tcx.def_path_str(trait_info.def_id),
2810                         item_name
2811                     );
2812                     err.note(msg);
2813                 }
2814                 trait_infos => {
2815                     let mut msg = format!(
2816                         "the following traits define an item `{}`, but are explicitly unimplemented:",
2817                         item_name
2818                     );
2819                     for trait_info in trait_infos {
2820                         msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2821                     }
2822                     err.note(msg);
2823                 }
2824             }
2825         }
2826     }
2827 
2828     /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2829     /// FIXME: currently not working for suggesting `map_or_else`, see #102408
suggest_else_fn_with_closure( &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, found: Ty<'tcx>, expected: Ty<'tcx>, ) -> bool2830     pub(crate) fn suggest_else_fn_with_closure(
2831         &self,
2832         err: &mut Diagnostic,
2833         expr: &hir::Expr<'_>,
2834         found: Ty<'tcx>,
2835         expected: Ty<'tcx>,
2836     ) -> bool {
2837         let Some((_def_id_or_name, output, _inputs)) =
2838             self.extract_callable_info(found) else {
2839                 return false;
2840         };
2841 
2842         if !self.can_coerce(output, expected) {
2843             return false;
2844         }
2845 
2846         let parent = self.tcx.hir().parent_id(expr.hir_id);
2847         if  let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2848             let hir::ExprKind::MethodCall(
2849                 hir::PathSegment { ident: method_name, .. },
2850                 self_expr,
2851                 args,
2852                 ..,
2853              ) = call_expr.kind &&
2854             let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2855             let new_name = Ident {
2856                 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2857                 span: method_name.span,
2858             };
2859             let probe = self.lookup_probe_for_diagnostic(
2860                 new_name,
2861                 self_ty,
2862                 self_expr,
2863                 ProbeScope::TraitsInScope,
2864                 Some(expected),
2865             );
2866 
2867             // check the method arguments number
2868             if let Ok(pick) = probe &&
2869                 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2870                 let fn_args = fn_sig.skip_binder().skip_binder().inputs() &&
2871                 fn_args.len() == args.len() + 1 {
2872                 err.span_suggestion_verbose(
2873                     method_name.span.shrink_to_hi(),
2874                     format!("try calling `{}` instead", new_name.name.as_str()),
2875                     "_else",
2876                     Applicability::MaybeIncorrect,
2877                 );
2878                 return true;
2879             }
2880         }
2881         false
2882     }
2883 
2884     /// Checks whether there is a local type somewhere in the chain of
2885     /// autoderefs of `rcvr_ty`.
type_derefs_to_local( &self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, ) -> bool2886     fn type_derefs_to_local(
2887         &self,
2888         span: Span,
2889         rcvr_ty: Ty<'tcx>,
2890         source: SelfSource<'tcx>,
2891     ) -> bool {
2892         fn is_local(ty: Ty<'_>) -> bool {
2893             match ty.kind() {
2894                 ty::Adt(def, _) => def.did().is_local(),
2895                 ty::Foreign(did) => did.is_local(),
2896                 ty::Dynamic(tr, ..) => tr.principal().is_some_and(|d| d.def_id().is_local()),
2897                 ty::Param(_) => true,
2898 
2899                 // Everything else (primitive types, etc.) is effectively
2900                 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2901                 // the noise from these sort of types is usually just really
2902                 // annoying, rather than any sort of help).
2903                 _ => false,
2904             }
2905         }
2906 
2907         // This occurs for UFCS desugaring of `T::method`, where there is no
2908         // receiver expression for the method call, and thus no autoderef.
2909         if let SelfSource::QPath(_) = source {
2910             return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2911         }
2912 
2913         self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2914     }
2915 }
2916 
2917 #[derive(Copy, Clone, Debug)]
2918 pub enum SelfSource<'a> {
2919     QPath(&'a hir::Ty<'a>),
2920     MethodCall(&'a hir::Expr<'a> /* rcvr */),
2921 }
2922 
2923 #[derive(Copy, Clone)]
2924 pub struct TraitInfo {
2925     pub def_id: DefId,
2926 }
2927 
2928 impl PartialEq for TraitInfo {
eq(&self, other: &TraitInfo) -> bool2929     fn eq(&self, other: &TraitInfo) -> bool {
2930         self.cmp(other) == Ordering::Equal
2931     }
2932 }
2933 impl Eq for TraitInfo {}
2934 impl PartialOrd for TraitInfo {
partial_cmp(&self, other: &TraitInfo) -> Option<Ordering>2935     fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2936         Some(self.cmp(other))
2937     }
2938 }
2939 impl Ord for TraitInfo {
cmp(&self, other: &TraitInfo) -> Ordering2940     fn cmp(&self, other: &TraitInfo) -> Ordering {
2941         // Local crates are more important than remote ones (local:
2942         // `cnum == 0`), and otherwise we throw in the defid for totality.
2943 
2944         let lhs = (other.def_id.krate, other.def_id);
2945         let rhs = (self.def_id.krate, self.def_id);
2946         lhs.cmp(&rhs)
2947     }
2948 }
2949 
2950 /// Retrieves all traits in this crate and any dependent crates,
2951 /// and wraps them into `TraitInfo` for custom sorting.
all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo>2952 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2953     tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2954 }
2955 
print_disambiguation_help<'tcx>( item_name: Ident, args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, candidate: Option<usize>, source_map: &source_map::SourceMap, fn_has_self_parameter: bool, )2956 fn print_disambiguation_help<'tcx>(
2957     item_name: Ident,
2958     args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2959     err: &mut Diagnostic,
2960     trait_name: String,
2961     rcvr_ty: Ty<'_>,
2962     kind: ty::AssocKind,
2963     def_kind_descr: &'static str,
2964     span: Span,
2965     candidate: Option<usize>,
2966     source_map: &source_map::SourceMap,
2967     fn_has_self_parameter: bool,
2968 ) {
2969     let mut applicability = Applicability::MachineApplicable;
2970     let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2971         let args = format!(
2972             "({}{})",
2973             rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2974             std::iter::once(receiver)
2975                 .chain(args.iter())
2976                 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2977                     applicability = Applicability::HasPlaceholders;
2978                     "_".to_owned()
2979                 }))
2980                 .collect::<Vec<_>>()
2981                 .join(", "),
2982         );
2983         let trait_name = if !fn_has_self_parameter {
2984             format!("<{} as {}>", rcvr_ty, trait_name)
2985         } else {
2986             trait_name
2987         };
2988         (span, format!("{}::{}{}", trait_name, item_name, args))
2989     } else {
2990         (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2991     };
2992     err.span_suggestion_verbose(
2993         span,
2994         format!(
2995             "disambiguate the {} for {}",
2996             def_kind_descr,
2997             if let Some(candidate) = candidate {
2998                 format!("candidate #{}", candidate)
2999             } else {
3000                 "the candidate".to_string()
3001             },
3002         ),
3003         sugg,
3004         applicability,
3005     );
3006 }
3007