1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
4 use crate::check::FnCtxt;
5 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
11 use rustc_hir::def::DefKind;
12 use rustc_hir::def_id::DefId;
13 use rustc_hir::lang_items::LangItem;
14 use rustc_hir::{ExprKind, Node, QPath};
15 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
16 use rustc_middle::traits::util::supertraits;
17 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
18 use rustc_middle::ty::print::with_crate_prefix;
19 use rustc_middle::ty::ToPolyTraitRef;
20 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
21 use rustc_span::symbol::{kw, sym, Ident};
22 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
23 use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
24 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
25 use rustc_trait_selection::traits::{
26 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
29 use std::cmp::Ordering;
32 use super::probe::{Mode, ProbeScope};
33 use super::{super::suggest_call_constructor, CandidateSource, MethodError, NoMatchData};
35 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
39 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
40 // so we look for these beforehand.
41 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
42 // If it's not a simple function, look for things which implement `FnOnce`.
44 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
48 // This conditional prevents us from asking to call errors and unresolved types.
49 // It might seem that we can use `predicate_must_hold_modulo_regions`,
50 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
51 // type resolution always gives a "maybe" here.
52 if self.autoderef(span, ty).any(|(ty, _)| {
53 info!("check deref {:?} error", ty);
54 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
59 self.autoderef(span, ty).any(|(ty, _)| {
60 info!("check deref {:?} impl FnOnce", ty);
62 let fn_once_substs = tcx.mk_substs_trait(
65 .next_ty_var(TypeVariableOrigin {
66 kind: TypeVariableOriginKind::MiscVariable,
71 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
72 let poly_trait_ref = ty::Binder::dummy(trait_ref);
73 let obligation = Obligation::misc(
77 poly_trait_ref.without_const().to_predicate(tcx),
79 self.predicate_may_hold(&obligation)
86 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
87 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
90 pub fn report_method_error(
95 source: SelfSource<'tcx>,
96 error: MethodError<'tcx>,
97 args: Option<&'tcx [hir::Expr<'tcx>]>,
98 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
99 // Avoid suggestions when we don't know what's going on.
100 if rcvr_ty.references_error() {
104 let report_candidates = |span: Span,
105 err: &mut Diagnostic,
106 mut sources: Vec<CandidateSource>,
110 // Dynamic limit to avoid hiding just one candidate, which is silly.
111 let limit = if sources.len() == 5 { 5 } else { 4 };
113 for (idx, source) in sources.iter().take(limit).enumerate() {
115 CandidateSource::Impl(impl_did) => {
116 // Provide the best span we can. Use the item, if local to crate, else
117 // the impl, if local to crate (item may be defaulted), else nothing.
118 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
119 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
120 self.associated_value(impl_trait_ref.def_id, item_name)
127 .span_if_local(item.def_id)
128 .or_else(|| self.tcx.hir().span_if_local(impl_did));
130 let impl_ty = self.tcx.at(span).type_of(impl_did);
132 let insertion = match self.tcx.impl_trait_ref(impl_did) {
133 None => String::new(),
134 Some(trait_ref) => format!(
135 " of the trait `{}`",
136 self.tcx.def_path_str(trait_ref.def_id)
140 let (note_str, idx) = if sources.len() > 1 {
143 "candidate #{} is defined in an impl{} for the type `{}`",
153 "the candidate is defined in an impl{} for the type `{}`",
159 if let Some(note_span) = note_span {
160 // We have a span pointing to the method. Show note with snippet.
162 self.tcx.sess.source_map().guess_head_span(note_span),
168 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
169 let path = self.tcx.def_path_str(trait_ref.def_id);
171 let ty = match item.kind {
172 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
173 ty::AssocKind::Fn => self
179 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
183 print_disambiguation_help(
193 self.tcx.sess.source_map(),
194 item.fn_has_self_parameter,
198 CandidateSource::Trait(trait_did) => {
199 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
204 .guess_head_span(self.tcx.def_span(item.def_id));
205 let idx = if sources.len() > 1 {
207 "candidate #{} is defined in the trait `{}`",
209 self.tcx.def_path_str(trait_did)
211 err.span_note(item_span, msg);
215 "the candidate is defined in the trait `{}`",
216 self.tcx.def_path_str(trait_did)
218 err.span_note(item_span, msg);
221 let path = self.tcx.def_path_str(trait_did);
222 print_disambiguation_help(
232 self.tcx.sess.source_map(),
233 item.fn_has_self_parameter,
238 if sources.len() > limit {
239 err.note(&format!("and {} others", sources.len() - limit));
243 let sugg_span = if let SelfSource::MethodCall(expr) = source {
244 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
245 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
251 MethodError::NoMatch(NoMatchData {
252 static_candidates: static_sources,
253 unsatisfied_predicates,
260 let actual = self.resolve_vars_if_possible(rcvr_ty);
261 let ty_str = self.ty_to_string(actual);
262 let is_method = mode == Mode::MethodCall;
263 let item_kind = if is_method {
265 } else if actual.is_enum() {
266 "variant or associated item"
268 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
269 (Some(name), false) if name.is_lowercase() => "function or associated item",
270 (Some(_), false) => "associated item",
271 (Some(_), true) | (None, false) => "variant or associated item",
272 (None, true) => "variant",
276 if self.suggest_constraining_numerical_ty(
277 tcx, actual, source, span, item_kind, item_name, &ty_str,
282 span = item_name.span;
284 // Don't show generic arguments when the method can't be found in any implementation (#81576).
285 let mut ty_str_reported = ty_str.clone();
286 if let ty::Adt(_, generics) = actual.kind() {
287 if generics.len() > 0 {
288 let mut autoderef = self.autoderef(span, actual);
289 let candidate_found = autoderef.any(|(ty, _)| {
290 if let ty::Adt(adt_deref, _) = ty.kind() {
292 .inherent_impls(adt_deref.did())
294 .filter_map(|def_id| self.associated_value(*def_id, item_name))
301 let has_deref = autoderef.step_count() > 0;
302 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
303 if let Some((path_string, _)) = ty_str.split_once('<') {
304 ty_str_reported = path_string.to_string();
310 let mut err = struct_span_err!(
314 "no {} named `{}` found for {} `{}` in the current scope",
317 actual.prefix_string(self.tcx),
320 if actual.references_error() {
321 err.downgrade_to_delayed_bug();
324 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
325 self.suggest_await_before_method(
326 &mut err, item_name, actual, cal, span,
329 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
332 "you are looking for the module in `std`, not the primitive type",
334 Applicability::MachineApplicable,
337 if let ty::RawPtr(_) = &actual.kind() {
339 "try using `<*const T>::as_ref()` to get a reference to the \
340 type behind the pointer: https://doc.rust-lang.org/std/\
341 primitive.pointer.html#method.as_ref",
344 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
345 to invalid or uninitialized memory is undefined behavior",
349 let ty_span = match actual.kind() {
350 ty::Param(param_type) => {
351 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
352 let type_param = generics.type_param(param_type, self.tcx);
353 Some(self.tcx.def_span(type_param.def_id))
355 ty::Adt(def, _) if def.did().is_local() => {
356 tcx.def_ident_span(def.did()).map(|span| span)
361 if let Some(span) = ty_span {
365 "{item_kind} `{item_name}` not found for this {}",
366 actual.prefix_string(self.tcx)
371 if self.is_fn_ty(rcvr_ty, span) {
372 if let SelfSource::MethodCall(expr) = source {
373 let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() {
374 if let Some(local_id) = def_id.as_local() {
375 let hir_id = tcx.hir().local_def_id_to_hir_id(local_id);
376 let node = tcx.hir().get(hir_id);
377 let fields = node.tuple_fields();
378 if let Some(fields) = fields
379 && let Some(DefKind::Ctor(of, _)) = self.tcx.opt_def_kind(local_id) {
380 Some((fields.len(), of))
385 // The logic here isn't smart but `associated_item_def_ids`
386 // doesn't work nicely on local.
387 if let DefKind::Ctor(of, _) = tcx.def_kind(def_id) {
388 let parent_def_id = tcx.parent(*def_id);
389 Some((tcx.associated_item_def_ids(parent_def_id).len(), of))
398 // If the function is a tuple constructor, we recommend that they call it
399 if let Some((fields, kind)) = suggest {
400 suggest_call_constructor(expr.span, kind, fields, &mut err);
405 "this is a function, perhaps you wish to call it",
411 let mut custom_span_label = false;
413 if !static_sources.is_empty() {
415 "found the following associated functions; to be used as methods, \
416 functions must have a `self` parameter",
418 err.span_label(span, "this is an associated function, not a method");
419 custom_span_label = true;
421 if static_sources.len() == 1 {
423 if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) {
424 // When the "method" is resolved through dereferencing, we really want the
425 // original type that has the associated function for accurate suggestions.
427 let ty = tcx.at(span).type_of(*impl_did);
428 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
429 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
430 // Use `actual` as it will have more `substs` filled in.
431 self.ty_to_value_string(actual.peel_refs())
433 _ => self.ty_to_value_string(ty.peel_refs()),
436 self.ty_to_value_string(actual.peel_refs())
438 if let SelfSource::MethodCall(expr) = source {
441 "use associated function syntax instead",
442 format!("{}::{}", ty_str, item_name),
443 Applicability::MachineApplicable,
446 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
449 report_candidates(span, &mut err, static_sources, sugg_span);
450 } else if static_sources.len() > 1 {
451 report_candidates(span, &mut err, static_sources, sugg_span);
454 let mut bound_spans = vec![];
455 let mut restrict_type_params = false;
456 let mut unsatisfied_bounds = false;
457 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
458 let msg = "consider using `len` instead";
459 if let SelfSource::MethodCall(_expr) = source {
460 err.span_suggestion_short(
464 Applicability::MachineApplicable,
467 err.span_label(span, msg);
469 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
470 let iterator_trait = self.tcx.def_path_str(iterator_trait);
471 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
473 } else if !unsatisfied_predicates.is_empty() {
474 let def_span = |def_id| {
475 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
477 let mut type_params = FxHashMap::default();
479 // Pick out the list of unimplemented traits on the receiver.
480 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
481 let mut unimplemented_traits = FxHashMap::default();
482 let mut unimplemented_traits_only = true;
483 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
484 if let (ty::PredicateKind::Trait(p), Some(cause)) =
485 (predicate.kind().skip_binder(), cause.as_ref())
487 if p.trait_ref.self_ty() != rcvr_ty {
488 // This is necessary, not just to keep the errors clean, but also
489 // because our derived obligations can wind up with a trait ref that
490 // requires a different param_env to be correctly compared.
493 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
494 predicate.kind().rebind(p.trait_ref),
496 cause: cause.clone(),
497 param_env: self.param_env,
498 predicate: *predicate,
505 // Make sure that, if any traits other than the found ones were involved,
506 // we don't don't report an unimplemented trait.
507 // We don't want to say that `iter::Cloned` is not an iterator, just
508 // because of some non-Clone item being iterated over.
509 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
510 match predicate.kind().skip_binder() {
511 ty::PredicateKind::Trait(p)
512 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
514 unimplemented_traits_only = false;
520 let mut collect_type_param_suggestions =
521 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
522 // We don't care about regions here, so it's fine to skip the binder here.
523 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
524 (self_ty.kind(), parent_pred.kind().skip_binder())
526 let node = match p.trait_ref.self_ty().kind() {
528 // Account for `fn` items like in `issue-35677.rs` to
529 // suggest restricting its type params.
530 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
531 hir_id: self.body_id,
536 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
539 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
542 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
546 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
547 if let Some(g) = kind.generics() {
549 g.tail_span_for_predicate_suggestion(),
550 g.add_where_or_trailing_comma(),
554 .or_insert_with(FxHashSet::default)
555 .insert(obligation.to_owned());
560 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
562 "doesn't satisfy `{}`",
563 if obligation.len() > 50 { quiet } else { obligation }
565 match &self_ty.kind() {
566 // Point at the type that couldn't satisfy the bound.
567 ty::Adt(def, _) => bound_spans.push((def_span(def.did()), msg)),
568 // Point at the trait object that couldn't satisfy the bound.
569 ty::Dynamic(preds, _) => {
570 for pred in preds.iter() {
571 match pred.skip_binder() {
572 ty::ExistentialPredicate::Trait(tr) => {
573 bound_spans.push((def_span(tr.def_id), msg.clone()))
575 ty::ExistentialPredicate::Projection(_)
576 | ty::ExistentialPredicate::AutoTrait(_) => {}
580 // Point at the closure that couldn't satisfy the bound.
581 ty::Closure(def_id, _) => bound_spans
582 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
586 let mut format_pred = |pred: ty::Predicate<'tcx>| {
587 let bound_predicate = pred.kind();
588 match bound_predicate.skip_binder() {
589 ty::PredicateKind::Projection(pred) => {
590 let pred = bound_predicate.rebind(pred);
591 // `<Foo as Iterator>::Item = String`.
592 let projection_ty = pred.skip_binder().projection_ty;
594 let substs_with_infer_self = tcx.mk_substs(
595 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
596 .chain(projection_ty.substs.iter().skip(1)),
599 let quiet_projection_ty = ty::ProjectionTy {
600 substs: substs_with_infer_self,
601 item_def_id: projection_ty.item_def_id,
604 let term = pred.skip_binder().term;
606 let obligation = format!("{} = {}", projection_ty, term);
607 let quiet = format!("{} = {}", quiet_projection_ty, term);
609 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
610 Some((obligation, projection_ty.self_ty()))
612 ty::PredicateKind::Trait(poly_trait_ref) => {
613 let p = poly_trait_ref.trait_ref;
614 let self_ty = p.self_ty();
615 let path = p.print_only_trait_path();
616 let obligation = format!("{}: {}", self_ty, path);
617 let quiet = format!("_: {}", path);
618 bound_span_label(self_ty, &obligation, &quiet);
619 Some((obligation, self_ty))
625 // Find all the requirements that come from a local `impl` block.
626 let mut skip_list: FxHashSet<_> = Default::default();
627 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
628 for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates
630 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
631 .filter_map(|(p, parent, c)| match c.code() {
632 ObligationCauseCode::ImplDerivedObligation(ref data) => {
633 Some((&data.derived, p, parent, data.impl_def_id, data.span))
638 let parent_trait_ref = data.parent_trait_pred;
639 let path = parent_trait_ref.print_modifiers_and_trait_path();
640 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
641 let unsatisfied_msg = "unsatisfied trait bound introduced here";
643 "unsatisfied trait bound introduced in this `derive` macro";
644 match self.tcx.hir().get_if_local(impl_def_id) {
645 // Unmet obligation comes from a `derive` macro, point at it once to
646 // avoid multiple span labels pointing at the same place.
647 Some(Node::Item(hir::Item {
648 kind: hir::ItemKind::Trait(..),
652 ident.span.ctxt().outer_expn_data().kind,
653 ExpnKind::Macro(MacroKind::Derive, _)
656 let span = ident.span.ctxt().outer_expn_data().call_site;
657 let mut spans: MultiSpan = span.into();
658 spans.push_span_label(span, derive_msg);
659 let entry = spanned_predicates.entry(spans);
660 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
663 Some(Node::Item(hir::Item {
664 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
667 self_ty.span.ctxt().outer_expn_data().kind,
668 ExpnKind::Macro(MacroKind::Derive, _)
670 of_trait.as_ref().map(|t| t
676 Some(ExpnKind::Macro(MacroKind::Derive, _))
679 let span = self_ty.span.ctxt().outer_expn_data().call_site;
680 let mut spans: MultiSpan = span.into();
681 spans.push_span_label(span, derive_msg);
682 let entry = spanned_predicates.entry(spans);
683 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
686 // Unmet obligation coming from a `trait`.
687 Some(Node::Item(hir::Item {
688 kind: hir::ItemKind::Trait(..),
693 ident.span.ctxt().outer_expn_data().kind,
694 ExpnKind::Macro(MacroKind::Derive, _)
697 if let Some(pred) = parent_p {
698 // Done to add the "doesn't satisfy" `span_label`.
699 let _ = format_pred(*pred);
702 let mut spans = if cause_span != *item_span {
703 let mut spans: MultiSpan = cause_span.into();
704 spans.push_span_label(cause_span, unsatisfied_msg);
709 spans.push_span_label(ident.span, "in this trait");
710 let entry = spanned_predicates.entry(spans);
711 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
714 // Unmet obligation coming from an `impl`.
715 Some(Node::Item(hir::Item {
716 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
720 self_ty.span.ctxt().outer_expn_data().kind,
721 ExpnKind::Macro(MacroKind::Derive, _)
723 of_trait.as_ref().map(|t| t
729 Some(ExpnKind::Macro(MacroKind::Derive, _))
732 if let Some(pred) = parent_p {
733 // Done to add the "doesn't satisfy" `span_label`.
734 let _ = format_pred(*pred);
737 let mut spans = if cause_span != *item_span {
738 let mut spans: MultiSpan = cause_span.into();
739 spans.push_span_label(cause_span, unsatisfied_msg);
742 let mut spans = Vec::with_capacity(2);
743 if let Some(trait_ref) = of_trait {
744 spans.push(trait_ref.path.span);
746 spans.push(self_ty.span);
749 if let Some(trait_ref) = of_trait {
750 spans.push_span_label(trait_ref.path.span, "");
752 spans.push_span_label(self_ty.span, "");
754 let entry = spanned_predicates.entry(spans);
755 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
760 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
761 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
762 for (span, (_path, _self_ty, preds)) in spanned_predicates {
763 let mut preds: Vec<_> = preds
765 .filter_map(|pred| format_pred(*pred))
766 .map(|(p, _)| format!("`{}`", p))
770 let msg = if let [pred] = &preds[..] {
771 format!("trait bound {} was not satisfied", pred)
774 "the following trait bounds were not satisfied:\n{}",
778 err.span_note(span, &msg);
779 unsatisfied_bounds = true;
782 // The requirements that didn't have an `impl` span to show.
783 let mut bound_list = unsatisfied_predicates
785 .filter_map(|(pred, parent_pred, _cause)| {
786 format_pred(*pred).map(|(p, self_ty)| {
787 collect_type_param_suggestions(self_ty, *pred, &p);
790 None => format!("`{}`", &p),
791 Some(parent_pred) => match format_pred(*parent_pred) {
792 None => format!("`{}`", &p),
793 Some((parent_p, _)) => {
794 collect_type_param_suggestions(
800 "`{}`\nwhich is required by `{}`",
810 .filter(|(_, pred)| !skip_list.contains(&pred))
813 .collect::<Vec<(usize, String)>>();
815 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
816 restrict_type_params = true;
817 // #74886: Sort here so that the output is always the same.
818 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
820 err.span_suggestion_verbose(
823 "consider restricting the type parameter{s} to satisfy the \
825 s = pluralize!(obligations.len())
827 format!("{} {}", add_where_or_comma, obligations.join(", ")),
828 Applicability::MaybeIncorrect,
832 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
833 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
834 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
836 if !bound_list.is_empty() || !skip_list.is_empty() {
837 let bound_list = bound_list
839 .map(|(_, path)| path)
842 let actual_prefix = actual.prefix_string(self.tcx);
843 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
844 let (primary_message, label) = if unimplemented_traits.len() == 1
845 && unimplemented_traits_only
850 .map(|(_, (trait_ref, obligation))| {
851 if trait_ref.self_ty().references_error()
852 || actual.references_error()
857 let OnUnimplementedNote { message, label, .. } =
858 self.infcx.on_unimplemented_note(trait_ref, &obligation);
861 .unwrap_or((None, None))
865 let primary_message = primary_message.unwrap_or_else(|| format!(
866 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
868 err.set_primary_message(&primary_message);
869 if let Some(label) = label {
870 custom_span_label = true;
871 err.span_label(span, label);
873 if !bound_list.is_empty() {
875 "the following trait bounds were not satisfied:\n{bound_list}"
878 self.suggest_derive(&mut err, &unsatisfied_predicates);
880 unsatisfied_bounds = true;
884 let label_span_not_found = |err: &mut DiagnosticBuilder<'_, _>| {
885 if unsatisfied_predicates.is_empty() {
886 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
887 let is_string_or_ref_str = match actual.kind() {
888 ty::Ref(_, ty, _) => {
892 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
895 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
898 if is_string_or_ref_str && item_name.name == sym::iter {
899 err.span_suggestion_verbose(
901 "because of the in-memory representation of `&str`, to obtain \
902 an `Iterator` over each of its codepoint use method `chars`",
904 Applicability::MachineApplicable,
907 if let ty::Adt(adt, _) = rcvr_ty.kind() {
908 let mut inherent_impls_candidate = self
910 .inherent_impls(adt.did())
914 if let Some(assoc) = self.associated_value(*def_id, item_name) {
915 // Check for both mode is the same so we avoid suggesting
916 // incorrect associated item.
917 match (mode, assoc.fn_has_self_parameter, source) {
918 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
919 // We check that the suggest type is actually
920 // different from the received one
921 // So we avoid suggestion method with Box<Self>
923 self.tcx.at(span).type_of(*def_id) != actual
924 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
926 (Mode::Path, false, _) => true,
933 .collect::<Vec<_>>();
934 if !inherent_impls_candidate.is_empty() {
935 inherent_impls_candidate.sort();
936 inherent_impls_candidate.dedup();
938 // number of type to shows at most.
939 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
940 let type_candidates = inherent_impls_candidate
944 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
948 let additional_types = if inherent_impls_candidate.len() > limit {
950 "\nand {} more types",
951 inherent_impls_candidate.len() - limit
957 "the {item_kind} was found for\n{}{}",
958 type_candidates, additional_types
963 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
967 // If the method name is the name of a field with a function or closure type,
968 // give a helping note that it has to be called as `(x.f)(...)`.
969 if let SelfSource::MethodCall(expr) = source {
970 if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err)
971 && lev_candidate.is_none()
972 && !custom_span_label
974 label_span_not_found(&mut err);
976 } else if !custom_span_label {
977 label_span_not_found(&mut err);
980 self.check_for_field_method(&mut err, source, span, actual, item_name);
982 self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
986 for (span, msg) in bound_spans.into_iter() {
987 err.span_label(span, &msg);
990 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
992 self.suggest_traits_to_import(
997 args.map(|args| args.len()),
1000 &unsatisfied_predicates,
1005 // Don't emit a suggestion if we found an actual method
1006 // that had unsatisfied trait bounds
1007 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1008 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1009 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1010 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1014 err.span_suggestion(
1016 "there is a variant with a similar name",
1018 Applicability::MaybeIncorrect,
1023 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1024 let msg = "remove this method call";
1025 let mut fallback_span = true;
1026 if let SelfSource::MethodCall(expr) = source {
1028 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1029 if let Some(span) = call_expr.span.trim_start(expr.span) {
1030 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1031 fallback_span = false;
1035 err.span_label(span, msg);
1037 } else if let Some(lev_candidate) = lev_candidate {
1038 // Don't emit a suggestion if we found an actual method
1039 // that had unsatisfied trait bounds
1040 if unsatisfied_predicates.is_empty() {
1041 let def_kind = lev_candidate.kind.as_def_kind();
1042 err.span_suggestion(
1045 "there is {} {} with a similar name",
1047 def_kind.descr(lev_candidate.def_id),
1050 Applicability::MaybeIncorrect,
1058 MethodError::Ambiguity(sources) => {
1059 let mut err = struct_span_err!(
1063 "multiple applicable items in scope"
1065 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1067 report_candidates(span, &mut err, sources, sugg_span);
1071 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1072 let kind = kind.descr(def_id);
1073 let mut err = struct_span_err!(
1077 "{} `{}` is private",
1081 err.span_label(item_name.span, &format!("private {}", kind));
1085 .span_if_local(def_id)
1086 .unwrap_or_else(|| self.tcx.def_span(def_id));
1087 err.span_label(sp, &format!("private {} defined here", kind));
1088 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1092 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1093 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1094 let mut err = self.sess().struct_span_err(span, &msg);
1095 err.span_label(bound_span, "this has a `Sized` requirement");
1096 if !candidates.is_empty() {
1098 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1099 add a `use` for {one_of_them}:",
1100 an = if candidates.len() == 1 { "an" } else { "" },
1101 s = pluralize!(candidates.len()),
1102 were = if candidates.len() == 1 { "was" } else { "were" },
1103 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1105 self.suggest_use_candidates(&mut err, help, candidates);
1107 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1109 let trait_type = self.tcx.mk_ref(
1111 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1113 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1119 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1124 fn suggest_field_call(
1128 expr: &hir::Expr<'_>,
1130 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1133 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1134 ty::Adt(def, substs) if !def.is_enum() => {
1135 let variant = &def.non_enum_variant();
1136 tcx.find_field_index(item_name, variant).map(|index| {
1137 let field = &variant.fields[index];
1138 let field_ty = field.ty(tcx, substs);
1144 if let Some((field, field_ty)) = field_receiver {
1145 let scope = tcx.parent_module(self.body_id).to_def_id();
1146 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1149 if self.is_fn_ty(field_ty, span) {
1150 let expr_span = expr.span.to(item_name.span);
1151 err.multipart_suggestion(
1153 "to call the function stored in `{}`, \
1154 surround the field access with parentheses",
1158 (expr_span.shrink_to_lo(), '('.to_string()),
1159 (expr_span.shrink_to_hi(), ')'.to_string()),
1161 Applicability::MachineApplicable,
1164 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1166 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1167 err.span_suggestion(
1169 "remove the arguments",
1171 Applicability::MaybeIncorrect,
1177 let field_kind = if is_accessible { "field" } else { "private field" };
1178 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1184 fn suggest_constraining_numerical_ty(
1188 source: SelfSource<'_>,
1194 let found_candidate = all_traits(self.tcx)
1196 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1197 let found_assoc = |ty: Ty<'tcx>| {
1198 simplify_type(tcx, ty, TreatParams::AsInfer)
1200 tcx.incoherent_impls(simp)
1202 .find_map(|&id| self.associated_value(id, item_name))
1206 let found_candidate = found_candidate
1207 || found_assoc(tcx.types.i8)
1208 || found_assoc(tcx.types.i16)
1209 || found_assoc(tcx.types.i32)
1210 || found_assoc(tcx.types.i64)
1211 || found_assoc(tcx.types.i128)
1212 || found_assoc(tcx.types.u8)
1213 || found_assoc(tcx.types.u16)
1214 || found_assoc(tcx.types.u32)
1215 || found_assoc(tcx.types.u64)
1216 || found_assoc(tcx.types.u128)
1217 || found_assoc(tcx.types.f32)
1218 || found_assoc(tcx.types.f32);
1220 && actual.is_numeric()
1221 && !actual.has_concrete_skeleton()
1222 && let SelfSource::MethodCall(expr) = source
1224 let mut err = struct_span_err!(
1228 "can't call {} `{}` on ambiguous numeric type `{}`",
1233 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1235 ExprKind::Lit(ref lit) => {
1240 .span_to_snippet(lit.span)
1241 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1243 // If this is a floating point literal that ends with '.',
1244 // get rid of it to stop this from becoming a member access.
1245 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1247 err.span_suggestion(
1250 "you must specify a concrete type for this numeric value, \
1254 format!("{snippet}_{concrete_type}"),
1255 Applicability::MaybeIncorrect,
1258 ExprKind::Path(QPath::Resolved(_, path)) => {
1260 if let hir::def::Res::Local(hir_id) = path.res {
1261 let span = tcx.hir().span(hir_id);
1262 let snippet = tcx.sess.source_map().span_to_snippet(span);
1263 let filename = tcx.sess.source_map().span_to_filename(span);
1266 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1268 "you must specify a type for this binding, like `{}`",
1272 match (filename, parent_node, snippet) {
1275 Node::Local(hir::Local {
1276 source: hir::LocalSource::Normal,
1282 err.span_suggestion(
1283 // account for `let x: _ = 42;`
1285 span.to(ty.as_ref().map(|ty| ty.span).unwrap_or(span)),
1287 format!("{}: {}", snippet, concrete_type),
1288 Applicability::MaybeIncorrect,
1292 err.span_label(span, msg);
1305 fn check_for_field_method(
1307 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1308 source: SelfSource<'tcx>,
1313 if let SelfSource::MethodCall(expr) = source
1314 && let Some((fields, substs)) = self.get_field_candidates(span, actual)
1316 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1317 for candidate_field in fields.iter() {
1318 if let Some(field_path) = self.check_for_nested_field_satisfying(
1326 ProbeScope::AllTraits,
1333 self.tcx.parent_module(expr.hir_id).to_def_id(),
1335 let field_path_str = field_path
1337 .map(|id| id.name.to_ident_string())
1338 .collect::<Vec<String>>()
1340 debug!("field_path_str: {:?}", field_path_str);
1342 err.span_suggestion_verbose(
1343 item_name.span.shrink_to_lo(),
1344 "one of the expressions' fields has a method of the same name",
1345 format!("{field_path_str}."),
1346 Applicability::MaybeIncorrect,
1353 fn check_for_unwrap_self(
1355 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1356 source: SelfSource<'tcx>,
1362 let SelfSource::MethodCall(expr) = source else { return; };
1363 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1365 let ty::Adt(kind, substs) = actual.kind() else { return; };
1366 if !kind.is_enum() {
1370 let matching_variants: Vec<_> = kind
1373 .flat_map(|variant| {
1374 let [field] = &variant.fields[..] else { return None; };
1375 let field_ty = field.ty(tcx, substs);
1377 // Skip `_`, since that'll just lead to ambiguity.
1378 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1382 self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
1384 .map(|pick| (variant, field, pick))
1388 let ret_ty_matches = |diagnostic_item| {
1389 if let Some(ret_ty) = self
1392 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1393 && let ty::Adt(kind, _) = ret_ty.kind()
1394 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1402 match &matching_variants[..] {
1403 [(_, field, pick)] => {
1404 let self_ty = field.ty(tcx, substs);
1406 tcx.def_span(pick.item.def_id),
1407 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1409 let (article, kind, variant, question) =
1410 if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
1411 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1412 } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
1413 ("an", "Option", "None", ret_ty_matches(sym::Option))
1418 err.span_suggestion_verbose(
1419 expr.span.shrink_to_hi(),
1421 "use the `?` operator to extract the `{self_ty}` value, propagating \
1422 {article} `{kind}::{variant}` value to the caller"
1425 Applicability::MachineApplicable,
1428 err.span_suggestion_verbose(
1429 expr.span.shrink_to_hi(),
1431 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1432 panicking if the value is {article} `{kind}::{variant}`"
1434 ".expect(\"REASON\")",
1435 Applicability::HasPlaceholders,
1439 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1444 pub(crate) fn note_unmet_impls_on_type(
1446 err: &mut Diagnostic,
1447 errors: Vec<FulfillmentError<'tcx>>,
1449 let all_local_types_needing_impls =
1450 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1451 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1452 ty::Adt(def, _) => def.did().is_local(),
1457 let mut preds: Vec<_> = errors
1459 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1460 ty::PredicateKind::Trait(pred) => Some(pred),
1464 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1467 .filter_map(|pred| match pred.self_ty().kind() {
1468 ty::Adt(def, _) => Some(def.did()),
1471 .collect::<FxHashSet<_>>();
1472 let sm = self.tcx.sess.source_map();
1473 let mut spans: MultiSpan = def_ids
1475 .filter_map(|def_id| {
1476 let span = self.tcx.def_span(*def_id);
1477 if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) }
1479 .collect::<Vec<_>>()
1482 for pred in &preds {
1483 match pred.self_ty().kind() {
1484 ty::Adt(def, _) => {
1485 spans.push_span_label(
1486 sm.guess_head_span(self.tcx.def_span(def.did())),
1487 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1494 if all_local_types_needing_impls && spans.primary_span().is_some() {
1495 let msg = if preds.len() == 1 {
1497 "an implementation of `{}` might be missing for `{}`",
1498 preds[0].trait_ref.print_only_trait_path(),
1503 "the following type{} would have to `impl` {} required trait{} for this \
1504 operation to be valid",
1505 pluralize!(def_ids.len()),
1506 if def_ids.len() == 1 { "its" } else { "their" },
1507 pluralize!(preds.len()),
1510 err.span_note(spans, &msg);
1513 let preds: Vec<_> = errors
1515 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1517 self.suggest_derive(err, &preds);
1522 err: &mut Diagnostic,
1523 unsatisfied_predicates: &[(
1524 ty::Predicate<'tcx>,
1525 Option<ty::Predicate<'tcx>>,
1526 Option<ObligationCause<'tcx>>,
1529 let mut derives = Vec::<(String, Span, String)>::new();
1530 let mut traits = Vec::<Span>::new();
1531 for (pred, _, _) in unsatisfied_predicates {
1532 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1533 let adt = match trait_pred.self_ty().ty_adt_def() {
1534 Some(adt) if adt.did().is_local() => adt,
1537 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1538 let can_derive = match diagnostic_name {
1539 sym::Default => !adt.is_enum(),
1547 | sym::Debug => true,
1551 let self_name = trait_pred.self_ty().to_string();
1552 let self_span = self.tcx.def_span(adt.did());
1553 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1554 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1556 if let Some(parent_diagnostic_name) =
1557 self.tcx.get_diagnostic_name(super_trait.def_id())
1562 parent_diagnostic_name.to_string(),
1567 derives.push((self_name, self_span, diagnostic_name.to_string()));
1569 traits.push(self.tcx.def_span(trait_pred.def_id()));
1572 traits.push(self.tcx.def_span(trait_pred.def_id()));
1581 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1582 for (self_name, self_span, trait_name) in derives.into_iter() {
1583 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1585 if last_self_name == &self_name {
1586 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1590 derives_grouped.push((self_name, self_span, trait_name));
1593 let len = traits.len();
1595 let span: MultiSpan = traits.into();
1598 &format!("the following trait{} must be implemented", pluralize!(len),),
1602 for (self_name, self_span, traits) in &derives_grouped {
1603 err.span_suggestion_verbose(
1604 self_span.shrink_to_lo(),
1605 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1606 format!("#[derive({})]\n", traits),
1607 Applicability::MaybeIncorrect,
1612 /// Print out the type for use in value namespace.
1613 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1615 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1616 _ => self.ty_to_string(ty),
1620 fn suggest_await_before_method(
1622 err: &mut Diagnostic,
1625 call: &hir::Expr<'_>,
1628 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
1629 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1632 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1633 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1635 err.span_suggestion_verbose(
1636 span.shrink_to_lo(),
1637 "consider `await`ing on the `Future` and calling the method on its `Output`",
1639 Applicability::MaybeIncorrect,
1644 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1645 let parent_map = self.tcx.visible_parent_map(());
1647 // Separate out candidates that must be imported with a glob, because they are named `_`
1648 // and cannot be referred with their identifier.
1649 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1650 if let Some(parent_did) = parent_map.get(trait_did) {
1651 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1652 if *parent_did != self.tcx.parent(*trait_did)
1655 .module_children(*parent_did)
1657 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1658 .all(|child| child.ident.name == kw::Underscore)
1667 let module_did = self.tcx.parent_module(self.body_id);
1668 let (module, _, _) = self.tcx.hir().get_module(module_did);
1669 let span = module.spans.inject_use_span;
1671 let path_strings = candidates.iter().map(|trait_did| {
1672 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1675 let glob_path_strings = globs.iter().map(|trait_did| {
1676 let parent_did = parent_map.get(trait_did).unwrap();
1678 "use {}::*; // trait {}\n",
1679 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1680 self.tcx.item_name(*trait_did),
1684 err.span_suggestions(
1687 path_strings.chain(glob_path_strings),
1688 Applicability::MaybeIncorrect,
1692 fn suggest_valid_traits(
1694 err: &mut Diagnostic,
1695 valid_out_of_scope_traits: Vec<DefId>,
1697 if !valid_out_of_scope_traits.is_empty() {
1698 let mut candidates = valid_out_of_scope_traits;
1702 // `TryFrom` and `FromIterator` have no methods
1703 let edition_fix = candidates
1705 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1708 err.help("items from traits can only be used if the trait is in scope");
1710 "the following {traits_are} implemented but not in scope; \
1711 perhaps add a `use` for {one_of_them}:",
1712 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1713 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1716 self.suggest_use_candidates(err, msg, candidates);
1717 if let Some(did) = edition_fix {
1719 "'{}' is included in the prelude starting in Edition 2021",
1720 with_crate_prefix!(self.tcx.def_path_str(did))
1730 fn suggest_traits_to_import(
1732 err: &mut Diagnostic,
1736 inputs_len: Option<usize>,
1737 source: SelfSource<'tcx>,
1738 valid_out_of_scope_traits: Vec<DefId>,
1739 unsatisfied_predicates: &[(
1740 ty::Predicate<'tcx>,
1741 Option<ty::Predicate<'tcx>>,
1742 Option<ObligationCause<'tcx>>,
1744 unsatisfied_bounds: bool,
1746 let mut alt_rcvr_sugg = false;
1747 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1748 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1750 self.tcx.lang_items().clone_trait(),
1751 self.tcx.lang_items().deref_trait(),
1752 self.tcx.lang_items().deref_mut_trait(),
1753 self.tcx.lang_items().drop_trait(),
1754 self.tcx.get_diagnostic_item(sym::AsRef),
1756 // Try alternative arbitrary self types that could fulfill this call.
1757 // FIXME: probe for all types that *could* be arbitrary self-types, not
1759 for (rcvr_ty, post) in &[
1761 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1762 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1764 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1766 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1767 // We point at the method, but we just skip the rest of the check for arbitrary
1768 // self types and rely on the suggestion to `use` the trait from
1769 // `suggest_valid_traits`.
1770 let did = Some(pick.item.container.id());
1771 let skip = skippable.contains(&did);
1772 if pick.autoderefs == 0 && !skip {
1774 pick.item.ident(self.tcx).span,
1775 &format!("the method is available for `{}` here", rcvr_ty),
1780 Err(MethodError::Ambiguity(_)) => {
1781 // If the method is defined (but ambiguous) for the receiver we have, it is also
1782 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1783 // the receiver, then it might disambiguate this method, but I think these
1784 // suggestions are generally misleading (see #94218).
1790 for (rcvr_ty, pre) in &[
1791 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1792 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1793 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1794 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1796 if let Some(new_rcvr_t) = *rcvr_ty
1797 && let Ok(pick) = self.lookup_probe(
1802 ProbeScope::AllTraits,
1805 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1806 let did = Some(pick.item.container.id());
1807 // We don't want to suggest a container type when the missing
1808 // method is `.clone()` or `.deref()` otherwise we'd suggest
1809 // `Arc::new(foo).clone()`, which is far from what the user wants.
1810 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1811 // implement the `AsRef` trait.
1812 let skip = skippable.contains(&did)
1813 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
1814 || 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);
1815 // Make sure the method is defined for the *actual* receiver: we don't
1816 // want to treat `Box<Self>` as a receiver if it only works because of
1817 // an autoderef to `&self`
1818 if pick.autoderefs == 0 && !skip {
1820 pick.item.ident(self.tcx).span,
1821 &format!("the method is available for `{}` here", new_rcvr_t),
1823 err.multipart_suggestion(
1824 "consider wrapping the receiver expression with the \
1827 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1828 (rcvr.span.shrink_to_hi(), ")".to_string()),
1830 Applicability::MaybeIncorrect,
1832 // We don't care about the other suggestions.
1833 alt_rcvr_sugg = true;
1839 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1843 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1845 let mut arbitrary_rcvr = vec![];
1846 // There are no traits implemented, so lets suggest some traits to
1847 // implement, by finding ones that have the item name, and are
1848 // legal to implement.
1849 let mut candidates = all_traits(self.tcx)
1851 // Don't issue suggestions for unstable traits since they're
1852 // unlikely to be implementable anyway
1853 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1854 Some(attr) => attr.level.is_stable(),
1858 // We approximate the coherence rules to only suggest
1859 // traits that are legal to implement by requiring that
1860 // either the type or trait is local. Multi-dispatch means
1861 // this isn't perfect (that is, there are cases when
1862 // implementing a trait would be legal but is rejected
1864 unsatisfied_predicates.iter().all(|(p, _, _)| {
1865 match p.kind().skip_binder() {
1866 // Hide traits if they are present in predicates as they can be fixed without
1867 // having to implement them.
1868 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1869 ty::PredicateKind::Projection(p) => {
1870 p.projection_ty.item_def_id == info.def_id
1874 }) && (type_is_local || info.def_id.is_local())
1876 .associated_value(info.def_id, item_name)
1878 if let ty::AssocKind::Fn = item.kind {
1882 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1883 if let Some(hir::Node::TraitItem(hir::TraitItem {
1884 kind: hir::TraitItemKind::Fn(fn_sig, method),
1886 })) = id.map(|id| self.tcx.hir().get(id))
1888 let self_first_arg = match method {
1889 hir::TraitFn::Required([ident, ..]) => {
1890 ident.name == kw::SelfLower
1892 hir::TraitFn::Provided(body_id) => {
1893 self.tcx.hir().body(*body_id).params.first().map_or(
1898 hir::PatKind::Binding(_, _, ident, _)
1899 if ident.name == kw::SelfLower
1907 if !fn_sig.decl.implicit_self.has_implicit_self()
1910 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1911 arbitrary_rcvr.push(ty.span);
1917 // We only want to suggest public or local traits (#45781).
1918 item.vis.is_public() || info.def_id.is_local()
1922 .collect::<Vec<_>>();
1923 for span in &arbitrary_rcvr {
1926 "the method might not be found because of this arbitrary self type",
1933 if !candidates.is_empty() {
1934 // Sort from most relevant to least relevant.
1935 candidates.sort_by(|a, b| a.cmp(b).reverse());
1938 let param_type = match rcvr_ty.kind() {
1939 ty::Param(param) => Some(param),
1940 ty::Ref(_, ty, _) => match ty.kind() {
1941 ty::Param(param) => Some(param),
1946 err.help(if param_type.is_some() {
1947 "items from traits can only be used if the type parameter is bounded by the trait"
1949 "items from traits can only be used if the trait is implemented and in scope"
1951 let candidates_len = candidates.len();
1952 let message = |action| {
1954 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1957 if candidates_len == 1 { "trait defines" } else { "traits define" },
1959 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1963 // Obtain the span for `param` and use it for a structured suggestion.
1964 if let Some(param) = param_type {
1965 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
1966 let type_param = generics.type_param(param, self.tcx);
1967 let hir = self.tcx.hir();
1968 if let Some(def_id) = type_param.def_id.as_local() {
1969 let id = hir.local_def_id_to_hir_id(def_id);
1970 // Get the `hir::Param` to verify whether it already has any bounds.
1971 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1972 // instead we suggest `T: Foo + Bar` in that case.
1974 Node::GenericParam(param) => {
1980 let ast_generics = hir.get_generics(id.owner).unwrap();
1981 let (sp, mut introducer) = if let Some(span) =
1982 ast_generics.bounds_span_for_suggestions(def_id)
1984 (span, Introducer::Plus)
1985 } else if let Some(colon_span) = param.colon_span {
1986 (colon_span.shrink_to_hi(), Introducer::Nothing)
1988 (param.span.shrink_to_hi(), Introducer::Colon)
1992 hir::GenericParamKind::Type { synthetic: true, .. },
1994 introducer = Introducer::Plus
1996 let trait_def_ids: FxHashSet<DefId> = ast_generics
1997 .bounds_for_param(def_id)
1998 .flat_map(|bp| bp.bounds.iter())
1999 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2001 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2002 err.span_suggestions(
2005 "restrict type parameter `{}` with",
2008 candidates.iter().map(|t| {
2012 Introducer::Plus => " +",
2013 Introducer::Colon => ":",
2014 Introducer::Nothing => "",
2016 self.tcx.def_path_str(t.def_id),
2019 Applicability::MaybeIncorrect,
2024 Node::Item(hir::Item {
2025 kind: hir::ItemKind::Trait(.., bounds, _),
2029 let (sp, sep, article) = if bounds.is_empty() {
2030 (ident.span.shrink_to_hi(), ":", "a")
2032 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2034 err.span_suggestions(
2036 &message(format!("add {} supertrait for", article)),
2037 candidates.iter().map(|t| {
2038 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2040 Applicability::MaybeIncorrect,
2049 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2050 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2051 // cases where a positive bound implies a negative impl.
2052 (candidates, Vec::new())
2053 } else if let Some(simp_rcvr_ty) =
2054 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2056 let mut potential_candidates = Vec::new();
2057 let mut explicitly_negative = Vec::new();
2058 for candidate in candidates {
2059 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2062 .all_impls(candidate.def_id)
2064 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2067 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2069 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2070 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2073 explicitly_negative.push(candidate);
2075 potential_candidates.push(candidate);
2078 (potential_candidates, explicitly_negative)
2080 // We don't know enough about `recv_ty` to make proper suggestions.
2081 (candidates, Vec::new())
2084 let action = if let Some(param) = param_type {
2085 format!("restrict type parameter `{}` with", param)
2087 // FIXME: it might only need to be imported into scope, not implemented.
2088 "implement".to_string()
2090 match &potential_candidates[..] {
2092 [trait_info] if trait_info.def_id.is_local() => {
2093 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
2095 self.tcx.sess.source_map().guess_head_span(span),
2097 "`{}` defines an item `{}`, perhaps you need to {} it",
2098 self.tcx.def_path_str(trait_info.def_id),
2105 let mut msg = message(action);
2106 for (i, trait_info) in trait_infos.iter().enumerate() {
2107 msg.push_str(&format!(
2108 "\ncandidate #{}: `{}`",
2110 self.tcx.def_path_str(trait_info.def_id),
2116 match &explicitly_negative[..] {
2120 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2121 self.tcx.def_path_str(trait_info.def_id),
2127 let mut msg = format!(
2128 "the following traits define an item `{}`, but are explicitly unimplemented:",
2131 for trait_info in trait_infos {
2132 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2140 /// Checks whether there is a local type somewhere in the chain of
2141 /// autoderefs of `rcvr_ty`.
2142 fn type_derefs_to_local(
2146 source: SelfSource<'tcx>,
2148 fn is_local(ty: Ty<'_>) -> bool {
2150 ty::Adt(def, _) => def.did().is_local(),
2151 ty::Foreign(did) => did.is_local(),
2152 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2153 ty::Param(_) => true,
2155 // Everything else (primitive types, etc.) is effectively
2156 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2157 // the noise from these sort of types is usually just really
2158 // annoying, rather than any sort of help).
2163 // This occurs for UFCS desugaring of `T::method`, where there is no
2164 // receiver expression for the method call, and thus no autoderef.
2165 if let SelfSource::QPath(_) = source {
2166 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2169 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2173 #[derive(Copy, Clone, Debug)]
2174 pub enum SelfSource<'a> {
2175 QPath(&'a hir::Ty<'a>),
2176 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2179 #[derive(Copy, Clone)]
2180 pub struct TraitInfo {
2184 impl PartialEq for TraitInfo {
2185 fn eq(&self, other: &TraitInfo) -> bool {
2186 self.cmp(other) == Ordering::Equal
2189 impl Eq for TraitInfo {}
2190 impl PartialOrd for TraitInfo {
2191 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2192 Some(self.cmp(other))
2195 impl Ord for TraitInfo {
2196 fn cmp(&self, other: &TraitInfo) -> Ordering {
2197 // Local crates are more important than remote ones (local:
2198 // `cnum == 0`), and otherwise we throw in the defid for totality.
2200 let lhs = (other.def_id.krate, other.def_id);
2201 let rhs = (self.def_id.krate, self.def_id);
2206 /// Retrieves all traits in this crate and any dependent crates,
2207 /// and wraps them into `TraitInfo` for custom sorting.
2208 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2209 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2212 fn print_disambiguation_help<'tcx>(
2214 args: Option<&'tcx [hir::Expr<'tcx>]>,
2215 err: &mut Diagnostic,
2218 kind: ty::AssocKind,
2221 candidate: Option<usize>,
2222 source_map: &source_map::SourceMap,
2223 fn_has_self_parameter: bool,
2225 let mut applicability = Applicability::MachineApplicable;
2226 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
2229 if rcvr_ty.is_region_ptr() {
2230 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2235 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2236 applicability = Applicability::HasPlaceholders;
2239 .collect::<Vec<_>>()
2242 let trait_name = if !fn_has_self_parameter {
2243 format!("<{} as {}>", rcvr_ty, trait_name)
2247 (span, format!("{}::{}{}", trait_name, item_name, args))
2249 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2251 err.span_suggestion_verbose(
2254 "disambiguate the {} for {}",
2255 kind.as_def_kind().descr(def_id),
2256 if let Some(candidate) = candidate {
2257 format!("candidate #{}", candidate)
2259 "the candidate".to_string()