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, TypeVisitable};
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)
125 let note_span = if item.def_id.is_local() {
126 Some(self.tcx.def_span(item.def_id))
127 } else if impl_did.is_local() {
128 Some(self.tcx.def_span(impl_did))
133 let impl_ty = self.tcx.at(span).type_of(impl_did);
135 let insertion = match self.tcx.impl_trait_ref(impl_did) {
136 None => String::new(),
137 Some(trait_ref) => format!(
138 " of the trait `{}`",
139 self.tcx.def_path_str(trait_ref.def_id)
143 let (note_str, idx) = if sources.len() > 1 {
146 "candidate #{} is defined in an impl{} for the type `{}`",
156 "the candidate is defined in an impl{} for the type `{}`",
162 if let Some(note_span) = note_span {
163 // We have a span pointing to the method. Show note with snippet.
164 err.span_note(note_span, ¬e_str);
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 };
200 let item_span = self.tcx.def_span(item.def_id);
201 let idx = if sources.len() > 1 {
203 "candidate #{} is defined in the trait `{}`",
205 self.tcx.def_path_str(trait_did)
207 err.span_note(item_span, msg);
211 "the candidate is defined in the trait `{}`",
212 self.tcx.def_path_str(trait_did)
214 err.span_note(item_span, msg);
217 let path = self.tcx.def_path_str(trait_did);
218 print_disambiguation_help(
228 self.tcx.sess.source_map(),
229 item.fn_has_self_parameter,
234 if sources.len() > limit {
235 err.note(&format!("and {} others", sources.len() - limit));
239 let sugg_span = if let SelfSource::MethodCall(expr) = source {
240 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
241 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
247 MethodError::NoMatch(NoMatchData {
248 static_candidates: static_sources,
249 unsatisfied_predicates,
256 let actual = self.resolve_vars_if_possible(rcvr_ty);
257 let ty_str = self.ty_to_string(actual);
258 let is_method = mode == Mode::MethodCall;
259 let item_kind = if is_method {
261 } else if actual.is_enum() {
262 "variant or associated item"
264 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
265 (Some(name), false) if name.is_lowercase() => "function or associated item",
266 (Some(_), false) => "associated item",
267 (Some(_), true) | (None, false) => "variant or associated item",
268 (None, true) => "variant",
272 if self.suggest_constraining_numerical_ty(
273 tcx, actual, source, span, item_kind, item_name, &ty_str,
278 span = item_name.span;
280 // Don't show generic arguments when the method can't be found in any implementation (#81576).
281 let mut ty_str_reported = ty_str.clone();
282 if let ty::Adt(_, generics) = actual.kind() {
283 if generics.len() > 0 {
284 let mut autoderef = self.autoderef(span, actual);
285 let candidate_found = autoderef.any(|(ty, _)| {
286 if let ty::Adt(adt_deref, _) = ty.kind() {
288 .inherent_impls(adt_deref.did())
290 .filter_map(|def_id| self.associated_value(*def_id, item_name))
297 let has_deref = autoderef.step_count() > 0;
298 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
299 if let Some((path_string, _)) = ty_str.split_once('<') {
300 ty_str_reported = path_string.to_string();
306 let mut err = struct_span_err!(
310 "no {} named `{}` found for {} `{}` in the current scope",
313 actual.prefix_string(self.tcx),
316 if actual.references_error() {
317 err.downgrade_to_delayed_bug();
320 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
321 self.suggest_await_before_method(
322 &mut err, item_name, actual, cal, span,
325 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
328 "you are looking for the module in `std`, not the primitive type",
330 Applicability::MachineApplicable,
333 if let ty::RawPtr(_) = &actual.kind() {
335 "try using `<*const T>::as_ref()` to get a reference to the \
336 type behind the pointer: https://doc.rust-lang.org/std/\
337 primitive.pointer.html#method.as_ref",
340 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
341 to invalid or uninitialized memory is undefined behavior",
345 let ty_span = match actual.kind() {
346 ty::Param(param_type) => {
347 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
348 let type_param = generics.type_param(param_type, self.tcx);
349 Some(self.tcx.def_span(type_param.def_id))
351 ty::Adt(def, _) if def.did().is_local() => {
352 tcx.def_ident_span(def.did()).map(|span| span)
357 if let Some(span) = ty_span {
361 "{item_kind} `{item_name}` not found for this {}",
362 actual.prefix_string(self.tcx)
367 if self.is_fn_ty(rcvr_ty, span) {
368 if let SelfSource::MethodCall(expr) = source {
369 let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() {
370 if let Some(local_id) = def_id.as_local() {
371 let hir_id = tcx.hir().local_def_id_to_hir_id(local_id);
372 let node = tcx.hir().get(hir_id);
373 let fields = node.tuple_fields();
374 if let Some(fields) = fields
375 && let Some(DefKind::Ctor(of, _)) = self.tcx.opt_def_kind(local_id) {
376 Some((fields.len(), of))
381 // The logic here isn't smart but `associated_item_def_ids`
382 // doesn't work nicely on local.
383 if let DefKind::Ctor(of, _) = tcx.def_kind(def_id) {
384 let parent_def_id = tcx.parent(*def_id);
385 Some((tcx.associated_item_def_ids(parent_def_id).len(), of))
394 // If the function is a tuple constructor, we recommend that they call it
395 if let Some((fields, kind)) = suggest {
396 suggest_call_constructor(expr.span, kind, fields, &mut err);
401 "this is a function, perhaps you wish to call it",
407 let mut custom_span_label = false;
409 if !static_sources.is_empty() {
411 "found the following associated functions; to be used as methods, \
412 functions must have a `self` parameter",
414 err.span_label(span, "this is an associated function, not a method");
415 custom_span_label = true;
417 if static_sources.len() == 1 {
419 if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) {
420 // When the "method" is resolved through dereferencing, we really want the
421 // original type that has the associated function for accurate suggestions.
423 let ty = tcx.at(span).type_of(*impl_did);
424 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
425 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
426 // Use `actual` as it will have more `substs` filled in.
427 self.ty_to_value_string(actual.peel_refs())
429 _ => self.ty_to_value_string(ty.peel_refs()),
432 self.ty_to_value_string(actual.peel_refs())
434 if let SelfSource::MethodCall(expr) = source {
437 "use associated function syntax instead",
438 format!("{}::{}", ty_str, item_name),
439 Applicability::MachineApplicable,
442 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
445 report_candidates(span, &mut err, static_sources, sugg_span);
446 } else if static_sources.len() > 1 {
447 report_candidates(span, &mut err, static_sources, sugg_span);
450 let mut bound_spans = vec![];
451 let mut restrict_type_params = false;
452 let mut unsatisfied_bounds = false;
453 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
454 let msg = "consider using `len` instead";
455 if let SelfSource::MethodCall(_expr) = source {
456 err.span_suggestion_short(
460 Applicability::MachineApplicable,
463 err.span_label(span, msg);
465 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
466 let iterator_trait = self.tcx.def_path_str(iterator_trait);
467 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
469 } else if !unsatisfied_predicates.is_empty() {
470 let mut type_params = FxHashMap::default();
472 // Pick out the list of unimplemented traits on the receiver.
473 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
474 let mut unimplemented_traits = FxHashMap::default();
475 let mut unimplemented_traits_only = true;
476 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
477 if let (ty::PredicateKind::Trait(p), Some(cause)) =
478 (predicate.kind().skip_binder(), cause.as_ref())
480 if p.trait_ref.self_ty() != rcvr_ty {
481 // This is necessary, not just to keep the errors clean, but also
482 // because our derived obligations can wind up with a trait ref that
483 // requires a different param_env to be correctly compared.
486 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
487 predicate.kind().rebind(p.trait_ref),
489 cause: cause.clone(),
490 param_env: self.param_env,
491 predicate: *predicate,
498 // Make sure that, if any traits other than the found ones were involved,
499 // we don't don't report an unimplemented trait.
500 // We don't want to say that `iter::Cloned` is not an iterator, just
501 // because of some non-Clone item being iterated over.
502 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
503 match predicate.kind().skip_binder() {
504 ty::PredicateKind::Trait(p)
505 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
507 unimplemented_traits_only = false;
513 let mut collect_type_param_suggestions =
514 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
515 // We don't care about regions here, so it's fine to skip the binder here.
516 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
517 (self_ty.kind(), parent_pred.kind().skip_binder())
519 let node = match p.trait_ref.self_ty().kind() {
521 // Account for `fn` items like in `issue-35677.rs` to
522 // suggest restricting its type params.
523 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
524 hir_id: self.body_id,
529 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
532 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
535 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
539 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
540 if let Some(g) = kind.generics() {
542 g.tail_span_for_predicate_suggestion(),
543 g.add_where_or_trailing_comma(),
547 .or_insert_with(FxHashSet::default)
548 .insert(obligation.to_owned());
553 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
555 "doesn't satisfy `{}`",
556 if obligation.len() > 50 { quiet } else { obligation }
558 match &self_ty.kind() {
559 // Point at the type that couldn't satisfy the bound.
561 bound_spans.push((self.tcx.def_span(def.did()), msg))
563 // Point at the trait object that couldn't satisfy the bound.
564 ty::Dynamic(preds, _) => {
565 for pred in preds.iter() {
566 match pred.skip_binder() {
567 ty::ExistentialPredicate::Trait(tr) => bound_spans
568 .push((self.tcx.def_span(tr.def_id), msg.clone())),
569 ty::ExistentialPredicate::Projection(_)
570 | ty::ExistentialPredicate::AutoTrait(_) => {}
574 // Point at the closure that couldn't satisfy the bound.
575 ty::Closure(def_id, _) => bound_spans.push((
576 tcx.def_span(*def_id),
577 format!("doesn't satisfy `{}`", quiet),
582 let mut format_pred = |pred: ty::Predicate<'tcx>| {
583 let bound_predicate = pred.kind();
584 match bound_predicate.skip_binder() {
585 ty::PredicateKind::Projection(pred) => {
586 let pred = bound_predicate.rebind(pred);
587 // `<Foo as Iterator>::Item = String`.
588 let projection_ty = pred.skip_binder().projection_ty;
590 let substs_with_infer_self = tcx.mk_substs(
591 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
592 .chain(projection_ty.substs.iter().skip(1)),
595 let quiet_projection_ty = ty::ProjectionTy {
596 substs: substs_with_infer_self,
597 item_def_id: projection_ty.item_def_id,
600 let term = pred.skip_binder().term;
602 let obligation = format!("{} = {}", projection_ty, term);
603 let quiet = format!("{} = {}", quiet_projection_ty, term);
605 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
606 Some((obligation, projection_ty.self_ty()))
608 ty::PredicateKind::Trait(poly_trait_ref) => {
609 let p = poly_trait_ref.trait_ref;
610 let self_ty = p.self_ty();
611 let path = p.print_only_trait_path();
612 let obligation = format!("{}: {}", self_ty, path);
613 let quiet = format!("_: {}", path);
614 bound_span_label(self_ty, &obligation, &quiet);
615 Some((obligation, self_ty))
621 // Find all the requirements that come from a local `impl` block.
622 let mut skip_list: FxHashSet<_> = Default::default();
623 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
624 for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates
626 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
627 .filter_map(|(p, parent, c)| match c.code() {
628 ObligationCauseCode::ImplDerivedObligation(ref data) => {
629 Some((&data.derived, p, parent, data.impl_def_id, data.span))
634 let parent_trait_ref = data.parent_trait_pred;
635 let path = parent_trait_ref.print_modifiers_and_trait_path();
636 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
637 let unsatisfied_msg = "unsatisfied trait bound introduced here";
639 "unsatisfied trait bound introduced in this `derive` macro";
640 match self.tcx.hir().get_if_local(impl_def_id) {
641 // Unmet obligation comes from a `derive` macro, point at it once to
642 // avoid multiple span labels pointing at the same place.
643 Some(Node::Item(hir::Item {
644 kind: hir::ItemKind::Trait(..),
648 ident.span.ctxt().outer_expn_data().kind,
649 ExpnKind::Macro(MacroKind::Derive, _)
652 let span = ident.span.ctxt().outer_expn_data().call_site;
653 let mut spans: MultiSpan = span.into();
654 spans.push_span_label(span, derive_msg);
655 let entry = spanned_predicates.entry(spans);
656 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
659 Some(Node::Item(hir::Item {
660 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
663 self_ty.span.ctxt().outer_expn_data().kind,
664 ExpnKind::Macro(MacroKind::Derive, _)
666 of_trait.as_ref().map(|t| t
672 Some(ExpnKind::Macro(MacroKind::Derive, _))
675 let span = self_ty.span.ctxt().outer_expn_data().call_site;
676 let mut spans: MultiSpan = span.into();
677 spans.push_span_label(span, derive_msg);
678 let entry = spanned_predicates.entry(spans);
679 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
682 // Unmet obligation coming from a `trait`.
683 Some(Node::Item(hir::Item {
684 kind: hir::ItemKind::Trait(..),
689 ident.span.ctxt().outer_expn_data().kind,
690 ExpnKind::Macro(MacroKind::Derive, _)
693 if let Some(pred) = parent_p {
694 // Done to add the "doesn't satisfy" `span_label`.
695 let _ = format_pred(*pred);
698 let mut spans = if cause_span != *item_span {
699 let mut spans: MultiSpan = cause_span.into();
700 spans.push_span_label(cause_span, unsatisfied_msg);
705 spans.push_span_label(ident.span, "in this trait");
706 let entry = spanned_predicates.entry(spans);
707 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
710 // Unmet obligation coming from an `impl`.
711 Some(Node::Item(hir::Item {
712 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
716 self_ty.span.ctxt().outer_expn_data().kind,
717 ExpnKind::Macro(MacroKind::Derive, _)
719 of_trait.as_ref().map(|t| t
725 Some(ExpnKind::Macro(MacroKind::Derive, _))
728 if let Some(pred) = parent_p {
729 // Done to add the "doesn't satisfy" `span_label`.
730 let _ = format_pred(*pred);
733 let mut spans = if cause_span != *item_span {
734 let mut spans: MultiSpan = cause_span.into();
735 spans.push_span_label(cause_span, unsatisfied_msg);
738 let mut spans = Vec::with_capacity(2);
739 if let Some(trait_ref) = of_trait {
740 spans.push(trait_ref.path.span);
742 spans.push(self_ty.span);
745 if let Some(trait_ref) = of_trait {
746 spans.push_span_label(trait_ref.path.span, "");
748 spans.push_span_label(self_ty.span, "");
750 let entry = spanned_predicates.entry(spans);
751 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
756 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
757 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
758 for (span, (_path, _self_ty, preds)) in spanned_predicates {
759 let mut preds: Vec<_> = preds
761 .filter_map(|pred| format_pred(*pred))
762 .map(|(p, _)| format!("`{}`", p))
766 let msg = if let [pred] = &preds[..] {
767 format!("trait bound {} was not satisfied", pred)
770 "the following trait bounds were not satisfied:\n{}",
774 err.span_note(span, &msg);
775 unsatisfied_bounds = true;
778 // The requirements that didn't have an `impl` span to show.
779 let mut bound_list = unsatisfied_predicates
781 .filter_map(|(pred, parent_pred, _cause)| {
782 format_pred(*pred).map(|(p, self_ty)| {
783 collect_type_param_suggestions(self_ty, *pred, &p);
786 None => format!("`{}`", &p),
787 Some(parent_pred) => match format_pred(*parent_pred) {
788 None => format!("`{}`", &p),
789 Some((parent_p, _)) => {
790 collect_type_param_suggestions(
796 "`{}`\nwhich is required by `{}`",
806 .filter(|(_, pred)| !skip_list.contains(&pred))
809 .collect::<Vec<(usize, String)>>();
811 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
812 restrict_type_params = true;
813 // #74886: Sort here so that the output is always the same.
814 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
816 err.span_suggestion_verbose(
819 "consider restricting the type parameter{s} to satisfy the \
821 s = pluralize!(obligations.len())
823 format!("{} {}", add_where_or_comma, obligations.join(", ")),
824 Applicability::MaybeIncorrect,
828 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
829 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
830 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
832 if !bound_list.is_empty() || !skip_list.is_empty() {
833 let bound_list = bound_list
835 .map(|(_, path)| path)
838 let actual_prefix = actual.prefix_string(self.tcx);
839 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
840 let (primary_message, label) = if unimplemented_traits.len() == 1
841 && unimplemented_traits_only
846 .map(|(_, (trait_ref, obligation))| {
847 if trait_ref.self_ty().references_error()
848 || actual.references_error()
853 let OnUnimplementedNote { message, label, .. } =
854 self.infcx.on_unimplemented_note(trait_ref, &obligation);
857 .unwrap_or((None, None))
861 let primary_message = primary_message.unwrap_or_else(|| format!(
862 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
864 err.set_primary_message(&primary_message);
865 if let Some(label) = label {
866 custom_span_label = true;
867 err.span_label(span, label);
869 if !bound_list.is_empty() {
871 "the following trait bounds were not satisfied:\n{bound_list}"
874 self.suggest_derive(&mut err, &unsatisfied_predicates);
876 unsatisfied_bounds = true;
880 let label_span_not_found = |err: &mut DiagnosticBuilder<'_, _>| {
881 if unsatisfied_predicates.is_empty() {
882 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
883 let is_string_or_ref_str = match actual.kind() {
884 ty::Ref(_, ty, _) => {
888 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
891 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
894 if is_string_or_ref_str && item_name.name == sym::iter {
895 err.span_suggestion_verbose(
897 "because of the in-memory representation of `&str`, to obtain \
898 an `Iterator` over each of its codepoint use method `chars`",
900 Applicability::MachineApplicable,
903 if let ty::Adt(adt, _) = rcvr_ty.kind() {
904 let mut inherent_impls_candidate = self
906 .inherent_impls(adt.did())
910 if let Some(assoc) = self.associated_value(*def_id, item_name) {
911 // Check for both mode is the same so we avoid suggesting
912 // incorrect associated item.
913 match (mode, assoc.fn_has_self_parameter, source) {
914 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
915 // We check that the suggest type is actually
916 // different from the received one
917 // So we avoid suggestion method with Box<Self>
919 self.tcx.at(span).type_of(*def_id) != actual
920 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
922 (Mode::Path, false, _) => true,
929 .collect::<Vec<_>>();
930 if !inherent_impls_candidate.is_empty() {
931 inherent_impls_candidate.sort();
932 inherent_impls_candidate.dedup();
934 // number of type to shows at most.
935 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
936 let type_candidates = inherent_impls_candidate
940 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
944 let additional_types = if inherent_impls_candidate.len() > limit {
946 "\nand {} more types",
947 inherent_impls_candidate.len() - limit
953 "the {item_kind} was found for\n{}{}",
954 type_candidates, additional_types
959 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
963 // If the method name is the name of a field with a function or closure type,
964 // give a helping note that it has to be called as `(x.f)(...)`.
965 if let SelfSource::MethodCall(expr) = source {
966 if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err)
967 && lev_candidate.is_none()
968 && !custom_span_label
970 label_span_not_found(&mut err);
972 } else if !custom_span_label {
973 label_span_not_found(&mut err);
976 self.check_for_field_method(&mut err, source, span, actual, item_name);
978 self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
982 for (span, msg) in bound_spans.into_iter() {
983 err.span_label(span, &msg);
986 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
988 self.suggest_traits_to_import(
993 args.map(|args| args.len()),
996 &unsatisfied_predicates,
1001 // Don't emit a suggestion if we found an actual method
1002 // that had unsatisfied trait bounds
1003 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1004 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1005 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1006 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1010 err.span_suggestion(
1012 "there is a variant with a similar name",
1014 Applicability::MaybeIncorrect,
1019 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1020 let msg = "remove this method call";
1021 let mut fallback_span = true;
1022 if let SelfSource::MethodCall(expr) = source {
1024 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1025 if let Some(span) = call_expr.span.trim_start(expr.span) {
1026 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1027 fallback_span = false;
1031 err.span_label(span, msg);
1033 } else if let Some(lev_candidate) = lev_candidate {
1034 // Don't emit a suggestion if we found an actual method
1035 // that had unsatisfied trait bounds
1036 if unsatisfied_predicates.is_empty() {
1037 let def_kind = lev_candidate.kind.as_def_kind();
1038 err.span_suggestion(
1041 "there is {} {} with a similar name",
1043 def_kind.descr(lev_candidate.def_id),
1046 Applicability::MaybeIncorrect,
1054 MethodError::Ambiguity(sources) => {
1055 let mut err = struct_span_err!(
1059 "multiple applicable items in scope"
1061 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1063 report_candidates(span, &mut err, sources, sugg_span);
1067 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1068 let kind = kind.descr(def_id);
1069 let mut err = struct_span_err!(
1073 "{} `{}` is private",
1077 err.span_label(item_name.span, &format!("private {}", kind));
1081 .span_if_local(def_id)
1082 .unwrap_or_else(|| self.tcx.def_span(def_id));
1083 err.span_label(sp, &format!("private {} defined here", kind));
1084 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1088 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1089 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1090 let mut err = self.sess().struct_span_err(span, &msg);
1091 err.span_label(bound_span, "this has a `Sized` requirement");
1092 if !candidates.is_empty() {
1094 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1095 add a `use` for {one_of_them}:",
1096 an = if candidates.len() == 1 { "an" } else { "" },
1097 s = pluralize!(candidates.len()),
1098 were = if candidates.len() == 1 { "was" } else { "were" },
1099 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1101 self.suggest_use_candidates(&mut err, help, candidates);
1103 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1105 let trait_type = self.tcx.mk_ref(
1107 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1109 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1115 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1120 fn suggest_field_call(
1124 expr: &hir::Expr<'_>,
1126 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1129 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1130 ty::Adt(def, substs) if !def.is_enum() => {
1131 let variant = &def.non_enum_variant();
1132 tcx.find_field_index(item_name, variant).map(|index| {
1133 let field = &variant.fields[index];
1134 let field_ty = field.ty(tcx, substs);
1140 if let Some((field, field_ty)) = field_receiver {
1141 let scope = tcx.parent_module(self.body_id).to_def_id();
1142 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1145 if self.is_fn_ty(field_ty, span) {
1146 let expr_span = expr.span.to(item_name.span);
1147 err.multipart_suggestion(
1149 "to call the function stored in `{}`, \
1150 surround the field access with parentheses",
1154 (expr_span.shrink_to_lo(), '('.to_string()),
1155 (expr_span.shrink_to_hi(), ')'.to_string()),
1157 Applicability::MachineApplicable,
1160 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1162 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1163 err.span_suggestion(
1165 "remove the arguments",
1167 Applicability::MaybeIncorrect,
1173 let field_kind = if is_accessible { "field" } else { "private field" };
1174 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1180 fn suggest_constraining_numerical_ty(
1184 source: SelfSource<'_>,
1190 let found_candidate = all_traits(self.tcx)
1192 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1193 let found_assoc = |ty: Ty<'tcx>| {
1194 simplify_type(tcx, ty, TreatParams::AsInfer)
1196 tcx.incoherent_impls(simp)
1198 .find_map(|&id| self.associated_value(id, item_name))
1202 let found_candidate = found_candidate
1203 || found_assoc(tcx.types.i8)
1204 || found_assoc(tcx.types.i16)
1205 || found_assoc(tcx.types.i32)
1206 || found_assoc(tcx.types.i64)
1207 || found_assoc(tcx.types.i128)
1208 || found_assoc(tcx.types.u8)
1209 || found_assoc(tcx.types.u16)
1210 || found_assoc(tcx.types.u32)
1211 || found_assoc(tcx.types.u64)
1212 || found_assoc(tcx.types.u128)
1213 || found_assoc(tcx.types.f32)
1214 || found_assoc(tcx.types.f32);
1216 && actual.is_numeric()
1217 && !actual.has_concrete_skeleton()
1218 && let SelfSource::MethodCall(expr) = source
1220 let mut err = struct_span_err!(
1224 "can't call {} `{}` on ambiguous numeric type `{}`",
1229 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1231 ExprKind::Lit(ref lit) => {
1236 .span_to_snippet(lit.span)
1237 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1239 // If this is a floating point literal that ends with '.',
1240 // get rid of it to stop this from becoming a member access.
1241 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1243 err.span_suggestion(
1246 "you must specify a concrete type for this numeric value, \
1250 format!("{snippet}_{concrete_type}"),
1251 Applicability::MaybeIncorrect,
1254 ExprKind::Path(QPath::Resolved(_, path)) => {
1256 if let hir::def::Res::Local(hir_id) = path.res {
1257 let span = tcx.hir().span(hir_id);
1258 let snippet = tcx.sess.source_map().span_to_snippet(span);
1259 let filename = tcx.sess.source_map().span_to_filename(span);
1262 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1264 "you must specify a type for this binding, like `{}`",
1268 match (filename, parent_node, snippet) {
1271 Node::Local(hir::Local {
1272 source: hir::LocalSource::Normal,
1278 err.span_suggestion(
1279 // account for `let x: _ = 42;`
1281 span.to(ty.as_ref().map(|ty| ty.span).unwrap_or(span)),
1283 format!("{}: {}", snippet, concrete_type),
1284 Applicability::MaybeIncorrect,
1288 err.span_label(span, msg);
1301 fn check_for_field_method(
1303 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1304 source: SelfSource<'tcx>,
1309 if let SelfSource::MethodCall(expr) = source
1310 && let Some((fields, substs)) = self.get_field_candidates(span, actual)
1312 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1313 for candidate_field in fields.iter() {
1314 if let Some(field_path) = self.check_for_nested_field_satisfying(
1322 ProbeScope::AllTraits,
1329 self.tcx.parent_module(expr.hir_id).to_def_id(),
1331 let field_path_str = field_path
1333 .map(|id| id.name.to_ident_string())
1334 .collect::<Vec<String>>()
1336 debug!("field_path_str: {:?}", field_path_str);
1338 err.span_suggestion_verbose(
1339 item_name.span.shrink_to_lo(),
1340 "one of the expressions' fields has a method of the same name",
1341 format!("{field_path_str}."),
1342 Applicability::MaybeIncorrect,
1349 fn check_for_unwrap_self(
1351 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1352 source: SelfSource<'tcx>,
1358 let SelfSource::MethodCall(expr) = source else { return; };
1359 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1361 let ty::Adt(kind, substs) = actual.kind() else { return; };
1362 if !kind.is_enum() {
1366 let matching_variants: Vec<_> = kind
1369 .flat_map(|variant| {
1370 let [field] = &variant.fields[..] else { return None; };
1371 let field_ty = field.ty(tcx, substs);
1373 // Skip `_`, since that'll just lead to ambiguity.
1374 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1378 self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
1380 .map(|pick| (variant, field, pick))
1384 let ret_ty_matches = |diagnostic_item| {
1385 if let Some(ret_ty) = self
1388 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1389 && let ty::Adt(kind, _) = ret_ty.kind()
1390 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1398 match &matching_variants[..] {
1399 [(_, field, pick)] => {
1400 let self_ty = field.ty(tcx, substs);
1402 tcx.def_span(pick.item.def_id),
1403 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1405 let (article, kind, variant, question) =
1406 if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
1407 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1408 } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
1409 ("an", "Option", "None", ret_ty_matches(sym::Option))
1414 err.span_suggestion_verbose(
1415 expr.span.shrink_to_hi(),
1417 "use the `?` operator to extract the `{self_ty}` value, propagating \
1418 {article} `{kind}::{variant}` value to the caller"
1421 Applicability::MachineApplicable,
1424 err.span_suggestion_verbose(
1425 expr.span.shrink_to_hi(),
1427 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1428 panicking if the value is {article} `{kind}::{variant}`"
1430 ".expect(\"REASON\")",
1431 Applicability::HasPlaceholders,
1435 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1440 pub(crate) fn note_unmet_impls_on_type(
1442 err: &mut Diagnostic,
1443 errors: Vec<FulfillmentError<'tcx>>,
1445 let all_local_types_needing_impls =
1446 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1447 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1448 ty::Adt(def, _) => def.did().is_local(),
1453 let mut preds: Vec<_> = errors
1455 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1456 ty::PredicateKind::Trait(pred) => Some(pred),
1460 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1463 .filter_map(|pred| match pred.self_ty().kind() {
1464 ty::Adt(def, _) => Some(def.did()),
1467 .collect::<FxHashSet<_>>();
1468 let mut spans: MultiSpan = def_ids
1470 .filter_map(|def_id| {
1471 let span = self.tcx.def_span(*def_id);
1472 if span.is_dummy() { None } else { Some(span) }
1474 .collect::<Vec<_>>()
1477 for pred in &preds {
1478 match pred.self_ty().kind() {
1479 ty::Adt(def, _) if def.did().is_local() => {
1480 spans.push_span_label(
1481 self.tcx.def_span(def.did()),
1482 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1489 if all_local_types_needing_impls && spans.primary_span().is_some() {
1490 let msg = if preds.len() == 1 {
1492 "an implementation of `{}` might be missing for `{}`",
1493 preds[0].trait_ref.print_only_trait_path(),
1498 "the following type{} would have to `impl` {} required trait{} for this \
1499 operation to be valid",
1500 pluralize!(def_ids.len()),
1501 if def_ids.len() == 1 { "its" } else { "their" },
1502 pluralize!(preds.len()),
1505 err.span_note(spans, &msg);
1508 let preds: Vec<_> = errors
1510 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1512 self.suggest_derive(err, &preds);
1517 err: &mut Diagnostic,
1518 unsatisfied_predicates: &[(
1519 ty::Predicate<'tcx>,
1520 Option<ty::Predicate<'tcx>>,
1521 Option<ObligationCause<'tcx>>,
1524 let mut derives = Vec::<(String, Span, String)>::new();
1525 let mut traits = Vec::<Span>::new();
1526 for (pred, _, _) in unsatisfied_predicates {
1527 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1528 let adt = match trait_pred.self_ty().ty_adt_def() {
1529 Some(adt) if adt.did().is_local() => adt,
1532 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1533 let can_derive = match diagnostic_name {
1534 sym::Default => !adt.is_enum(),
1542 | sym::Debug => true,
1546 let self_name = trait_pred.self_ty().to_string();
1547 let self_span = self.tcx.def_span(adt.did());
1548 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1549 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1551 if let Some(parent_diagnostic_name) =
1552 self.tcx.get_diagnostic_name(super_trait.def_id())
1557 parent_diagnostic_name.to_string(),
1562 derives.push((self_name, self_span, diagnostic_name.to_string()));
1564 traits.push(self.tcx.def_span(trait_pred.def_id()));
1567 traits.push(self.tcx.def_span(trait_pred.def_id()));
1576 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1577 for (self_name, self_span, trait_name) in derives.into_iter() {
1578 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1580 if last_self_name == &self_name {
1581 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1585 derives_grouped.push((self_name, self_span, trait_name));
1588 let len = traits.len();
1590 let span: MultiSpan = traits.into();
1593 &format!("the following trait{} must be implemented", pluralize!(len),),
1597 for (self_name, self_span, traits) in &derives_grouped {
1598 err.span_suggestion_verbose(
1599 self_span.shrink_to_lo(),
1600 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1601 format!("#[derive({})]\n", traits),
1602 Applicability::MaybeIncorrect,
1607 /// Print out the type for use in value namespace.
1608 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1610 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1611 _ => self.ty_to_string(ty),
1615 fn suggest_await_before_method(
1617 err: &mut Diagnostic,
1620 call: &hir::Expr<'_>,
1623 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
1624 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1627 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1628 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1630 err.span_suggestion_verbose(
1631 span.shrink_to_lo(),
1632 "consider `await`ing on the `Future` and calling the method on its `Output`",
1634 Applicability::MaybeIncorrect,
1639 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1640 let parent_map = self.tcx.visible_parent_map(());
1642 // Separate out candidates that must be imported with a glob, because they are named `_`
1643 // and cannot be referred with their identifier.
1644 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1645 if let Some(parent_did) = parent_map.get(trait_did) {
1646 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1647 if *parent_did != self.tcx.parent(*trait_did)
1650 .module_children(*parent_did)
1652 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1653 .all(|child| child.ident.name == kw::Underscore)
1662 let module_did = self.tcx.parent_module(self.body_id);
1663 let (module, _, _) = self.tcx.hir().get_module(module_did);
1664 let span = module.spans.inject_use_span;
1666 let path_strings = candidates.iter().map(|trait_did| {
1667 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1670 let glob_path_strings = globs.iter().map(|trait_did| {
1671 let parent_did = parent_map.get(trait_did).unwrap();
1673 "use {}::*; // trait {}\n",
1674 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1675 self.tcx.item_name(*trait_did),
1679 err.span_suggestions(
1682 path_strings.chain(glob_path_strings),
1683 Applicability::MaybeIncorrect,
1687 fn suggest_valid_traits(
1689 err: &mut Diagnostic,
1690 valid_out_of_scope_traits: Vec<DefId>,
1692 if !valid_out_of_scope_traits.is_empty() {
1693 let mut candidates = valid_out_of_scope_traits;
1697 // `TryFrom` and `FromIterator` have no methods
1698 let edition_fix = candidates
1700 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1703 err.help("items from traits can only be used if the trait is in scope");
1705 "the following {traits_are} implemented but not in scope; \
1706 perhaps add a `use` for {one_of_them}:",
1707 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1708 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1711 self.suggest_use_candidates(err, msg, candidates);
1712 if let Some(did) = edition_fix {
1714 "'{}' is included in the prelude starting in Edition 2021",
1715 with_crate_prefix!(self.tcx.def_path_str(did))
1725 fn suggest_traits_to_import(
1727 err: &mut Diagnostic,
1731 inputs_len: Option<usize>,
1732 source: SelfSource<'tcx>,
1733 valid_out_of_scope_traits: Vec<DefId>,
1734 unsatisfied_predicates: &[(
1735 ty::Predicate<'tcx>,
1736 Option<ty::Predicate<'tcx>>,
1737 Option<ObligationCause<'tcx>>,
1739 unsatisfied_bounds: bool,
1741 let mut alt_rcvr_sugg = false;
1742 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1743 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1745 self.tcx.lang_items().clone_trait(),
1746 self.tcx.lang_items().deref_trait(),
1747 self.tcx.lang_items().deref_mut_trait(),
1748 self.tcx.lang_items().drop_trait(),
1749 self.tcx.get_diagnostic_item(sym::AsRef),
1751 // Try alternative arbitrary self types that could fulfill this call.
1752 // FIXME: probe for all types that *could* be arbitrary self-types, not
1754 for (rcvr_ty, post) in &[
1756 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1757 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1759 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1761 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1762 // We point at the method, but we just skip the rest of the check for arbitrary
1763 // self types and rely on the suggestion to `use` the trait from
1764 // `suggest_valid_traits`.
1765 let did = Some(pick.item.container.id());
1766 let skip = skippable.contains(&did);
1767 if pick.autoderefs == 0 && !skip {
1769 pick.item.ident(self.tcx).span,
1770 &format!("the method is available for `{}` here", rcvr_ty),
1775 Err(MethodError::Ambiguity(_)) => {
1776 // If the method is defined (but ambiguous) for the receiver we have, it is also
1777 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1778 // the receiver, then it might disambiguate this method, but I think these
1779 // suggestions are generally misleading (see #94218).
1785 for (rcvr_ty, pre) in &[
1786 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1787 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1788 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1789 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1791 if let Some(new_rcvr_t) = *rcvr_ty
1792 && let Ok(pick) = self.lookup_probe(
1797 ProbeScope::AllTraits,
1800 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1801 let did = Some(pick.item.container.id());
1802 // We don't want to suggest a container type when the missing
1803 // method is `.clone()` or `.deref()` otherwise we'd suggest
1804 // `Arc::new(foo).clone()`, which is far from what the user wants.
1805 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1806 // implement the `AsRef` trait.
1807 let skip = skippable.contains(&did)
1808 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
1809 || 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);
1810 // Make sure the method is defined for the *actual* receiver: we don't
1811 // want to treat `Box<Self>` as a receiver if it only works because of
1812 // an autoderef to `&self`
1813 if pick.autoderefs == 0 && !skip {
1815 pick.item.ident(self.tcx).span,
1816 &format!("the method is available for `{}` here", new_rcvr_t),
1818 err.multipart_suggestion(
1819 "consider wrapping the receiver expression with the \
1822 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1823 (rcvr.span.shrink_to_hi(), ")".to_string()),
1825 Applicability::MaybeIncorrect,
1827 // We don't care about the other suggestions.
1828 alt_rcvr_sugg = true;
1834 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1838 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1840 let mut arbitrary_rcvr = vec![];
1841 // There are no traits implemented, so lets suggest some traits to
1842 // implement, by finding ones that have the item name, and are
1843 // legal to implement.
1844 let mut candidates = all_traits(self.tcx)
1846 // Don't issue suggestions for unstable traits since they're
1847 // unlikely to be implementable anyway
1848 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1849 Some(attr) => attr.level.is_stable(),
1853 // We approximate the coherence rules to only suggest
1854 // traits that are legal to implement by requiring that
1855 // either the type or trait is local. Multi-dispatch means
1856 // this isn't perfect (that is, there are cases when
1857 // implementing a trait would be legal but is rejected
1859 unsatisfied_predicates.iter().all(|(p, _, _)| {
1860 match p.kind().skip_binder() {
1861 // Hide traits if they are present in predicates as they can be fixed without
1862 // having to implement them.
1863 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1864 ty::PredicateKind::Projection(p) => {
1865 p.projection_ty.item_def_id == info.def_id
1869 }) && (type_is_local || info.def_id.is_local())
1871 .associated_value(info.def_id, item_name)
1873 if let ty::AssocKind::Fn = item.kind {
1877 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1878 if let Some(hir::Node::TraitItem(hir::TraitItem {
1879 kind: hir::TraitItemKind::Fn(fn_sig, method),
1881 })) = id.map(|id| self.tcx.hir().get(id))
1883 let self_first_arg = match method {
1884 hir::TraitFn::Required([ident, ..]) => {
1885 ident.name == kw::SelfLower
1887 hir::TraitFn::Provided(body_id) => {
1888 self.tcx.hir().body(*body_id).params.first().map_or(
1893 hir::PatKind::Binding(_, _, ident, _)
1894 if ident.name == kw::SelfLower
1902 if !fn_sig.decl.implicit_self.has_implicit_self()
1905 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1906 arbitrary_rcvr.push(ty.span);
1912 // We only want to suggest public or local traits (#45781).
1913 item.vis.is_public() || info.def_id.is_local()
1917 .collect::<Vec<_>>();
1918 for span in &arbitrary_rcvr {
1921 "the method might not be found because of this arbitrary self type",
1928 if !candidates.is_empty() {
1929 // Sort from most relevant to least relevant.
1930 candidates.sort_by(|a, b| a.cmp(b).reverse());
1933 let param_type = match rcvr_ty.kind() {
1934 ty::Param(param) => Some(param),
1935 ty::Ref(_, ty, _) => match ty.kind() {
1936 ty::Param(param) => Some(param),
1941 err.help(if param_type.is_some() {
1942 "items from traits can only be used if the type parameter is bounded by the trait"
1944 "items from traits can only be used if the trait is implemented and in scope"
1946 let candidates_len = candidates.len();
1947 let message = |action| {
1949 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1952 if candidates_len == 1 { "trait defines" } else { "traits define" },
1954 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1958 // Obtain the span for `param` and use it for a structured suggestion.
1959 if let Some(param) = param_type {
1960 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
1961 let type_param = generics.type_param(param, self.tcx);
1962 let hir = self.tcx.hir();
1963 if let Some(def_id) = type_param.def_id.as_local() {
1964 let id = hir.local_def_id_to_hir_id(def_id);
1965 // Get the `hir::Param` to verify whether it already has any bounds.
1966 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1967 // instead we suggest `T: Foo + Bar` in that case.
1969 Node::GenericParam(param) => {
1975 let ast_generics = hir.get_generics(id.owner).unwrap();
1976 let (sp, mut introducer) = if let Some(span) =
1977 ast_generics.bounds_span_for_suggestions(def_id)
1979 (span, Introducer::Plus)
1980 } else if let Some(colon_span) = param.colon_span {
1981 (colon_span.shrink_to_hi(), Introducer::Nothing)
1983 (param.span.shrink_to_hi(), Introducer::Colon)
1987 hir::GenericParamKind::Type { synthetic: true, .. },
1989 introducer = Introducer::Plus
1991 let trait_def_ids: FxHashSet<DefId> = ast_generics
1992 .bounds_for_param(def_id)
1993 .flat_map(|bp| bp.bounds.iter())
1994 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1996 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1997 err.span_suggestions(
2000 "restrict type parameter `{}` with",
2003 candidates.iter().map(|t| {
2007 Introducer::Plus => " +",
2008 Introducer::Colon => ":",
2009 Introducer::Nothing => "",
2011 self.tcx.def_path_str(t.def_id),
2014 Applicability::MaybeIncorrect,
2019 Node::Item(hir::Item {
2020 kind: hir::ItemKind::Trait(.., bounds, _),
2024 let (sp, sep, article) = if bounds.is_empty() {
2025 (ident.span.shrink_to_hi(), ":", "a")
2027 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2029 err.span_suggestions(
2031 &message(format!("add {} supertrait for", article)),
2032 candidates.iter().map(|t| {
2033 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2035 Applicability::MaybeIncorrect,
2044 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2045 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2046 // cases where a positive bound implies a negative impl.
2047 (candidates, Vec::new())
2048 } else if let Some(simp_rcvr_ty) =
2049 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2051 let mut potential_candidates = Vec::new();
2052 let mut explicitly_negative = Vec::new();
2053 for candidate in candidates {
2054 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2057 .all_impls(candidate.def_id)
2059 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2062 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2064 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2065 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2068 explicitly_negative.push(candidate);
2070 potential_candidates.push(candidate);
2073 (potential_candidates, explicitly_negative)
2075 // We don't know enough about `recv_ty` to make proper suggestions.
2076 (candidates, Vec::new())
2079 let action = if let Some(param) = param_type {
2080 format!("restrict type parameter `{}` with", param)
2082 // FIXME: it might only need to be imported into scope, not implemented.
2083 "implement".to_string()
2085 match &potential_candidates[..] {
2087 [trait_info] if trait_info.def_id.is_local() => {
2089 self.tcx.def_span(trait_info.def_id),
2091 "`{}` defines an item `{}`, perhaps you need to {} it",
2092 self.tcx.def_path_str(trait_info.def_id),
2099 let mut msg = message(action);
2100 for (i, trait_info) in trait_infos.iter().enumerate() {
2101 msg.push_str(&format!(
2102 "\ncandidate #{}: `{}`",
2104 self.tcx.def_path_str(trait_info.def_id),
2110 match &explicitly_negative[..] {
2114 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2115 self.tcx.def_path_str(trait_info.def_id),
2121 let mut msg = format!(
2122 "the following traits define an item `{}`, but are explicitly unimplemented:",
2125 for trait_info in trait_infos {
2126 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2134 /// Checks whether there is a local type somewhere in the chain of
2135 /// autoderefs of `rcvr_ty`.
2136 fn type_derefs_to_local(
2140 source: SelfSource<'tcx>,
2142 fn is_local(ty: Ty<'_>) -> bool {
2144 ty::Adt(def, _) => def.did().is_local(),
2145 ty::Foreign(did) => did.is_local(),
2146 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2147 ty::Param(_) => true,
2149 // Everything else (primitive types, etc.) is effectively
2150 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2151 // the noise from these sort of types is usually just really
2152 // annoying, rather than any sort of help).
2157 // This occurs for UFCS desugaring of `T::method`, where there is no
2158 // receiver expression for the method call, and thus no autoderef.
2159 if let SelfSource::QPath(_) = source {
2160 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2163 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2167 #[derive(Copy, Clone, Debug)]
2168 pub enum SelfSource<'a> {
2169 QPath(&'a hir::Ty<'a>),
2170 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2173 #[derive(Copy, Clone)]
2174 pub struct TraitInfo {
2178 impl PartialEq for TraitInfo {
2179 fn eq(&self, other: &TraitInfo) -> bool {
2180 self.cmp(other) == Ordering::Equal
2183 impl Eq for TraitInfo {}
2184 impl PartialOrd for TraitInfo {
2185 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2186 Some(self.cmp(other))
2189 impl Ord for TraitInfo {
2190 fn cmp(&self, other: &TraitInfo) -> Ordering {
2191 // Local crates are more important than remote ones (local:
2192 // `cnum == 0`), and otherwise we throw in the defid for totality.
2194 let lhs = (other.def_id.krate, other.def_id);
2195 let rhs = (self.def_id.krate, self.def_id);
2200 /// Retrieves all traits in this crate and any dependent crates,
2201 /// and wraps them into `TraitInfo` for custom sorting.
2202 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2203 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2206 fn print_disambiguation_help<'tcx>(
2208 args: Option<&'tcx [hir::Expr<'tcx>]>,
2209 err: &mut Diagnostic,
2212 kind: ty::AssocKind,
2215 candidate: Option<usize>,
2216 source_map: &source_map::SourceMap,
2217 fn_has_self_parameter: bool,
2219 let mut applicability = Applicability::MachineApplicable;
2220 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
2223 if rcvr_ty.is_region_ptr() {
2224 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2229 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2230 applicability = Applicability::HasPlaceholders;
2233 .collect::<Vec<_>>()
2236 let trait_name = if !fn_has_self_parameter {
2237 format!("<{} as {}>", rcvr_ty, trait_name)
2241 (span, format!("{}::{}{}", trait_name, item_name, args))
2243 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2245 err.span_suggestion_verbose(
2248 "disambiguate the {} for {}",
2249 kind.as_def_kind().descr(def_id),
2250 if let Some(candidate) = candidate {
2251 format!("candidate #{}", candidate)
2253 "the candidate".to_string()