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