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 sources: &mut 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: mut 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, &mut static_sources, sugg_span);
426 } else if static_sources.len() > 1 {
427 report_candidates(span, &mut err, &mut 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,
1015 // Don't emit a suggestion if we found an actual method
1016 // that had unsatisfied trait bounds
1017 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1018 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1019 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1020 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1024 err.span_suggestion(
1026 "there is a variant with a similar name",
1028 Applicability::MaybeIncorrect,
1033 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1034 let msg = "remove this method call";
1035 let mut fallback_span = true;
1036 if let SelfSource::MethodCall(expr) = source {
1038 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1039 if let Some(span) = call_expr.span.trim_start(expr.span) {
1040 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1041 fallback_span = false;
1045 err.span_label(span, msg);
1047 } else if let Some(lev_candidate) = lev_candidate {
1048 // Don't emit a suggestion if we found an actual method
1049 // that had unsatisfied trait bounds
1050 if unsatisfied_predicates.is_empty() {
1051 let def_kind = lev_candidate.kind.as_def_kind();
1052 // Methods are defined within the context of a struct and their first parameter is always self,
1053 // which represents the instance of the struct the method is being called on
1054 // Associated functions don’t take self as a parameter and
1055 // they are not methods because they don’t have an instance of the struct to work with.
1056 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1057 err.span_suggestion(
1059 &format!("there is a method with a similar name",),
1061 Applicability::MaybeIncorrect,
1064 err.span_suggestion(
1067 "there is {} {} with a similar name",
1069 def_kind.descr(lev_candidate.def_id),
1072 Applicability::MaybeIncorrect,
1078 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1083 MethodError::Ambiguity(mut sources) => {
1084 let mut err = struct_span_err!(
1088 "multiple applicable items in scope"
1090 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1092 report_candidates(span, &mut err, &mut sources, sugg_span);
1096 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1097 let kind = kind.descr(def_id);
1098 let mut err = struct_span_err!(
1102 "{} `{}` is private",
1106 err.span_label(item_name.span, &format!("private {}", kind));
1110 .span_if_local(def_id)
1111 .unwrap_or_else(|| self.tcx.def_span(def_id));
1112 err.span_label(sp, &format!("private {} defined here", kind));
1113 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1117 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1118 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1119 let mut err = self.sess().struct_span_err(span, &msg);
1120 err.span_label(bound_span, "this has a `Sized` requirement");
1121 if !candidates.is_empty() {
1123 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1124 add a `use` for {one_of_them}:",
1125 an = if candidates.len() == 1 { "an" } else { "" },
1126 s = pluralize!(candidates.len()),
1127 were = pluralize!("was", candidates.len()),
1128 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1130 self.suggest_use_candidates(&mut err, help, candidates);
1132 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1134 let trait_type = self.tcx.mk_ref(
1136 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1138 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1144 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1149 fn suggest_field_call(
1153 expr: &hir::Expr<'_>,
1155 err: &mut Diagnostic,
1158 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1159 ty::Adt(def, substs) if !def.is_enum() => {
1160 let variant = &def.non_enum_variant();
1161 tcx.find_field_index(item_name, variant).map(|index| {
1162 let field = &variant.fields[index];
1163 let field_ty = field.ty(tcx, substs);
1169 if let Some((field, field_ty)) = field_receiver {
1170 let scope = tcx.parent_module(self.body_id);
1171 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1174 if self.is_fn_ty(field_ty, span) {
1175 let expr_span = expr.span.to(item_name.span);
1176 err.multipart_suggestion(
1178 "to call the function stored in `{}`, \
1179 surround the field access with parentheses",
1183 (expr_span.shrink_to_lo(), '('.to_string()),
1184 (expr_span.shrink_to_hi(), ')'.to_string()),
1186 Applicability::MachineApplicable,
1189 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1191 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1192 err.span_suggestion(
1194 "remove the arguments",
1196 Applicability::MaybeIncorrect,
1202 let field_kind = if is_accessible { "field" } else { "private field" };
1203 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1209 /// Suggest possible range with adding parentheses, for example:
1210 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1211 fn suggest_wrapping_range_with_parens(
1215 source: SelfSource<'tcx>,
1220 if let SelfSource::MethodCall(expr) = source {
1221 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1222 if let Node::Expr(parent_expr) = parent {
1223 let lang_item = match parent_expr.kind {
1224 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1225 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1226 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1227 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1228 Some(LangItem::RangeToInclusive)
1232 ExprKind::Call(ref func, _) => match func.kind {
1233 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1234 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1235 Some(LangItem::RangeInclusiveStruct)
1242 if lang_item.is_none() {
1246 let span_included = match parent_expr.kind {
1247 hir::ExprKind::Struct(_, eps, _) => {
1248 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1250 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1251 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1259 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1261 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1263 let pick = self.probe_for_name(
1270 ProbeScope::AllTraits,
1273 let range_span = parent_expr.span.with_hi(expr.span.hi());
1274 tcx.sess.emit_err(errors::MissingParentheseInRange {
1276 ty_str: ty_str.to_string(),
1277 method_name: item_name.as_str().to_string(),
1278 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1279 func_name: item_name.name.as_str().to_string(),
1280 left: range_span.shrink_to_lo(),
1281 right: range_span.shrink_to_hi(),
1292 fn suggest_constraining_numerical_ty(
1296 source: SelfSource<'_>,
1302 let found_candidate = all_traits(self.tcx)
1304 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1305 let found_assoc = |ty: Ty<'tcx>| {
1306 simplify_type(tcx, ty, TreatParams::AsInfer)
1308 tcx.incoherent_impls(simp)
1310 .find_map(|&id| self.associated_value(id, item_name))
1314 let found_candidate = found_candidate
1315 || found_assoc(tcx.types.i8)
1316 || found_assoc(tcx.types.i16)
1317 || found_assoc(tcx.types.i32)
1318 || found_assoc(tcx.types.i64)
1319 || found_assoc(tcx.types.i128)
1320 || found_assoc(tcx.types.u8)
1321 || found_assoc(tcx.types.u16)
1322 || found_assoc(tcx.types.u32)
1323 || found_assoc(tcx.types.u64)
1324 || found_assoc(tcx.types.u128)
1325 || found_assoc(tcx.types.f32)
1326 || found_assoc(tcx.types.f32);
1328 && actual.is_numeric()
1329 && !actual.has_concrete_skeleton()
1330 && let SelfSource::MethodCall(expr) = source
1332 let mut err = struct_span_err!(
1336 "can't call {} `{}` on ambiguous numeric type `{}`",
1341 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1343 ExprKind::Lit(ref lit) => {
1348 .span_to_snippet(lit.span)
1349 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1351 // If this is a floating point literal that ends with '.',
1352 // get rid of it to stop this from becoming a member access.
1353 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1354 err.span_suggestion(
1357 "you must specify a concrete type for this numeric value, \
1361 format!("{snippet}_{concrete_type}"),
1362 Applicability::MaybeIncorrect,
1365 ExprKind::Path(QPath::Resolved(_, path)) => {
1367 if let hir::def::Res::Local(hir_id) = path.res {
1368 let span = tcx.hir().span(hir_id);
1369 let filename = tcx.sess.source_map().span_to_filename(span);
1372 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1374 "you must specify a type for this binding, like `{}`",
1378 match (filename, parent_node) {
1381 Node::Local(hir::Local {
1382 source: hir::LocalSource::Normal,
1387 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1388 err.span_suggestion(
1389 // account for `let x: _ = 42;`
1393 format!(": {concrete_type}"),
1394 Applicability::MaybeIncorrect,
1398 err.span_label(span, msg);
1411 fn check_for_field_method(
1413 err: &mut Diagnostic,
1414 source: SelfSource<'tcx>,
1419 if let SelfSource::MethodCall(expr) = source
1420 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1421 && let Some((fields, substs)) =
1422 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1424 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1426 let lang_items = self.tcx.lang_items();
1427 let never_mention_traits = [
1428 lang_items.clone_trait(),
1429 lang_items.deref_trait(),
1430 lang_items.deref_mut_trait(),
1431 self.tcx.get_diagnostic_item(sym::AsRef),
1432 self.tcx.get_diagnostic_item(sym::AsMut),
1433 self.tcx.get_diagnostic_item(sym::Borrow),
1434 self.tcx.get_diagnostic_item(sym::BorrowMut),
1436 let candidate_fields: Vec<_> = fields
1437 .filter_map(|candidate_field| {
1438 self.check_for_nested_field_satisfying(
1446 ProbeScope::TraitsInScope,
1448 .map_or(false, |pick| {
1449 !never_mention_traits
1452 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1464 .map(|id| id.name.to_ident_string())
1465 .collect::<Vec<String>>()
1470 let len = candidate_fields.len();
1472 err.span_suggestions(
1473 item_name.span.shrink_to_lo(),
1475 "{} of the expressions' fields {} a method of the same name",
1476 if len > 1 { "some" } else { "one" },
1477 if len > 1 { "have" } else { "has" },
1479 candidate_fields.iter().map(|path| format!("{path}.")),
1480 Applicability::MaybeIncorrect,
1486 fn check_for_inner_self(
1488 err: &mut Diagnostic,
1489 source: SelfSource<'tcx>,
1495 let SelfSource::MethodCall(expr) = source else { return; };
1496 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1498 let ty::Adt(kind, substs) = actual.kind() else { return; };
1499 match kind.adt_kind() {
1500 ty::AdtKind::Enum => {
1501 let matching_variants: Vec<_> = kind
1504 .flat_map(|variant| {
1505 let [field] = &variant.fields[..] else { return None; };
1506 let field_ty = field.ty(tcx, substs);
1508 // Skip `_`, since that'll just lead to ambiguity.
1509 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1518 ProbeScope::TraitsInScope,
1521 .map(|pick| (variant, field, pick))
1525 let ret_ty_matches = |diagnostic_item| {
1526 if let Some(ret_ty) = self
1529 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1530 && let ty::Adt(kind, _) = ret_ty.kind()
1531 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1539 match &matching_variants[..] {
1540 [(_, field, pick)] => {
1541 let self_ty = field.ty(tcx, substs);
1543 tcx.def_span(pick.item.def_id),
1544 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1546 let (article, kind, variant, question) =
1547 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1548 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1549 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1550 ("an", "Option", "None", ret_ty_matches(sym::Option))
1555 err.span_suggestion_verbose(
1556 expr.span.shrink_to_hi(),
1558 "use the `?` operator to extract the `{self_ty}` value, propagating \
1559 {article} `{kind}::{variant}` value to the caller"
1562 Applicability::MachineApplicable,
1565 err.span_suggestion_verbose(
1566 expr.span.shrink_to_hi(),
1568 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1569 panicking if the value is {article} `{kind}::{variant}`"
1571 ".expect(\"REASON\")",
1572 Applicability::HasPlaceholders,
1576 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1580 // Target wrapper types - types that wrap or pretend to wrap another type,
1581 // perhaps this inner type is meant to be called?
1582 ty::AdtKind::Struct | ty::AdtKind::Union => {
1583 let [first] = ***substs else { return; };
1584 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1585 let Ok(pick) = self.lookup_probe(
1590 ProbeScope::TraitsInScope,
1593 let name = self.ty_to_value_string(actual);
1594 let inner_id = kind.did();
1595 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1596 pick.autoref_or_ptr_adjustment
1603 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1604 err.help("use `with` or `try_with` to access thread local storage");
1605 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1607 "if this `{name}` has been initialized, \
1608 use one of the `assume_init` methods to access the inner value"
1610 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1611 let (suggestion, borrow_kind, panic_if) = match mutable {
1612 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1613 Some(Mutability::Mut) => {
1614 (".borrow_mut()", "mutably borrow", "any borrows exist")
1618 err.span_suggestion_verbose(
1619 expr.span.shrink_to_hi(),
1621 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1622 panicking if {panic_if}"
1625 Applicability::MaybeIncorrect,
1627 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1628 err.span_suggestion_verbose(
1629 expr.span.shrink_to_hi(),
1631 "use `.lock().unwrap()` to borrow the `{ty}`, \
1632 blocking the current thread until it can be acquired"
1635 Applicability::MaybeIncorrect,
1637 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1638 let (suggestion, borrow_kind) = match mutable {
1639 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1640 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1643 err.span_suggestion_verbose(
1644 expr.span.shrink_to_hi(),
1646 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1647 blocking the current thread until it can be acquired"
1650 Applicability::MaybeIncorrect,
1657 tcx.def_span(pick.item.def_id),
1658 &format!("the method `{item_name}` exists on the type `{ty}`"),
1664 pub(crate) fn note_unmet_impls_on_type(
1666 err: &mut Diagnostic,
1667 errors: Vec<FulfillmentError<'tcx>>,
1669 let all_local_types_needing_impls =
1670 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1671 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1672 ty::Adt(def, _) => def.did().is_local(),
1677 let mut preds: Vec<_> = errors
1679 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1680 ty::PredicateKind::Trait(pred) => Some(pred),
1684 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1687 .filter_map(|pred| match pred.self_ty().kind() {
1688 ty::Adt(def, _) => Some(def.did()),
1691 .collect::<FxHashSet<_>>();
1692 let mut spans: MultiSpan = def_ids
1694 .filter_map(|def_id| {
1695 let span = self.tcx.def_span(*def_id);
1696 if span.is_dummy() { None } else { Some(span) }
1698 .collect::<Vec<_>>()
1701 for pred in &preds {
1702 match pred.self_ty().kind() {
1703 ty::Adt(def, _) if def.did().is_local() => {
1704 spans.push_span_label(
1705 self.tcx.def_span(def.did()),
1706 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1713 if all_local_types_needing_impls && spans.primary_span().is_some() {
1714 let msg = if preds.len() == 1 {
1716 "an implementation of `{}` might be missing for `{}`",
1717 preds[0].trait_ref.print_only_trait_path(),
1722 "the following type{} would have to `impl` {} required trait{} for this \
1723 operation to be valid",
1724 pluralize!(def_ids.len()),
1725 if def_ids.len() == 1 { "its" } else { "their" },
1726 pluralize!(preds.len()),
1729 err.span_note(spans, &msg);
1732 let preds: Vec<_> = errors
1734 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1736 self.suggest_derive(err, &preds);
1741 err: &mut Diagnostic,
1742 unsatisfied_predicates: &[(
1743 ty::Predicate<'tcx>,
1744 Option<ty::Predicate<'tcx>>,
1745 Option<ObligationCause<'tcx>>,
1748 let mut derives = Vec::<(String, Span, Symbol)>::new();
1749 let mut traits = Vec::<Span>::new();
1750 for (pred, _, _) in unsatisfied_predicates {
1751 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1752 let adt = match trait_pred.self_ty().ty_adt_def() {
1753 Some(adt) if adt.did().is_local() => adt,
1756 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1757 let can_derive = match diagnostic_name {
1758 sym::Default => !adt.is_enum(),
1766 | sym::Debug => true,
1770 let self_name = trait_pred.self_ty().to_string();
1771 let self_span = self.tcx.def_span(adt.did());
1772 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1773 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1775 if let Some(parent_diagnostic_name) =
1776 self.tcx.get_diagnostic_name(super_trait.def_id())
1781 parent_diagnostic_name,
1786 derives.push((self_name, self_span, diagnostic_name));
1788 traits.push(self.tcx.def_span(trait_pred.def_id()));
1791 traits.push(self.tcx.def_span(trait_pred.def_id()));
1800 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1801 for (self_name, self_span, trait_name) in derives.into_iter() {
1802 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1804 if last_self_name == &self_name {
1805 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1809 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1812 let len = traits.len();
1814 let span: MultiSpan = traits.into();
1817 &format!("the following trait{} must be implemented", pluralize!(len),),
1821 for (self_name, self_span, traits) in &derives_grouped {
1822 err.span_suggestion_verbose(
1823 self_span.shrink_to_lo(),
1824 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1825 format!("#[derive({})]\n", traits),
1826 Applicability::MaybeIncorrect,
1831 fn check_for_deref_method(
1833 err: &mut Diagnostic,
1834 self_source: SelfSource<'tcx>,
1838 let SelfSource::QPath(ty) = self_source else { return; };
1839 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1840 if let Ok(pick) = self.probe_for_name(
1847 ProbeScope::TraitsInScope,
1849 if deref_ty.is_suggestable(self.tcx, true)
1850 // If this method receives `&self`, then the provided
1851 // argument _should_ coerce, so it's valid to suggest
1852 // just changing the path.
1853 && pick.item.fn_has_self_parameter
1854 && let Some(self_ty) =
1855 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1858 let suggested_path = match deref_ty.kind() {
1867 | ty::Param(_) => format!("{deref_ty}"),
1868 _ => format!("<{deref_ty}>"),
1870 err.span_suggestion_verbose(
1872 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1874 Applicability::MaybeIncorrect,
1879 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1887 /// Print out the type for use in value namespace.
1888 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1890 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1891 _ => self.ty_to_string(ty),
1895 fn suggest_await_before_method(
1897 err: &mut Diagnostic,
1900 call: &hir::Expr<'_>,
1903 let output_ty = match self.get_impl_future_output_ty(ty) {
1904 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1907 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1908 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1910 err.span_suggestion_verbose(
1911 span.shrink_to_lo(),
1912 "consider `await`ing on the `Future` and calling the method on its `Output`",
1914 Applicability::MaybeIncorrect,
1919 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1920 let parent_map = self.tcx.visible_parent_map(());
1922 // Separate out candidates that must be imported with a glob, because they are named `_`
1923 // and cannot be referred with their identifier.
1924 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1925 if let Some(parent_did) = parent_map.get(trait_did) {
1926 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1927 if *parent_did != self.tcx.parent(*trait_did)
1930 .module_children(*parent_did)
1932 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1933 .all(|child| child.ident.name == kw::Underscore)
1942 let module_did = self.tcx.parent_module(self.body_id);
1943 let (module, _, _) = self.tcx.hir().get_module(module_did);
1944 let span = module.spans.inject_use_span;
1946 let path_strings = candidates.iter().map(|trait_did| {
1947 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1950 let glob_path_strings = globs.iter().map(|trait_did| {
1951 let parent_did = parent_map.get(trait_did).unwrap();
1953 "use {}::*; // trait {}\n",
1954 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1955 self.tcx.item_name(*trait_did),
1959 err.span_suggestions(
1962 path_strings.chain(glob_path_strings),
1963 Applicability::MaybeIncorrect,
1967 fn suggest_valid_traits(
1969 err: &mut Diagnostic,
1970 valid_out_of_scope_traits: Vec<DefId>,
1972 if !valid_out_of_scope_traits.is_empty() {
1973 let mut candidates = valid_out_of_scope_traits;
1977 // `TryFrom` and `FromIterator` have no methods
1978 let edition_fix = candidates
1980 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1983 err.help("items from traits can only be used if the trait is in scope");
1985 "the following {traits_are} implemented but not in scope; \
1986 perhaps add a `use` for {one_of_them}:",
1987 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1988 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1991 self.suggest_use_candidates(err, msg, candidates);
1992 if let Some(did) = edition_fix {
1994 "'{}' is included in the prelude starting in Edition 2021",
1995 with_crate_prefix!(self.tcx.def_path_str(did))
2005 fn suggest_traits_to_import(
2007 err: &mut Diagnostic,
2011 inputs_len: Option<usize>,
2012 source: SelfSource<'tcx>,
2013 valid_out_of_scope_traits: Vec<DefId>,
2014 unsatisfied_predicates: &[(
2015 ty::Predicate<'tcx>,
2016 Option<ty::Predicate<'tcx>>,
2017 Option<ObligationCause<'tcx>>,
2019 static_candidates: &[CandidateSource],
2020 unsatisfied_bounds: bool,
2022 let mut alt_rcvr_sugg = false;
2023 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2024 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
2026 self.tcx.lang_items().clone_trait(),
2027 self.tcx.lang_items().deref_trait(),
2028 self.tcx.lang_items().deref_mut_trait(),
2029 self.tcx.lang_items().drop_trait(),
2030 self.tcx.get_diagnostic_item(sym::AsRef),
2032 // Try alternative arbitrary self types that could fulfill this call.
2033 // FIXME: probe for all types that *could* be arbitrary self-types, not
2035 for (rcvr_ty, post) in &[
2037 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2038 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2040 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2042 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2043 // We point at the method, but we just skip the rest of the check for arbitrary
2044 // self types and rely on the suggestion to `use` the trait from
2045 // `suggest_valid_traits`.
2046 let did = Some(pick.item.container_id(self.tcx));
2047 let skip = skippable.contains(&did);
2048 if pick.autoderefs == 0 && !skip {
2050 pick.item.ident(self.tcx).span,
2051 &format!("the method is available for `{}` here", rcvr_ty),
2056 Err(MethodError::Ambiguity(_)) => {
2057 // If the method is defined (but ambiguous) for the receiver we have, it is also
2058 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2059 // the receiver, then it might disambiguate this method, but I think these
2060 // suggestions are generally misleading (see #94218).
2066 for (rcvr_ty, pre) in &[
2067 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2068 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2069 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2070 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2072 if let Some(new_rcvr_t) = *rcvr_ty
2073 && let Ok(pick) = self.lookup_probe(
2078 ProbeScope::AllTraits,
2081 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2082 let did = Some(pick.item.container_id(self.tcx));
2083 // We don't want to suggest a container type when the missing
2084 // method is `.clone()` or `.deref()` otherwise we'd suggest
2085 // `Arc::new(foo).clone()`, which is far from what the user wants.
2086 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2087 // implement the `AsRef` trait.
2088 let skip = skippable.contains(&did)
2089 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2090 || 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);
2091 // Make sure the method is defined for the *actual* receiver: we don't
2092 // want to treat `Box<Self>` as a receiver if it only works because of
2093 // an autoderef to `&self`
2094 if pick.autoderefs == 0 && !skip {
2096 pick.item.ident(self.tcx).span,
2097 &format!("the method is available for `{}` here", new_rcvr_t),
2099 err.multipart_suggestion(
2100 "consider wrapping the receiver expression with the \
2103 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2104 (rcvr.span.shrink_to_hi(), ")".to_string()),
2106 Applicability::MaybeIncorrect,
2108 // We don't care about the other suggestions.
2109 alt_rcvr_sugg = true;
2115 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2119 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2121 let mut arbitrary_rcvr = vec![];
2122 // There are no traits implemented, so lets suggest some traits to
2123 // implement, by finding ones that have the item name, and are
2124 // legal to implement.
2125 let mut candidates = all_traits(self.tcx)
2127 // Don't issue suggestions for unstable traits since they're
2128 // unlikely to be implementable anyway
2129 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2130 Some(attr) => attr.level.is_stable(),
2134 // Static candidates are already implemented, and known not to work
2135 // Do not suggest them again
2136 static_candidates.iter().all(|sc| match *sc {
2137 CandidateSource::Trait(def_id) => def_id != info.def_id,
2138 CandidateSource::Impl(def_id) => {
2139 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2144 // We approximate the coherence rules to only suggest
2145 // traits that are legal to implement by requiring that
2146 // either the type or trait is local. Multi-dispatch means
2147 // this isn't perfect (that is, there are cases when
2148 // implementing a trait would be legal but is rejected
2150 unsatisfied_predicates.iter().all(|(p, _, _)| {
2151 match p.kind().skip_binder() {
2152 // Hide traits if they are present in predicates as they can be fixed without
2153 // having to implement them.
2154 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2155 ty::PredicateKind::Projection(p) => {
2156 p.projection_ty.item_def_id == info.def_id
2160 }) && (type_is_local || info.def_id.is_local())
2162 .associated_value(info.def_id, item_name)
2164 if let ty::AssocKind::Fn = item.kind {
2168 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2169 if let Some(hir::Node::TraitItem(hir::TraitItem {
2170 kind: hir::TraitItemKind::Fn(fn_sig, method),
2172 })) = id.map(|id| self.tcx.hir().get(id))
2174 let self_first_arg = match method {
2175 hir::TraitFn::Required([ident, ..]) => {
2176 ident.name == kw::SelfLower
2178 hir::TraitFn::Provided(body_id) => {
2179 self.tcx.hir().body(*body_id).params.first().map_or(
2184 hir::PatKind::Binding(_, _, ident, _)
2185 if ident.name == kw::SelfLower
2193 if !fn_sig.decl.implicit_self.has_implicit_self()
2196 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2197 arbitrary_rcvr.push(ty.span);
2203 // We only want to suggest public or local traits (#45781).
2204 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2208 .collect::<Vec<_>>();
2209 for span in &arbitrary_rcvr {
2212 "the method might not be found because of this arbitrary self type",
2219 if !candidates.is_empty() {
2220 // Sort from most relevant to least relevant.
2221 candidates.sort_by(|a, b| a.cmp(b).reverse());
2224 let param_type = match rcvr_ty.kind() {
2225 ty::Param(param) => Some(param),
2226 ty::Ref(_, ty, _) => match ty.kind() {
2227 ty::Param(param) => Some(param),
2232 err.help(if param_type.is_some() {
2233 "items from traits can only be used if the type parameter is bounded by the trait"
2235 "items from traits can only be used if the trait is implemented and in scope"
2237 let candidates_len = candidates.len();
2238 let message = |action| {
2240 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2243 if candidates_len == 1 { "trait defines" } else { "traits define" },
2245 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2249 // Obtain the span for `param` and use it for a structured suggestion.
2250 if let Some(param) = param_type {
2251 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2252 let type_param = generics.type_param(param, self.tcx);
2253 let hir = self.tcx.hir();
2254 if let Some(def_id) = type_param.def_id.as_local() {
2255 let id = hir.local_def_id_to_hir_id(def_id);
2256 // Get the `hir::Param` to verify whether it already has any bounds.
2257 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2258 // instead we suggest `T: Foo + Bar` in that case.
2260 Node::GenericParam(param) => {
2266 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2267 let (sp, mut introducer) = if let Some(span) =
2268 ast_generics.bounds_span_for_suggestions(def_id)
2270 (span, Introducer::Plus)
2271 } else if let Some(colon_span) = param.colon_span {
2272 (colon_span.shrink_to_hi(), Introducer::Nothing)
2274 (param.span.shrink_to_hi(), Introducer::Colon)
2278 hir::GenericParamKind::Type { synthetic: true, .. },
2280 introducer = Introducer::Plus
2282 let trait_def_ids: FxHashSet<DefId> = ast_generics
2283 .bounds_for_param(def_id)
2284 .flat_map(|bp| bp.bounds.iter())
2285 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2287 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2288 err.span_suggestions(
2291 "restrict type parameter `{}` with",
2294 candidates.iter().map(|t| {
2298 Introducer::Plus => " +",
2299 Introducer::Colon => ":",
2300 Introducer::Nothing => "",
2302 self.tcx.def_path_str(t.def_id),
2305 Applicability::MaybeIncorrect,
2310 Node::Item(hir::Item {
2311 kind: hir::ItemKind::Trait(.., bounds, _),
2315 let (sp, sep, article) = if bounds.is_empty() {
2316 (ident.span.shrink_to_hi(), ":", "a")
2318 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2320 err.span_suggestions(
2322 &message(format!("add {} supertrait for", article)),
2323 candidates.iter().map(|t| {
2324 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2326 Applicability::MaybeIncorrect,
2335 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2336 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2337 // cases where a positive bound implies a negative impl.
2338 (candidates, Vec::new())
2339 } else if let Some(simp_rcvr_ty) =
2340 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2342 let mut potential_candidates = Vec::new();
2343 let mut explicitly_negative = Vec::new();
2344 for candidate in candidates {
2345 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2348 .all_impls(candidate.def_id)
2350 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2353 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2355 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2356 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2359 explicitly_negative.push(candidate);
2361 potential_candidates.push(candidate);
2364 (potential_candidates, explicitly_negative)
2366 // We don't know enough about `recv_ty` to make proper suggestions.
2367 (candidates, Vec::new())
2370 let action = if let Some(param) = param_type {
2371 format!("restrict type parameter `{}` with", param)
2373 // FIXME: it might only need to be imported into scope, not implemented.
2374 "implement".to_string()
2376 match &potential_candidates[..] {
2378 [trait_info] if trait_info.def_id.is_local() => {
2380 self.tcx.def_span(trait_info.def_id),
2382 "`{}` defines an item `{}`, perhaps you need to {} it",
2383 self.tcx.def_path_str(trait_info.def_id),
2390 let mut msg = message(action);
2391 for (i, trait_info) in trait_infos.iter().enumerate() {
2392 msg.push_str(&format!(
2393 "\ncandidate #{}: `{}`",
2395 self.tcx.def_path_str(trait_info.def_id),
2401 match &explicitly_negative[..] {
2405 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2406 self.tcx.def_path_str(trait_info.def_id),
2412 let mut msg = format!(
2413 "the following traits define an item `{}`, but are explicitly unimplemented:",
2416 for trait_info in trait_infos {
2417 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2425 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2426 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2427 pub(crate) fn suggest_else_fn_with_closure(
2429 err: &mut Diagnostic,
2430 expr: &hir::Expr<'_>,
2434 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2435 else { return false; };
2437 if !self.can_coerce(output, expected) {
2441 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2442 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2443 let hir::ExprKind::MethodCall(
2444 hir::PathSegment { ident: method_name, .. },
2448 ) = call_expr.kind &&
2449 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2450 let new_name = Ident {
2451 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2452 span: method_name.span,
2454 let probe = self.lookup_probe(
2459 ProbeScope::TraitsInScope,
2462 // check the method arguments number
2463 if let Ok(pick) = probe &&
2464 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2465 let fn_args = fn_sig.skip_binder().inputs() &&
2466 fn_args.len() == args.len() + 1 {
2467 err.span_suggestion_verbose(
2468 method_name.span.shrink_to_hi(),
2469 &format!("try calling `{}` instead", new_name.name.as_str()),
2471 Applicability::MaybeIncorrect,
2479 /// Checks whether there is a local type somewhere in the chain of
2480 /// autoderefs of `rcvr_ty`.
2481 fn type_derefs_to_local(
2485 source: SelfSource<'tcx>,
2487 fn is_local(ty: Ty<'_>) -> bool {
2489 ty::Adt(def, _) => def.did().is_local(),
2490 ty::Foreign(did) => did.is_local(),
2491 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2492 ty::Param(_) => true,
2494 // Everything else (primitive types, etc.) is effectively
2495 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2496 // the noise from these sort of types is usually just really
2497 // annoying, rather than any sort of help).
2502 // This occurs for UFCS desugaring of `T::method`, where there is no
2503 // receiver expression for the method call, and thus no autoderef.
2504 if let SelfSource::QPath(_) = source {
2505 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2508 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2512 #[derive(Copy, Clone, Debug)]
2513 pub enum SelfSource<'a> {
2514 QPath(&'a hir::Ty<'a>),
2515 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2518 #[derive(Copy, Clone)]
2519 pub struct TraitInfo {
2523 impl PartialEq for TraitInfo {
2524 fn eq(&self, other: &TraitInfo) -> bool {
2525 self.cmp(other) == Ordering::Equal
2528 impl Eq for TraitInfo {}
2529 impl PartialOrd for TraitInfo {
2530 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2531 Some(self.cmp(other))
2534 impl Ord for TraitInfo {
2535 fn cmp(&self, other: &TraitInfo) -> Ordering {
2536 // Local crates are more important than remote ones (local:
2537 // `cnum == 0`), and otherwise we throw in the defid for totality.
2539 let lhs = (other.def_id.krate, other.def_id);
2540 let rhs = (self.def_id.krate, self.def_id);
2545 /// Retrieves all traits in this crate and any dependent crates,
2546 /// and wraps them into `TraitInfo` for custom sorting.
2547 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2548 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2551 fn print_disambiguation_help<'tcx>(
2553 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2554 err: &mut Diagnostic,
2557 kind: ty::AssocKind,
2560 candidate: Option<usize>,
2561 source_map: &source_map::SourceMap,
2562 fn_has_self_parameter: bool,
2564 let mut applicability = Applicability::MachineApplicable;
2565 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2568 if rcvr_ty.is_region_ptr() {
2569 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2573 std::iter::once(receiver)
2575 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2576 applicability = Applicability::HasPlaceholders;
2579 .collect::<Vec<_>>()
2582 let trait_name = if !fn_has_self_parameter {
2583 format!("<{} as {}>", rcvr_ty, trait_name)
2587 (span, format!("{}::{}{}", trait_name, item_name, args))
2589 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2591 err.span_suggestion_verbose(
2594 "disambiguate the {} for {}",
2595 kind.as_def_kind().descr(def_id),
2596 if let Some(candidate) = candidate {
2597 format!("candidate #{}", candidate)
2599 "the candidate".to_string()