1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
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::TypeErrCtxtExt as _;
27 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
28 use rustc_trait_selection::traits::{
29 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
32 use std::cmp::Ordering;
35 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
36 use super::{CandidateSource, MethodError, NoMatchData};
38 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
42 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
43 // so we look for these beforehand.
44 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
45 // If it's not a simple function, look for things which implement `FnOnce`.
47 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
51 // This conditional prevents us from asking to call errors and unresolved types.
52 // It might seem that we can use `predicate_must_hold_modulo_regions`,
53 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
54 // type resolution always gives a "maybe" here.
55 if self.autoderef(span, ty).any(|(ty, _)| {
56 info!("check deref {:?} error", ty);
57 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
62 self.autoderef(span, ty).any(|(ty, _)| {
63 info!("check deref {:?} impl FnOnce", ty);
65 let fn_once_substs = tcx.mk_substs_trait(
68 .next_ty_var(TypeVariableOrigin {
69 kind: TypeVariableOriginKind::MiscVariable,
74 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
75 let poly_trait_ref = ty::Binder::dummy(trait_ref);
76 let obligation = Obligation::misc(
80 poly_trait_ref.without_const().to_predicate(tcx),
82 self.predicate_may_hold(&obligation)
89 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
90 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
93 pub fn report_method_error(
98 source: SelfSource<'tcx>,
99 error: MethodError<'tcx>,
100 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
101 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
102 // Avoid suggestions when we don't know what's going on.
103 if rcvr_ty.references_error() {
107 let report_candidates = |span: Span,
108 err: &mut Diagnostic,
109 mut sources: Vec<CandidateSource>,
113 // Dynamic limit to avoid hiding just one candidate, which is silly.
114 let limit = if sources.len() == 5 { 5 } else { 4 };
116 for (idx, source) in sources.iter().take(limit).enumerate() {
118 CandidateSource::Impl(impl_did) => {
119 // Provide the best span we can. Use the item, if local to crate, else
120 // the impl, if local to crate (item may be defaulted), else nothing.
121 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
122 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
123 self.associated_value(impl_trait_ref.def_id, item_name)
128 let note_span = if item.def_id.is_local() {
129 Some(self.tcx.def_span(item.def_id))
130 } else if impl_did.is_local() {
131 Some(self.tcx.def_span(impl_did))
136 let impl_ty = self.tcx.at(span).type_of(impl_did);
138 let insertion = match self.tcx.impl_trait_ref(impl_did) {
139 None => String::new(),
140 Some(trait_ref) => format!(
141 " of the trait `{}`",
142 self.tcx.def_path_str(trait_ref.def_id)
146 let (note_str, idx) = if sources.len() > 1 {
149 "candidate #{} is defined in an impl{} for the type `{}`",
159 "the candidate is defined in an impl{} for the type `{}`",
165 if let Some(note_span) = note_span {
166 // We have a span pointing to the method. Show note with snippet.
167 err.span_note(note_span, ¬e_str);
171 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
172 let path = self.tcx.def_path_str(trait_ref.def_id);
174 let ty = match item.kind {
175 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
176 ty::AssocKind::Fn => self
182 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
186 print_disambiguation_help(
196 self.tcx.sess.source_map(),
197 item.fn_has_self_parameter,
201 CandidateSource::Trait(trait_did) => {
202 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
203 let item_span = self.tcx.def_span(item.def_id);
204 let idx = if sources.len() > 1 {
206 "candidate #{} is defined in the trait `{}`",
208 self.tcx.def_path_str(trait_did)
210 err.span_note(item_span, msg);
214 "the candidate is defined in the trait `{}`",
215 self.tcx.def_path_str(trait_did)
217 err.span_note(item_span, msg);
220 let path = self.tcx.def_path_str(trait_did);
221 print_disambiguation_help(
231 self.tcx.sess.source_map(),
232 item.fn_has_self_parameter,
237 if sources.len() > limit {
238 err.note(&format!("and {} others", sources.len() - limit));
242 let sugg_span = if let SelfSource::MethodCall(expr) = source {
243 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
244 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
250 MethodError::NoMatch(NoMatchData {
251 static_candidates: static_sources,
252 unsatisfied_predicates,
259 let actual = self.resolve_vars_if_possible(rcvr_ty);
260 let ty_str = self.ty_to_string(actual);
261 let is_method = mode == Mode::MethodCall;
262 let item_kind = if is_method {
264 } else if actual.is_enum() {
265 "variant or associated item"
267 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
268 (Some(name), false) if name.is_lowercase() => "function or associated item",
269 (Some(_), false) => "associated item",
270 (Some(_), true) | (None, false) => "variant or associated item",
271 (None, true) => "variant",
275 if self.suggest_wrapping_range_with_parens(
276 tcx, actual, source, span, item_name, &ty_str,
277 ) || self.suggest_constraining_numerical_ty(
278 tcx, actual, source, span, item_kind, item_name, &ty_str,
283 span = item_name.span;
285 // Don't show generic arguments when the method can't be found in any implementation (#81576).
286 let mut ty_str_reported = ty_str.clone();
287 if let ty::Adt(_, generics) = actual.kind() {
288 if generics.len() > 0 {
289 let mut autoderef = self.autoderef(span, actual);
290 let candidate_found = autoderef.any(|(ty, _)| {
291 if let ty::Adt(adt_deref, _) = ty.kind() {
293 .inherent_impls(adt_deref.did())
295 .filter_map(|def_id| self.associated_value(*def_id, item_name))
302 let has_deref = autoderef.step_count() > 0;
303 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
304 if let Some((path_string, _)) = ty_str.split_once('<') {
305 ty_str_reported = path_string.to_string();
311 let mut err = struct_span_err!(
315 "no {} named `{}` found for {} `{}` in the current scope",
318 actual.prefix_string(self.tcx),
321 if actual.references_error() {
322 err.downgrade_to_delayed_bug();
325 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
326 self.suggest_await_before_method(
327 &mut err, item_name, actual, cal, span,
330 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
333 "you are looking for the module in `std`, not the primitive type",
335 Applicability::MachineApplicable,
338 if let ty::RawPtr(_) = &actual.kind() {
340 "try using `<*const T>::as_ref()` to get a reference to the \
341 type behind the pointer: https://doc.rust-lang.org/std/\
342 primitive.pointer.html#method.as_ref",
345 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
346 to invalid or uninitialized memory is undefined behavior",
350 let ty_span = match actual.kind() {
351 ty::Param(param_type) => {
352 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
353 let type_param = generics.type_param(param_type, self.tcx);
354 Some(self.tcx.def_span(type_param.def_id))
356 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
360 if let Some(span) = ty_span {
364 "{item_kind} `{item_name}` not found for this {}",
365 actual.prefix_string(self.tcx)
370 if let SelfSource::MethodCall(rcvr_expr) = source {
371 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
375 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
376 let probe = self.lookup_probe(
381 ProbeScope::AllTraits,
387 let mut custom_span_label = false;
389 if !static_sources.is_empty() {
391 "found the following associated functions; to be used as methods, \
392 functions must have a `self` parameter",
394 err.span_label(span, "this is an associated function, not a method");
395 custom_span_label = true;
397 if static_sources.len() == 1 {
399 if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) {
400 // When the "method" is resolved through dereferencing, we really want the
401 // original type that has the associated function for accurate suggestions.
403 let ty = tcx.at(span).type_of(*impl_did);
404 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
405 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
406 // Use `actual` as it will have more `substs` filled in.
407 self.ty_to_value_string(actual.peel_refs())
409 _ => self.ty_to_value_string(ty.peel_refs()),
412 self.ty_to_value_string(actual.peel_refs())
414 if let SelfSource::MethodCall(expr) = source {
417 "use associated function syntax instead",
418 format!("{}::{}", ty_str, item_name),
419 Applicability::MachineApplicable,
422 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
425 report_candidates(span, &mut err, static_sources, sugg_span);
426 } else if static_sources.len() > 1 {
427 report_candidates(span, &mut err, static_sources, sugg_span);
430 let mut bound_spans = vec![];
431 let mut restrict_type_params = false;
432 let mut unsatisfied_bounds = false;
433 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
434 let msg = "consider using `len` instead";
435 if let SelfSource::MethodCall(_expr) = source {
436 err.span_suggestion_short(
440 Applicability::MachineApplicable,
443 err.span_label(span, msg);
445 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
446 let iterator_trait = self.tcx.def_path_str(iterator_trait);
447 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
449 } else if !unsatisfied_predicates.is_empty() {
450 let mut type_params = FxHashMap::default();
452 // Pick out the list of unimplemented traits on the receiver.
453 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
454 let mut unimplemented_traits = FxHashMap::default();
455 let mut unimplemented_traits_only = true;
456 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
457 if let (ty::PredicateKind::Trait(p), Some(cause)) =
458 (predicate.kind().skip_binder(), cause.as_ref())
460 if p.trait_ref.self_ty() != rcvr_ty {
461 // This is necessary, not just to keep the errors clean, but also
462 // because our derived obligations can wind up with a trait ref that
463 // requires a different param_env to be correctly compared.
466 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
467 predicate.kind().rebind(p.trait_ref),
469 cause: cause.clone(),
470 param_env: self.param_env,
471 predicate: *predicate,
478 // Make sure that, if any traits other than the found ones were involved,
479 // we don't don't report an unimplemented trait.
480 // We don't want to say that `iter::Cloned` is not an iterator, just
481 // because of some non-Clone item being iterated over.
482 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
483 match predicate.kind().skip_binder() {
484 ty::PredicateKind::Trait(p)
485 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
487 unimplemented_traits_only = false;
493 let mut collect_type_param_suggestions =
494 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
495 // We don't care about regions here, so it's fine to skip the binder here.
496 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
497 (self_ty.kind(), parent_pred.kind().skip_binder())
499 let node = match p.trait_ref.self_ty().kind() {
501 // Account for `fn` items like in `issue-35677.rs` to
502 // suggest restricting its type params.
503 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
504 hir_id: self.body_id,
509 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
512 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
515 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
519 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
520 if let Some(g) = kind.generics() {
522 g.tail_span_for_predicate_suggestion(),
523 g.add_where_or_trailing_comma(),
527 .or_insert_with(FxHashSet::default)
528 .insert(obligation.to_owned());
533 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
535 "doesn't satisfy `{}`",
536 if obligation.len() > 50 { quiet } else { obligation }
538 match &self_ty.kind() {
539 // Point at the type that couldn't satisfy the bound.
541 bound_spans.push((self.tcx.def_span(def.did()), msg))
543 // Point at the trait object that couldn't satisfy the bound.
544 ty::Dynamic(preds, _, _) => {
545 for pred in preds.iter() {
546 match pred.skip_binder() {
547 ty::ExistentialPredicate::Trait(tr) => bound_spans
548 .push((self.tcx.def_span(tr.def_id), msg.clone())),
549 ty::ExistentialPredicate::Projection(_)
550 | ty::ExistentialPredicate::AutoTrait(_) => {}
554 // Point at the closure that couldn't satisfy the bound.
555 ty::Closure(def_id, _) => bound_spans.push((
556 tcx.def_span(*def_id),
557 format!("doesn't satisfy `{}`", quiet),
562 let mut format_pred = |pred: ty::Predicate<'tcx>| {
563 let bound_predicate = pred.kind();
564 match bound_predicate.skip_binder() {
565 ty::PredicateKind::Projection(pred) => {
566 let pred = bound_predicate.rebind(pred);
567 // `<Foo as Iterator>::Item = String`.
568 let projection_ty = pred.skip_binder().projection_ty;
570 let substs_with_infer_self = tcx.mk_substs(
571 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
572 .chain(projection_ty.substs.iter().skip(1)),
575 let quiet_projection_ty = ty::ProjectionTy {
576 substs: substs_with_infer_self,
577 item_def_id: projection_ty.item_def_id,
580 let term = pred.skip_binder().term;
582 let obligation = format!("{} = {}", projection_ty, term);
583 let quiet = format!("{} = {}", quiet_projection_ty, term);
585 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
586 Some((obligation, projection_ty.self_ty()))
588 ty::PredicateKind::Trait(poly_trait_ref) => {
589 let p = poly_trait_ref.trait_ref;
590 let self_ty = p.self_ty();
591 let path = p.print_only_trait_path();
592 let obligation = format!("{}: {}", self_ty, path);
593 let quiet = format!("_: {}", path);
594 bound_span_label(self_ty, &obligation, &quiet);
595 Some((obligation, self_ty))
601 // Find all the requirements that come from a local `impl` block.
602 let mut skip_list: FxHashSet<_> = Default::default();
603 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
604 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
606 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
607 .filter_map(|(p, parent, c)| match c.code() {
608 ObligationCauseCode::ImplDerivedObligation(ref data) => {
609 Some((&data.derived, p, parent, data.impl_def_id, data))
614 let parent_trait_ref = data.parent_trait_pred;
615 let path = parent_trait_ref.print_modifiers_and_trait_path();
616 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
617 let unsatisfied_msg = "unsatisfied trait bound introduced here";
619 "unsatisfied trait bound introduced in this `derive` macro";
620 match self.tcx.hir().get_if_local(impl_def_id) {
621 // Unmet obligation comes from a `derive` macro, point at it once to
622 // avoid multiple span labels pointing at the same place.
623 Some(Node::Item(hir::Item {
624 kind: hir::ItemKind::Trait(..),
628 ident.span.ctxt().outer_expn_data().kind,
629 ExpnKind::Macro(MacroKind::Derive, _)
632 let span = ident.span.ctxt().outer_expn_data().call_site;
633 let mut spans: MultiSpan = span.into();
634 spans.push_span_label(span, derive_msg);
635 let entry = spanned_predicates.entry(spans);
636 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
639 Some(Node::Item(hir::Item {
640 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
643 self_ty.span.ctxt().outer_expn_data().kind,
644 ExpnKind::Macro(MacroKind::Derive, _)
646 of_trait.as_ref().map(|t| t
652 Some(ExpnKind::Macro(MacroKind::Derive, _))
655 let span = self_ty.span.ctxt().outer_expn_data().call_site;
656 let mut spans: MultiSpan = span.into();
657 spans.push_span_label(span, derive_msg);
658 let entry = spanned_predicates.entry(spans);
659 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
662 // Unmet obligation coming from a `trait`.
663 Some(Node::Item(hir::Item {
664 kind: hir::ItemKind::Trait(..),
669 ident.span.ctxt().outer_expn_data().kind,
670 ExpnKind::Macro(MacroKind::Derive, _)
673 if let Some(pred) = parent_p {
674 // Done to add the "doesn't satisfy" `span_label`.
675 let _ = format_pred(*pred);
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);
685 spans.push_span_label(ident.span, "in this trait");
686 let entry = spanned_predicates.entry(spans);
687 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
690 // Unmet obligation coming from an `impl`.
691 Some(Node::Item(hir::Item {
693 hir::ItemKind::Impl(hir::Impl {
694 of_trait, self_ty, generics, ..
699 self_ty.span.ctxt().outer_expn_data().kind,
700 ExpnKind::Macro(MacroKind::Derive, _)
702 of_trait.as_ref().map(|t| t
708 Some(ExpnKind::Macro(MacroKind::Derive, _))
712 unsatisfied_predicates.iter().any(|(pred, _, _)| {
713 match pred.kind().skip_binder() {
714 ty::PredicateKind::Trait(pred) => {
716 == self.tcx.lang_items().sized_trait()
717 && pred.polarity == ty::ImplPolarity::Positive
722 for param in generics.params {
723 if param.span == cause.span && sized_pred {
724 let (sp, sugg) = match param.colon_span {
725 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
726 None => (param.span.shrink_to_hi(), ": ?Sized"),
728 err.span_suggestion_verbose(
730 "consider relaxing the type parameter's implicit \
733 Applicability::MachineApplicable,
737 if let Some(pred) = parent_p {
738 // Done to add the "doesn't satisfy" `span_label`.
739 let _ = format_pred(*pred);
742 let mut spans = if cause.span != *item_span {
743 let mut spans: MultiSpan = cause.span.into();
744 spans.push_span_label(cause.span, unsatisfied_msg);
747 let mut spans = Vec::with_capacity(2);
748 if let Some(trait_ref) = of_trait {
749 spans.push(trait_ref.path.span);
751 spans.push(self_ty.span);
754 if let Some(trait_ref) = of_trait {
755 spans.push_span_label(trait_ref.path.span, "");
757 spans.push_span_label(self_ty.span, "");
759 let entry = spanned_predicates.entry(spans);
760 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
765 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
766 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
767 for (span, (_path, _self_ty, preds)) in spanned_predicates {
768 let mut preds: Vec<_> = preds
770 .filter_map(|pred| format_pred(*pred))
771 .map(|(p, _)| format!("`{}`", p))
775 let msg = if let [pred] = &preds[..] {
776 format!("trait bound {} was not satisfied", pred)
779 "the following trait bounds were not satisfied:\n{}",
783 err.span_note(span, &msg);
784 unsatisfied_bounds = true;
787 // The requirements that didn't have an `impl` span to show.
788 let mut bound_list = unsatisfied_predicates
790 .filter_map(|(pred, parent_pred, _cause)| {
791 format_pred(*pred).map(|(p, self_ty)| {
792 collect_type_param_suggestions(self_ty, *pred, &p);
795 None => format!("`{}`", &p),
796 Some(parent_pred) => match format_pred(*parent_pred) {
797 None => format!("`{}`", &p),
798 Some((parent_p, _)) => {
799 collect_type_param_suggestions(
805 "`{}`\nwhich is required by `{}`",
815 .filter(|(_, pred)| !skip_list.contains(&pred))
818 .collect::<Vec<(usize, String)>>();
820 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
821 restrict_type_params = true;
822 // #74886: Sort here so that the output is always the same.
823 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
825 err.span_suggestion_verbose(
828 "consider restricting the type parameter{s} to satisfy the \
830 s = pluralize!(obligations.len())
832 format!("{} {}", add_where_or_comma, obligations.join(", ")),
833 Applicability::MaybeIncorrect,
837 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
838 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
839 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
841 if !bound_list.is_empty() || !skip_list.is_empty() {
842 let bound_list = bound_list
844 .map(|(_, path)| path)
847 let actual_prefix = actual.prefix_string(self.tcx);
848 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
849 let (primary_message, label) =
850 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
854 .map(|(_, (trait_ref, obligation))| {
855 if trait_ref.self_ty().references_error()
856 || actual.references_error()
861 let OnUnimplementedNote { message, label, .. } = self
863 .on_unimplemented_note(trait_ref, &obligation);
866 .unwrap_or((None, None))
870 let primary_message = primary_message.unwrap_or_else(|| format!(
871 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
873 err.set_primary_message(&primary_message);
874 if let Some(label) = label {
875 custom_span_label = true;
876 err.span_label(span, label);
878 if !bound_list.is_empty() {
880 "the following trait bounds were not satisfied:\n{bound_list}"
883 self.suggest_derive(&mut err, &unsatisfied_predicates);
885 unsatisfied_bounds = true;
889 let label_span_not_found = |err: &mut Diagnostic| {
890 if unsatisfied_predicates.is_empty() {
891 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
892 let is_string_or_ref_str = match actual.kind() {
893 ty::Ref(_, ty, _) => {
897 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
900 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
903 if is_string_or_ref_str && item_name.name == sym::iter {
904 err.span_suggestion_verbose(
906 "because of the in-memory representation of `&str`, to obtain \
907 an `Iterator` over each of its codepoint use method `chars`",
909 Applicability::MachineApplicable,
912 if let ty::Adt(adt, _) = rcvr_ty.kind() {
913 let mut inherent_impls_candidate = self
915 .inherent_impls(adt.did())
919 if let Some(assoc) = self.associated_value(*def_id, item_name) {
920 // Check for both mode is the same so we avoid suggesting
921 // incorrect associated item.
922 match (mode, assoc.fn_has_self_parameter, source) {
923 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
924 // We check that the suggest type is actually
925 // different from the received one
926 // So we avoid suggestion method with Box<Self>
928 self.tcx.at(span).type_of(*def_id) != actual
929 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
931 (Mode::Path, false, _) => true,
938 .collect::<Vec<_>>();
939 if !inherent_impls_candidate.is_empty() {
940 inherent_impls_candidate.sort();
941 inherent_impls_candidate.dedup();
943 // number of type to shows at most.
944 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
945 let type_candidates = inherent_impls_candidate
949 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
953 let additional_types = if inherent_impls_candidate.len() > limit {
955 "\nand {} more types",
956 inherent_impls_candidate.len() - limit
962 "the {item_kind} was found for\n{}{}",
963 type_candidates, additional_types
968 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
972 // If the method name is the name of a field with a function or closure type,
973 // give a helping note that it has to be called as `(x.f)(...)`.
974 if let SelfSource::MethodCall(expr) = source {
975 if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err)
976 && lev_candidate.is_none()
977 && !custom_span_label
979 label_span_not_found(&mut err);
981 } else if !custom_span_label {
982 label_span_not_found(&mut err);
985 // Don't suggest (for example) `expr.field.method()` if `expr.method()`
986 // doesn't exist due to unsatisfied predicates.
987 if unsatisfied_predicates.is_empty() {
988 self.check_for_field_method(&mut err, source, span, actual, item_name);
991 self.check_for_inner_self(&mut err, source, span, actual, item_name);
995 for (span, msg) in bound_spans.into_iter() {
996 err.span_label(span, &msg);
999 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
1001 self.suggest_traits_to_import(
1006 args.map(|(_, args)| args.len() + 1),
1008 out_of_scope_traits,
1009 &unsatisfied_predicates,
1014 // Don't emit a suggestion if we found an actual method
1015 // that had unsatisfied trait bounds
1016 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1017 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1018 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1019 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1023 err.span_suggestion(
1025 "there is a variant with a similar name",
1027 Applicability::MaybeIncorrect,
1032 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1033 let msg = "remove this method call";
1034 let mut fallback_span = true;
1035 if let SelfSource::MethodCall(expr) = source {
1037 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1038 if let Some(span) = call_expr.span.trim_start(expr.span) {
1039 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1040 fallback_span = false;
1044 err.span_label(span, msg);
1046 } else if let Some(lev_candidate) = lev_candidate {
1047 // Don't emit a suggestion if we found an actual method
1048 // that had unsatisfied trait bounds
1049 if unsatisfied_predicates.is_empty() {
1050 let def_kind = lev_candidate.kind.as_def_kind();
1051 // Methods are defined within the context of a struct and their first parameter is always self,
1052 // which represents the instance of the struct the method is being called on
1053 // Associated functions don’t take self as a parameter and
1054 // they are not methods because they don’t have an instance of the struct to work with.
1055 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1056 err.span_suggestion(
1058 &format!("there is a method with a similar name",),
1060 Applicability::MaybeIncorrect,
1063 err.span_suggestion(
1066 "there is {} {} with a similar name",
1068 def_kind.descr(lev_candidate.def_id),
1071 Applicability::MaybeIncorrect,
1077 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1082 MethodError::Ambiguity(sources) => {
1083 let mut err = struct_span_err!(
1087 "multiple applicable items in scope"
1089 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1091 report_candidates(span, &mut err, sources, sugg_span);
1095 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1096 let kind = kind.descr(def_id);
1097 let mut err = struct_span_err!(
1101 "{} `{}` is private",
1105 err.span_label(item_name.span, &format!("private {}", kind));
1109 .span_if_local(def_id)
1110 .unwrap_or_else(|| self.tcx.def_span(def_id));
1111 err.span_label(sp, &format!("private {} defined here", kind));
1112 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1116 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1117 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1118 let mut err = self.sess().struct_span_err(span, &msg);
1119 err.span_label(bound_span, "this has a `Sized` requirement");
1120 if !candidates.is_empty() {
1122 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1123 add a `use` for {one_of_them}:",
1124 an = if candidates.len() == 1 { "an" } else { "" },
1125 s = pluralize!(candidates.len()),
1126 were = pluralize!("was", candidates.len()),
1127 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1129 self.suggest_use_candidates(&mut err, help, candidates);
1131 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1133 let trait_type = self.tcx.mk_ref(
1135 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1137 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1143 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1148 fn suggest_field_call(
1152 expr: &hir::Expr<'_>,
1154 err: &mut Diagnostic,
1157 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1158 ty::Adt(def, substs) if !def.is_enum() => {
1159 let variant = &def.non_enum_variant();
1160 tcx.find_field_index(item_name, variant).map(|index| {
1161 let field = &variant.fields[index];
1162 let field_ty = field.ty(tcx, substs);
1168 if let Some((field, field_ty)) = field_receiver {
1169 let scope = tcx.parent_module(self.body_id);
1170 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1173 if self.is_fn_ty(field_ty, span) {
1174 let expr_span = expr.span.to(item_name.span);
1175 err.multipart_suggestion(
1177 "to call the function stored in `{}`, \
1178 surround the field access with parentheses",
1182 (expr_span.shrink_to_lo(), '('.to_string()),
1183 (expr_span.shrink_to_hi(), ')'.to_string()),
1185 Applicability::MachineApplicable,
1188 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1190 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1191 err.span_suggestion(
1193 "remove the arguments",
1195 Applicability::MaybeIncorrect,
1201 let field_kind = if is_accessible { "field" } else { "private field" };
1202 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1208 /// Suggest possible range with adding parentheses, for example:
1209 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1210 fn suggest_wrapping_range_with_parens(
1214 source: SelfSource<'tcx>,
1219 if let SelfSource::MethodCall(expr) = source {
1220 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1221 if let Node::Expr(parent_expr) = parent {
1222 let lang_item = match parent_expr.kind {
1223 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1224 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1225 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1226 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1227 Some(LangItem::RangeToInclusive)
1231 ExprKind::Call(ref func, _) => match func.kind {
1232 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1233 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1234 Some(LangItem::RangeInclusiveStruct)
1241 if lang_item.is_none() {
1245 let span_included = match parent_expr.kind {
1246 hir::ExprKind::Struct(_, eps, _) => {
1247 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1249 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1250 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1258 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1260 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1262 let pick = self.probe_for_name(
1269 ProbeScope::AllTraits,
1272 let range_span = parent_expr.span.with_hi(expr.span.hi());
1273 tcx.sess.emit_err(errors::MissingParentheseInRange {
1275 ty_str: ty_str.to_string(),
1276 method_name: item_name.as_str().to_string(),
1277 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1278 func_name: item_name.name.as_str().to_string(),
1279 left: range_span.shrink_to_lo(),
1280 right: range_span.shrink_to_hi(),
1291 fn suggest_constraining_numerical_ty(
1295 source: SelfSource<'_>,
1301 let found_candidate = all_traits(self.tcx)
1303 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1304 let found_assoc = |ty: Ty<'tcx>| {
1305 simplify_type(tcx, ty, TreatParams::AsInfer)
1307 tcx.incoherent_impls(simp)
1309 .find_map(|&id| self.associated_value(id, item_name))
1313 let found_candidate = found_candidate
1314 || found_assoc(tcx.types.i8)
1315 || found_assoc(tcx.types.i16)
1316 || found_assoc(tcx.types.i32)
1317 || found_assoc(tcx.types.i64)
1318 || found_assoc(tcx.types.i128)
1319 || found_assoc(tcx.types.u8)
1320 || found_assoc(tcx.types.u16)
1321 || found_assoc(tcx.types.u32)
1322 || found_assoc(tcx.types.u64)
1323 || found_assoc(tcx.types.u128)
1324 || found_assoc(tcx.types.f32)
1325 || found_assoc(tcx.types.f32);
1327 && actual.is_numeric()
1328 && !actual.has_concrete_skeleton()
1329 && let SelfSource::MethodCall(expr) = source
1331 let mut err = struct_span_err!(
1335 "can't call {} `{}` on ambiguous numeric type `{}`",
1340 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1342 ExprKind::Lit(ref lit) => {
1347 .span_to_snippet(lit.span)
1348 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1350 // If this is a floating point literal that ends with '.',
1351 // get rid of it to stop this from becoming a member access.
1352 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1353 err.span_suggestion(
1356 "you must specify a concrete type for this numeric value, \
1360 format!("{snippet}_{concrete_type}"),
1361 Applicability::MaybeIncorrect,
1364 ExprKind::Path(QPath::Resolved(_, path)) => {
1366 if let hir::def::Res::Local(hir_id) = path.res {
1367 let span = tcx.hir().span(hir_id);
1368 let filename = tcx.sess.source_map().span_to_filename(span);
1371 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1373 "you must specify a type for this binding, like `{}`",
1377 match (filename, parent_node) {
1380 Node::Local(hir::Local {
1381 source: hir::LocalSource::Normal,
1386 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1387 err.span_suggestion(
1388 // account for `let x: _ = 42;`
1392 format!(": {concrete_type}"),
1393 Applicability::MaybeIncorrect,
1397 err.span_label(span, msg);
1410 fn check_for_field_method(
1412 err: &mut Diagnostic,
1413 source: SelfSource<'tcx>,
1418 if let SelfSource::MethodCall(expr) = source
1419 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1420 && let Some((fields, substs)) =
1421 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1423 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1425 let lang_items = self.tcx.lang_items();
1426 let never_mention_traits = [
1427 lang_items.clone_trait(),
1428 lang_items.deref_trait(),
1429 lang_items.deref_mut_trait(),
1430 self.tcx.get_diagnostic_item(sym::AsRef),
1431 self.tcx.get_diagnostic_item(sym::AsMut),
1432 self.tcx.get_diagnostic_item(sym::Borrow),
1433 self.tcx.get_diagnostic_item(sym::BorrowMut),
1435 let candidate_fields: Vec<_> = fields
1436 .filter_map(|candidate_field| {
1437 self.check_for_nested_field_satisfying(
1445 ProbeScope::TraitsInScope,
1447 .map_or(false, |pick| {
1448 !never_mention_traits
1451 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1463 .map(|id| id.name.to_ident_string())
1464 .collect::<Vec<String>>()
1469 let len = candidate_fields.len();
1471 err.span_suggestions(
1472 item_name.span.shrink_to_lo(),
1474 "{} of the expressions' fields {} a method of the same name",
1475 if len > 1 { "some" } else { "one" },
1476 if len > 1 { "have" } else { "has" },
1478 candidate_fields.iter().map(|path| format!("{path}.")),
1479 Applicability::MaybeIncorrect,
1485 fn check_for_inner_self(
1487 err: &mut Diagnostic,
1488 source: SelfSource<'tcx>,
1494 let SelfSource::MethodCall(expr) = source else { return; };
1495 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1497 let ty::Adt(kind, substs) = actual.kind() else { return; };
1498 match kind.adt_kind() {
1499 ty::AdtKind::Enum => {
1500 let matching_variants: Vec<_> = kind
1503 .flat_map(|variant| {
1504 let [field] = &variant.fields[..] else { return None; };
1505 let field_ty = field.ty(tcx, substs);
1507 // Skip `_`, since that'll just lead to ambiguity.
1508 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1517 ProbeScope::TraitsInScope,
1520 .map(|pick| (variant, field, pick))
1524 let ret_ty_matches = |diagnostic_item| {
1525 if let Some(ret_ty) = self
1528 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1529 && let ty::Adt(kind, _) = ret_ty.kind()
1530 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1538 match &matching_variants[..] {
1539 [(_, field, pick)] => {
1540 let self_ty = field.ty(tcx, substs);
1542 tcx.def_span(pick.item.def_id),
1543 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1545 let (article, kind, variant, question) =
1546 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1547 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1548 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1549 ("an", "Option", "None", ret_ty_matches(sym::Option))
1554 err.span_suggestion_verbose(
1555 expr.span.shrink_to_hi(),
1557 "use the `?` operator to extract the `{self_ty}` value, propagating \
1558 {article} `{kind}::{variant}` value to the caller"
1561 Applicability::MachineApplicable,
1564 err.span_suggestion_verbose(
1565 expr.span.shrink_to_hi(),
1567 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1568 panicking if the value is {article} `{kind}::{variant}`"
1570 ".expect(\"REASON\")",
1571 Applicability::HasPlaceholders,
1575 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1579 // Target wrapper types - types that wrap or pretend to wrap another type,
1580 // perhaps this inner type is meant to be called?
1581 ty::AdtKind::Struct | ty::AdtKind::Union => {
1582 let [first] = ***substs else { return; };
1583 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1584 let Ok(pick) = self.lookup_probe(
1589 ProbeScope::TraitsInScope,
1592 let name = self.ty_to_value_string(actual);
1593 let inner_id = kind.did();
1594 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1595 pick.autoref_or_ptr_adjustment
1602 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1603 err.help("use `with` or `try_with` to access thread local storage");
1604 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1606 "if this `{name}` has been initialized, \
1607 use one of the `assume_init` methods to access the inner value"
1609 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1610 let (suggestion, borrow_kind, panic_if) = match mutable {
1611 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1612 Some(Mutability::Mut) => {
1613 (".borrow_mut()", "mutably borrow", "any borrows exist")
1617 err.span_suggestion_verbose(
1618 expr.span.shrink_to_hi(),
1620 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1621 panicking if {panic_if}"
1624 Applicability::MaybeIncorrect,
1626 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1627 err.span_suggestion_verbose(
1628 expr.span.shrink_to_hi(),
1630 "use `.lock().unwrap()` to borrow the `{ty}`, \
1631 blocking the current thread until it can be acquired"
1634 Applicability::MaybeIncorrect,
1636 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1637 let (suggestion, borrow_kind) = match mutable {
1638 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1639 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1642 err.span_suggestion_verbose(
1643 expr.span.shrink_to_hi(),
1645 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1646 blocking the current thread until it can be acquired"
1649 Applicability::MaybeIncorrect,
1656 tcx.def_span(pick.item.def_id),
1657 &format!("the method `{item_name}` exists on the type `{ty}`"),
1663 pub(crate) fn note_unmet_impls_on_type(
1665 err: &mut Diagnostic,
1666 errors: Vec<FulfillmentError<'tcx>>,
1668 let all_local_types_needing_impls =
1669 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1670 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1671 ty::Adt(def, _) => def.did().is_local(),
1676 let mut preds: Vec<_> = errors
1678 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1679 ty::PredicateKind::Trait(pred) => Some(pred),
1683 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1686 .filter_map(|pred| match pred.self_ty().kind() {
1687 ty::Adt(def, _) => Some(def.did()),
1690 .collect::<FxHashSet<_>>();
1691 let mut spans: MultiSpan = def_ids
1693 .filter_map(|def_id| {
1694 let span = self.tcx.def_span(*def_id);
1695 if span.is_dummy() { None } else { Some(span) }
1697 .collect::<Vec<_>>()
1700 for pred in &preds {
1701 match pred.self_ty().kind() {
1702 ty::Adt(def, _) if def.did().is_local() => {
1703 spans.push_span_label(
1704 self.tcx.def_span(def.did()),
1705 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1712 if all_local_types_needing_impls && spans.primary_span().is_some() {
1713 let msg = if preds.len() == 1 {
1715 "an implementation of `{}` might be missing for `{}`",
1716 preds[0].trait_ref.print_only_trait_path(),
1721 "the following type{} would have to `impl` {} required trait{} for this \
1722 operation to be valid",
1723 pluralize!(def_ids.len()),
1724 if def_ids.len() == 1 { "its" } else { "their" },
1725 pluralize!(preds.len()),
1728 err.span_note(spans, &msg);
1731 let preds: Vec<_> = errors
1733 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1735 self.suggest_derive(err, &preds);
1740 err: &mut Diagnostic,
1741 unsatisfied_predicates: &[(
1742 ty::Predicate<'tcx>,
1743 Option<ty::Predicate<'tcx>>,
1744 Option<ObligationCause<'tcx>>,
1747 let mut derives = Vec::<(String, Span, Symbol)>::new();
1748 let mut traits = Vec::<Span>::new();
1749 for (pred, _, _) in unsatisfied_predicates {
1750 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1751 let adt = match trait_pred.self_ty().ty_adt_def() {
1752 Some(adt) if adt.did().is_local() => adt,
1755 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1756 let can_derive = match diagnostic_name {
1757 sym::Default => !adt.is_enum(),
1765 | sym::Debug => true,
1769 let self_name = trait_pred.self_ty().to_string();
1770 let self_span = self.tcx.def_span(adt.did());
1771 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1772 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1774 if let Some(parent_diagnostic_name) =
1775 self.tcx.get_diagnostic_name(super_trait.def_id())
1780 parent_diagnostic_name,
1785 derives.push((self_name, self_span, diagnostic_name));
1787 traits.push(self.tcx.def_span(trait_pred.def_id()));
1790 traits.push(self.tcx.def_span(trait_pred.def_id()));
1799 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1800 for (self_name, self_span, trait_name) in derives.into_iter() {
1801 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1803 if last_self_name == &self_name {
1804 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1808 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1811 let len = traits.len();
1813 let span: MultiSpan = traits.into();
1816 &format!("the following trait{} must be implemented", pluralize!(len),),
1820 for (self_name, self_span, traits) in &derives_grouped {
1821 err.span_suggestion_verbose(
1822 self_span.shrink_to_lo(),
1823 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1824 format!("#[derive({})]\n", traits),
1825 Applicability::MaybeIncorrect,
1830 fn check_for_deref_method(
1832 err: &mut Diagnostic,
1833 self_source: SelfSource<'tcx>,
1837 let SelfSource::QPath(ty) = self_source else { return; };
1838 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1839 if let Ok(pick) = self.probe_for_name(
1846 ProbeScope::TraitsInScope,
1848 if deref_ty.is_suggestable(self.tcx, true)
1849 // If this method receives `&self`, then the provided
1850 // argument _should_ coerce, so it's valid to suggest
1851 // just changing the path.
1852 && pick.item.fn_has_self_parameter
1853 && let Some(self_ty) =
1854 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1857 let suggested_path = match deref_ty.kind() {
1866 | ty::Param(_) => format!("{deref_ty}"),
1867 _ => format!("<{deref_ty}>"),
1869 err.span_suggestion_verbose(
1871 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1873 Applicability::MaybeIncorrect,
1878 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1886 /// Print out the type for use in value namespace.
1887 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1889 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1890 _ => self.ty_to_string(ty),
1894 fn suggest_await_before_method(
1896 err: &mut Diagnostic,
1899 call: &hir::Expr<'_>,
1902 let output_ty = match self.get_impl_future_output_ty(ty) {
1903 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1906 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1907 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1909 err.span_suggestion_verbose(
1910 span.shrink_to_lo(),
1911 "consider `await`ing on the `Future` and calling the method on its `Output`",
1913 Applicability::MaybeIncorrect,
1918 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1919 let parent_map = self.tcx.visible_parent_map(());
1921 // Separate out candidates that must be imported with a glob, because they are named `_`
1922 // and cannot be referred with their identifier.
1923 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1924 if let Some(parent_did) = parent_map.get(trait_did) {
1925 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1926 if *parent_did != self.tcx.parent(*trait_did)
1929 .module_children(*parent_did)
1931 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1932 .all(|child| child.ident.name == kw::Underscore)
1941 let module_did = self.tcx.parent_module(self.body_id);
1942 let (module, _, _) = self.tcx.hir().get_module(module_did);
1943 let span = module.spans.inject_use_span;
1945 let path_strings = candidates.iter().map(|trait_did| {
1946 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1949 let glob_path_strings = globs.iter().map(|trait_did| {
1950 let parent_did = parent_map.get(trait_did).unwrap();
1952 "use {}::*; // trait {}\n",
1953 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1954 self.tcx.item_name(*trait_did),
1958 err.span_suggestions(
1961 path_strings.chain(glob_path_strings),
1962 Applicability::MaybeIncorrect,
1966 fn suggest_valid_traits(
1968 err: &mut Diagnostic,
1969 valid_out_of_scope_traits: Vec<DefId>,
1971 if !valid_out_of_scope_traits.is_empty() {
1972 let mut candidates = valid_out_of_scope_traits;
1976 // `TryFrom` and `FromIterator` have no methods
1977 let edition_fix = candidates
1979 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1982 err.help("items from traits can only be used if the trait is in scope");
1984 "the following {traits_are} implemented but not in scope; \
1985 perhaps add a `use` for {one_of_them}:",
1986 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1987 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1990 self.suggest_use_candidates(err, msg, candidates);
1991 if let Some(did) = edition_fix {
1993 "'{}' is included in the prelude starting in Edition 2021",
1994 with_crate_prefix!(self.tcx.def_path_str(did))
2004 fn suggest_traits_to_import(
2006 err: &mut Diagnostic,
2010 inputs_len: Option<usize>,
2011 source: SelfSource<'tcx>,
2012 valid_out_of_scope_traits: Vec<DefId>,
2013 unsatisfied_predicates: &[(
2014 ty::Predicate<'tcx>,
2015 Option<ty::Predicate<'tcx>>,
2016 Option<ObligationCause<'tcx>>,
2018 unsatisfied_bounds: bool,
2020 let mut alt_rcvr_sugg = false;
2021 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2022 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
2024 self.tcx.lang_items().clone_trait(),
2025 self.tcx.lang_items().deref_trait(),
2026 self.tcx.lang_items().deref_mut_trait(),
2027 self.tcx.lang_items().drop_trait(),
2028 self.tcx.get_diagnostic_item(sym::AsRef),
2030 // Try alternative arbitrary self types that could fulfill this call.
2031 // FIXME: probe for all types that *could* be arbitrary self-types, not
2033 for (rcvr_ty, post) in &[
2035 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2036 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2038 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2040 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2041 // We point at the method, but we just skip the rest of the check for arbitrary
2042 // self types and rely on the suggestion to `use` the trait from
2043 // `suggest_valid_traits`.
2044 let did = Some(pick.item.container_id(self.tcx));
2045 let skip = skippable.contains(&did);
2046 if pick.autoderefs == 0 && !skip {
2048 pick.item.ident(self.tcx).span,
2049 &format!("the method is available for `{}` here", rcvr_ty),
2054 Err(MethodError::Ambiguity(_)) => {
2055 // If the method is defined (but ambiguous) for the receiver we have, it is also
2056 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2057 // the receiver, then it might disambiguate this method, but I think these
2058 // suggestions are generally misleading (see #94218).
2064 for (rcvr_ty, pre) in &[
2065 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2066 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2067 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2068 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2070 if let Some(new_rcvr_t) = *rcvr_ty
2071 && let Ok(pick) = self.lookup_probe(
2076 ProbeScope::AllTraits,
2079 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2080 let did = Some(pick.item.container_id(self.tcx));
2081 // We don't want to suggest a container type when the missing
2082 // method is `.clone()` or `.deref()` otherwise we'd suggest
2083 // `Arc::new(foo).clone()`, which is far from what the user wants.
2084 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2085 // implement the `AsRef` trait.
2086 let skip = skippable.contains(&did)
2087 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2088 || 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);
2089 // Make sure the method is defined for the *actual* receiver: we don't
2090 // want to treat `Box<Self>` as a receiver if it only works because of
2091 // an autoderef to `&self`
2092 if pick.autoderefs == 0 && !skip {
2094 pick.item.ident(self.tcx).span,
2095 &format!("the method is available for `{}` here", new_rcvr_t),
2097 err.multipart_suggestion(
2098 "consider wrapping the receiver expression with the \
2101 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2102 (rcvr.span.shrink_to_hi(), ")".to_string()),
2104 Applicability::MaybeIncorrect,
2106 // We don't care about the other suggestions.
2107 alt_rcvr_sugg = true;
2113 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2117 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2119 let mut arbitrary_rcvr = vec![];
2120 // There are no traits implemented, so lets suggest some traits to
2121 // implement, by finding ones that have the item name, and are
2122 // legal to implement.
2123 let mut candidates = all_traits(self.tcx)
2125 // Don't issue suggestions for unstable traits since they're
2126 // unlikely to be implementable anyway
2127 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2128 Some(attr) => attr.level.is_stable(),
2132 // We approximate the coherence rules to only suggest
2133 // traits that are legal to implement by requiring that
2134 // either the type or trait is local. Multi-dispatch means
2135 // this isn't perfect (that is, there are cases when
2136 // implementing a trait would be legal but is rejected
2138 unsatisfied_predicates.iter().all(|(p, _, _)| {
2139 match p.kind().skip_binder() {
2140 // Hide traits if they are present in predicates as they can be fixed without
2141 // having to implement them.
2142 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2143 ty::PredicateKind::Projection(p) => {
2144 p.projection_ty.item_def_id == info.def_id
2148 }) && (type_is_local || info.def_id.is_local())
2150 .associated_value(info.def_id, item_name)
2152 if let ty::AssocKind::Fn = item.kind {
2156 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2157 if let Some(hir::Node::TraitItem(hir::TraitItem {
2158 kind: hir::TraitItemKind::Fn(fn_sig, method),
2160 })) = id.map(|id| self.tcx.hir().get(id))
2162 let self_first_arg = match method {
2163 hir::TraitFn::Required([ident, ..]) => {
2164 ident.name == kw::SelfLower
2166 hir::TraitFn::Provided(body_id) => {
2167 self.tcx.hir().body(*body_id).params.first().map_or(
2172 hir::PatKind::Binding(_, _, ident, _)
2173 if ident.name == kw::SelfLower
2181 if !fn_sig.decl.implicit_self.has_implicit_self()
2184 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2185 arbitrary_rcvr.push(ty.span);
2191 // We only want to suggest public or local traits (#45781).
2192 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2196 .collect::<Vec<_>>();
2197 for span in &arbitrary_rcvr {
2200 "the method might not be found because of this arbitrary self type",
2207 if !candidates.is_empty() {
2208 // Sort from most relevant to least relevant.
2209 candidates.sort_by(|a, b| a.cmp(b).reverse());
2212 let param_type = match rcvr_ty.kind() {
2213 ty::Param(param) => Some(param),
2214 ty::Ref(_, ty, _) => match ty.kind() {
2215 ty::Param(param) => Some(param),
2220 err.help(if param_type.is_some() {
2221 "items from traits can only be used if the type parameter is bounded by the trait"
2223 "items from traits can only be used if the trait is implemented and in scope"
2225 let candidates_len = candidates.len();
2226 let message = |action| {
2228 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2231 if candidates_len == 1 { "trait defines" } else { "traits define" },
2233 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2237 // Obtain the span for `param` and use it for a structured suggestion.
2238 if let Some(param) = param_type {
2239 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2240 let type_param = generics.type_param(param, self.tcx);
2241 let hir = self.tcx.hir();
2242 if let Some(def_id) = type_param.def_id.as_local() {
2243 let id = hir.local_def_id_to_hir_id(def_id);
2244 // Get the `hir::Param` to verify whether it already has any bounds.
2245 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2246 // instead we suggest `T: Foo + Bar` in that case.
2248 Node::GenericParam(param) => {
2254 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2255 let (sp, mut introducer) = if let Some(span) =
2256 ast_generics.bounds_span_for_suggestions(def_id)
2258 (span, Introducer::Plus)
2259 } else if let Some(colon_span) = param.colon_span {
2260 (colon_span.shrink_to_hi(), Introducer::Nothing)
2262 (param.span.shrink_to_hi(), Introducer::Colon)
2266 hir::GenericParamKind::Type { synthetic: true, .. },
2268 introducer = Introducer::Plus
2270 let trait_def_ids: FxHashSet<DefId> = ast_generics
2271 .bounds_for_param(def_id)
2272 .flat_map(|bp| bp.bounds.iter())
2273 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2275 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2276 err.span_suggestions(
2279 "restrict type parameter `{}` with",
2282 candidates.iter().map(|t| {
2286 Introducer::Plus => " +",
2287 Introducer::Colon => ":",
2288 Introducer::Nothing => "",
2290 self.tcx.def_path_str(t.def_id),
2293 Applicability::MaybeIncorrect,
2298 Node::Item(hir::Item {
2299 kind: hir::ItemKind::Trait(.., bounds, _),
2303 let (sp, sep, article) = if bounds.is_empty() {
2304 (ident.span.shrink_to_hi(), ":", "a")
2306 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2308 err.span_suggestions(
2310 &message(format!("add {} supertrait for", article)),
2311 candidates.iter().map(|t| {
2312 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2314 Applicability::MaybeIncorrect,
2323 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2324 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2325 // cases where a positive bound implies a negative impl.
2326 (candidates, Vec::new())
2327 } else if let Some(simp_rcvr_ty) =
2328 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2330 let mut potential_candidates = Vec::new();
2331 let mut explicitly_negative = Vec::new();
2332 for candidate in candidates {
2333 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2336 .all_impls(candidate.def_id)
2338 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2341 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2343 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2344 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2347 explicitly_negative.push(candidate);
2349 potential_candidates.push(candidate);
2352 (potential_candidates, explicitly_negative)
2354 // We don't know enough about `recv_ty` to make proper suggestions.
2355 (candidates, Vec::new())
2358 let action = if let Some(param) = param_type {
2359 format!("restrict type parameter `{}` with", param)
2361 // FIXME: it might only need to be imported into scope, not implemented.
2362 "implement".to_string()
2364 match &potential_candidates[..] {
2366 [trait_info] if trait_info.def_id.is_local() => {
2368 self.tcx.def_span(trait_info.def_id),
2370 "`{}` defines an item `{}`, perhaps you need to {} it",
2371 self.tcx.def_path_str(trait_info.def_id),
2378 let mut msg = message(action);
2379 for (i, trait_info) in trait_infos.iter().enumerate() {
2380 msg.push_str(&format!(
2381 "\ncandidate #{}: `{}`",
2383 self.tcx.def_path_str(trait_info.def_id),
2389 match &explicitly_negative[..] {
2393 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2394 self.tcx.def_path_str(trait_info.def_id),
2400 let mut msg = format!(
2401 "the following traits define an item `{}`, but are explicitly unimplemented:",
2404 for trait_info in trait_infos {
2405 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2413 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2414 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2415 pub(crate) fn suggest_else_fn_with_closure(
2417 err: &mut Diagnostic,
2418 expr: &hir::Expr<'_>,
2422 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2423 else { return false; };
2425 if !self.can_coerce(output, expected) {
2429 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2430 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2431 let hir::ExprKind::MethodCall(
2432 hir::PathSegment { ident: method_name, .. },
2436 ) = call_expr.kind &&
2437 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2438 let new_name = Ident {
2439 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2440 span: method_name.span,
2442 let probe = self.lookup_probe(
2447 ProbeScope::TraitsInScope,
2450 // check the method arguments number
2451 if let Ok(pick) = probe &&
2452 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2453 let fn_args = fn_sig.skip_binder().inputs() &&
2454 fn_args.len() == args.len() + 1 {
2455 err.span_suggestion_verbose(
2456 method_name.span.shrink_to_hi(),
2457 &format!("try calling `{}` instead", new_name.name.as_str()),
2459 Applicability::MaybeIncorrect,
2467 /// Checks whether there is a local type somewhere in the chain of
2468 /// autoderefs of `rcvr_ty`.
2469 fn type_derefs_to_local(
2473 source: SelfSource<'tcx>,
2475 fn is_local(ty: Ty<'_>) -> bool {
2477 ty::Adt(def, _) => def.did().is_local(),
2478 ty::Foreign(did) => did.is_local(),
2479 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2480 ty::Param(_) => true,
2482 // Everything else (primitive types, etc.) is effectively
2483 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2484 // the noise from these sort of types is usually just really
2485 // annoying, rather than any sort of help).
2490 // This occurs for UFCS desugaring of `T::method`, where there is no
2491 // receiver expression for the method call, and thus no autoderef.
2492 if let SelfSource::QPath(_) = source {
2493 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2496 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2500 #[derive(Copy, Clone, Debug)]
2501 pub enum SelfSource<'a> {
2502 QPath(&'a hir::Ty<'a>),
2503 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2506 #[derive(Copy, Clone)]
2507 pub struct TraitInfo {
2511 impl PartialEq for TraitInfo {
2512 fn eq(&self, other: &TraitInfo) -> bool {
2513 self.cmp(other) == Ordering::Equal
2516 impl Eq for TraitInfo {}
2517 impl PartialOrd for TraitInfo {
2518 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2519 Some(self.cmp(other))
2522 impl Ord for TraitInfo {
2523 fn cmp(&self, other: &TraitInfo) -> Ordering {
2524 // Local crates are more important than remote ones (local:
2525 // `cnum == 0`), and otherwise we throw in the defid for totality.
2527 let lhs = (other.def_id.krate, other.def_id);
2528 let rhs = (self.def_id.krate, self.def_id);
2533 /// Retrieves all traits in this crate and any dependent crates,
2534 /// and wraps them into `TraitInfo` for custom sorting.
2535 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2536 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2539 fn print_disambiguation_help<'tcx>(
2541 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2542 err: &mut Diagnostic,
2545 kind: ty::AssocKind,
2548 candidate: Option<usize>,
2549 source_map: &source_map::SourceMap,
2550 fn_has_self_parameter: bool,
2552 let mut applicability = Applicability::MachineApplicable;
2553 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2556 if rcvr_ty.is_region_ptr() {
2557 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2561 std::iter::once(receiver)
2563 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2564 applicability = Applicability::HasPlaceholders;
2567 .collect::<Vec<_>>()
2570 let trait_name = if !fn_has_self_parameter {
2571 format!("<{} as {}>", rcvr_ty, trait_name)
2575 (span, format!("{}::{}{}", trait_name, item_name, args))
2577 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2579 err.span_suggestion_verbose(
2582 "disambiguate the {} for {}",
2583 kind.as_def_kind().descr(def_id),
2584 if let Some(candidate) = candidate {
2585 format!("candidate #{}", candidate)
2587 "the candidate".to_string()