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_ast::ast::Mutability;
6 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
12 use rustc_hir::def::DefKind;
13 use rustc_hir::def_id::DefId;
14 use rustc_hir::lang_items::LangItem;
15 use rustc_hir::{ExprKind, Node, QPath};
16 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
17 use rustc_middle::traits::util::supertraits;
18 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
19 use rustc_middle::ty::print::with_crate_prefix;
20 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
21 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
22 use rustc_span::symbol::{kw, sym, Ident};
23 use rustc_span::Symbol;
24 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
25 use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
26 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
27 use rustc_trait_selection::traits::{
28 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
31 use std::cmp::Ordering;
34 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
35 use super::{CandidateSource, MethodError, NoMatchData};
37 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
41 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
42 // so we look for these beforehand.
43 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
44 // If it's not a simple function, look for things which implement `FnOnce`.
46 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
50 // This conditional prevents us from asking to call errors and unresolved types.
51 // It might seem that we can use `predicate_must_hold_modulo_regions`,
52 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
53 // type resolution always gives a "maybe" here.
54 if self.autoderef(span, ty).any(|(ty, _)| {
55 info!("check deref {:?} error", ty);
56 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
61 self.autoderef(span, ty).any(|(ty, _)| {
62 info!("check deref {:?} impl FnOnce", ty);
64 let fn_once_substs = tcx.mk_substs_trait(
67 .next_ty_var(TypeVariableOrigin {
68 kind: TypeVariableOriginKind::MiscVariable,
73 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
74 let poly_trait_ref = ty::Binder::dummy(trait_ref);
75 let obligation = Obligation::misc(
79 poly_trait_ref.without_const().to_predicate(tcx),
81 self.predicate_may_hold(&obligation)
88 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
89 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
92 pub fn report_method_error(
97 source: SelfSource<'tcx>,
98 error: MethodError<'tcx>,
99 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
100 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
101 // Avoid suggestions when we don't know what's going on.
102 if rcvr_ty.references_error() {
106 let report_candidates = |span: Span,
107 err: &mut Diagnostic,
108 mut sources: Vec<CandidateSource>,
112 // Dynamic limit to avoid hiding just one candidate, which is silly.
113 let limit = if sources.len() == 5 { 5 } else { 4 };
115 for (idx, source) in sources.iter().take(limit).enumerate() {
117 CandidateSource::Impl(impl_did) => {
118 // Provide the best span we can. Use the item, if local to crate, else
119 // the impl, if local to crate (item may be defaulted), else nothing.
120 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
121 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
122 self.associated_value(impl_trait_ref.def_id, item_name)
127 let note_span = if item.def_id.is_local() {
128 Some(self.tcx.def_span(item.def_id))
129 } else if impl_did.is_local() {
130 Some(self.tcx.def_span(impl_did))
135 let impl_ty = self.tcx.at(span).type_of(impl_did);
137 let insertion = match self.tcx.impl_trait_ref(impl_did) {
138 None => String::new(),
139 Some(trait_ref) => format!(
140 " of the trait `{}`",
141 self.tcx.def_path_str(trait_ref.def_id)
145 let (note_str, idx) = if sources.len() > 1 {
148 "candidate #{} is defined in an impl{} for the type `{}`",
158 "the candidate is defined in an impl{} for the type `{}`",
164 if let Some(note_span) = note_span {
165 // We have a span pointing to the method. Show note with snippet.
166 err.span_note(note_span, ¬e_str);
170 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
171 let path = self.tcx.def_path_str(trait_ref.def_id);
173 let ty = match item.kind {
174 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
175 ty::AssocKind::Fn => self
181 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
185 print_disambiguation_help(
195 self.tcx.sess.source_map(),
196 item.fn_has_self_parameter,
200 CandidateSource::Trait(trait_did) => {
201 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
202 let item_span = self.tcx.def_span(item.def_id);
203 let idx = if sources.len() > 1 {
205 "candidate #{} is defined in the trait `{}`",
207 self.tcx.def_path_str(trait_did)
209 err.span_note(item_span, msg);
213 "the candidate is defined in the trait `{}`",
214 self.tcx.def_path_str(trait_did)
216 err.span_note(item_span, msg);
219 let path = self.tcx.def_path_str(trait_did);
220 print_disambiguation_help(
230 self.tcx.sess.source_map(),
231 item.fn_has_self_parameter,
236 if sources.len() > limit {
237 err.note(&format!("and {} others", sources.len() - limit));
241 let sugg_span = if let SelfSource::MethodCall(expr) = source {
242 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
243 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
249 MethodError::NoMatch(NoMatchData {
250 static_candidates: static_sources,
251 unsatisfied_predicates,
258 let actual = self.resolve_vars_if_possible(rcvr_ty);
259 let ty_str = self.ty_to_string(actual);
260 let is_method = mode == Mode::MethodCall;
261 let item_kind = if is_method {
263 } else if actual.is_enum() {
264 "variant or associated item"
266 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
267 (Some(name), false) if name.is_lowercase() => "function or associated item",
268 (Some(_), false) => "associated item",
269 (Some(_), true) | (None, false) => "variant or associated item",
270 (None, true) => "variant",
274 if self.suggest_constraining_numerical_ty(
275 tcx, actual, source, span, item_kind, item_name, &ty_str,
280 span = item_name.span;
282 // Don't show generic arguments when the method can't be found in any implementation (#81576).
283 let mut ty_str_reported = ty_str.clone();
284 if let ty::Adt(_, generics) = actual.kind() {
285 if generics.len() > 0 {
286 let mut autoderef = self.autoderef(span, actual);
287 let candidate_found = autoderef.any(|(ty, _)| {
288 if let ty::Adt(adt_deref, _) = ty.kind() {
290 .inherent_impls(adt_deref.did())
292 .filter_map(|def_id| self.associated_value(*def_id, item_name))
299 let has_deref = autoderef.step_count() > 0;
300 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
301 if let Some((path_string, _)) = ty_str.split_once('<') {
302 ty_str_reported = path_string.to_string();
308 let mut err = struct_span_err!(
312 "no {} named `{}` found for {} `{}` in the current scope",
315 actual.prefix_string(self.tcx),
318 if actual.references_error() {
319 err.downgrade_to_delayed_bug();
322 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
323 self.suggest_await_before_method(
324 &mut err, item_name, actual, cal, span,
327 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
330 "you are looking for the module in `std`, not the primitive type",
332 Applicability::MachineApplicable,
335 if let ty::RawPtr(_) = &actual.kind() {
337 "try using `<*const T>::as_ref()` to get a reference to the \
338 type behind the pointer: https://doc.rust-lang.org/std/\
339 primitive.pointer.html#method.as_ref",
342 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
343 to invalid or uninitialized memory is undefined behavior",
347 let ty_span = match actual.kind() {
348 ty::Param(param_type) => {
349 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
350 let type_param = generics.type_param(param_type, self.tcx);
351 Some(self.tcx.def_span(type_param.def_id))
353 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
357 if let Some(span) = ty_span {
361 "{item_kind} `{item_name}` not found for this {}",
362 actual.prefix_string(self.tcx)
367 if let SelfSource::MethodCall(rcvr_expr) = source {
368 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
372 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
373 let probe = self.lookup_probe(
378 ProbeScope::AllTraits,
384 let mut custom_span_label = false;
386 if !static_sources.is_empty() {
388 "found the following associated functions; to be used as methods, \
389 functions must have a `self` parameter",
391 err.span_label(span, "this is an associated function, not a method");
392 custom_span_label = true;
394 if static_sources.len() == 1 {
396 if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) {
397 // When the "method" is resolved through dereferencing, we really want the
398 // original type that has the associated function for accurate suggestions.
400 let ty = tcx.at(span).type_of(*impl_did);
401 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
402 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
403 // Use `actual` as it will have more `substs` filled in.
404 self.ty_to_value_string(actual.peel_refs())
406 _ => self.ty_to_value_string(ty.peel_refs()),
409 self.ty_to_value_string(actual.peel_refs())
411 if let SelfSource::MethodCall(expr) = source {
414 "use associated function syntax instead",
415 format!("{}::{}", ty_str, item_name),
416 Applicability::MachineApplicable,
419 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
422 report_candidates(span, &mut err, static_sources, sugg_span);
423 } else if static_sources.len() > 1 {
424 report_candidates(span, &mut err, static_sources, sugg_span);
427 let mut bound_spans = vec![];
428 let mut restrict_type_params = false;
429 let mut unsatisfied_bounds = false;
430 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
431 let msg = "consider using `len` instead";
432 if let SelfSource::MethodCall(_expr) = source {
433 err.span_suggestion_short(
437 Applicability::MachineApplicable,
440 err.span_label(span, msg);
442 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
443 let iterator_trait = self.tcx.def_path_str(iterator_trait);
444 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
446 } else if !unsatisfied_predicates.is_empty() {
447 let mut type_params = FxHashMap::default();
449 // Pick out the list of unimplemented traits on the receiver.
450 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
451 let mut unimplemented_traits = FxHashMap::default();
452 let mut unimplemented_traits_only = true;
453 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
454 if let (ty::PredicateKind::Trait(p), Some(cause)) =
455 (predicate.kind().skip_binder(), cause.as_ref())
457 if p.trait_ref.self_ty() != rcvr_ty {
458 // This is necessary, not just to keep the errors clean, but also
459 // because our derived obligations can wind up with a trait ref that
460 // requires a different param_env to be correctly compared.
463 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
464 predicate.kind().rebind(p.trait_ref),
466 cause: cause.clone(),
467 param_env: self.param_env,
468 predicate: *predicate,
475 // Make sure that, if any traits other than the found ones were involved,
476 // we don't don't report an unimplemented trait.
477 // We don't want to say that `iter::Cloned` is not an iterator, just
478 // because of some non-Clone item being iterated over.
479 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
480 match predicate.kind().skip_binder() {
481 ty::PredicateKind::Trait(p)
482 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
484 unimplemented_traits_only = false;
490 let mut collect_type_param_suggestions =
491 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
492 // We don't care about regions here, so it's fine to skip the binder here.
493 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
494 (self_ty.kind(), parent_pred.kind().skip_binder())
496 let node = match p.trait_ref.self_ty().kind() {
498 // Account for `fn` items like in `issue-35677.rs` to
499 // suggest restricting its type params.
500 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
501 hir_id: self.body_id,
506 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
509 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
512 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
516 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
517 if let Some(g) = kind.generics() {
519 g.tail_span_for_predicate_suggestion(),
520 g.add_where_or_trailing_comma(),
524 .or_insert_with(FxHashSet::default)
525 .insert(obligation.to_owned());
530 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
532 "doesn't satisfy `{}`",
533 if obligation.len() > 50 { quiet } else { obligation }
535 match &self_ty.kind() {
536 // Point at the type that couldn't satisfy the bound.
538 bound_spans.push((self.tcx.def_span(def.did()), msg))
540 // Point at the trait object that couldn't satisfy the bound.
541 ty::Dynamic(preds, _, _) => {
542 for pred in preds.iter() {
543 match pred.skip_binder() {
544 ty::ExistentialPredicate::Trait(tr) => bound_spans
545 .push((self.tcx.def_span(tr.def_id), msg.clone())),
546 ty::ExistentialPredicate::Projection(_)
547 | ty::ExistentialPredicate::AutoTrait(_) => {}
551 // Point at the closure that couldn't satisfy the bound.
552 ty::Closure(def_id, _) => bound_spans.push((
553 tcx.def_span(*def_id),
554 format!("doesn't satisfy `{}`", quiet),
559 let mut format_pred = |pred: ty::Predicate<'tcx>| {
560 let bound_predicate = pred.kind();
561 match bound_predicate.skip_binder() {
562 ty::PredicateKind::Projection(pred) => {
563 let pred = bound_predicate.rebind(pred);
564 // `<Foo as Iterator>::Item = String`.
565 let projection_ty = pred.skip_binder().projection_ty;
567 let substs_with_infer_self = tcx.mk_substs(
568 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
569 .chain(projection_ty.substs.iter().skip(1)),
572 let quiet_projection_ty = ty::ProjectionTy {
573 substs: substs_with_infer_self,
574 item_def_id: projection_ty.item_def_id,
577 let term = pred.skip_binder().term;
579 let obligation = format!("{} = {}", projection_ty, term);
580 let quiet = format!("{} = {}", quiet_projection_ty, term);
582 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
583 Some((obligation, projection_ty.self_ty()))
585 ty::PredicateKind::Trait(poly_trait_ref) => {
586 let p = poly_trait_ref.trait_ref;
587 let self_ty = p.self_ty();
588 let path = p.print_only_trait_path();
589 let obligation = format!("{}: {}", self_ty, path);
590 let quiet = format!("_: {}", path);
591 bound_span_label(self_ty, &obligation, &quiet);
592 Some((obligation, self_ty))
598 // Find all the requirements that come from a local `impl` block.
599 let mut skip_list: FxHashSet<_> = Default::default();
600 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
601 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
603 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
604 .filter_map(|(p, parent, c)| match c.code() {
605 ObligationCauseCode::ImplDerivedObligation(ref data) => {
606 Some((&data.derived, p, parent, data.impl_def_id, data))
611 let parent_trait_ref = data.parent_trait_pred;
612 let path = parent_trait_ref.print_modifiers_and_trait_path();
613 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
614 let unsatisfied_msg = "unsatisfied trait bound introduced here";
616 "unsatisfied trait bound introduced in this `derive` macro";
617 match self.tcx.hir().get_if_local(impl_def_id) {
618 // Unmet obligation comes from a `derive` macro, point at it once to
619 // avoid multiple span labels pointing at the same place.
620 Some(Node::Item(hir::Item {
621 kind: hir::ItemKind::Trait(..),
625 ident.span.ctxt().outer_expn_data().kind,
626 ExpnKind::Macro(MacroKind::Derive, _)
629 let span = ident.span.ctxt().outer_expn_data().call_site;
630 let mut spans: MultiSpan = span.into();
631 spans.push_span_label(span, derive_msg);
632 let entry = spanned_predicates.entry(spans);
633 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
636 Some(Node::Item(hir::Item {
637 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
640 self_ty.span.ctxt().outer_expn_data().kind,
641 ExpnKind::Macro(MacroKind::Derive, _)
643 of_trait.as_ref().map(|t| t
649 Some(ExpnKind::Macro(MacroKind::Derive, _))
652 let span = self_ty.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 // Unmet obligation coming from a `trait`.
660 Some(Node::Item(hir::Item {
661 kind: hir::ItemKind::Trait(..),
666 ident.span.ctxt().outer_expn_data().kind,
667 ExpnKind::Macro(MacroKind::Derive, _)
670 if let Some(pred) = parent_p {
671 // Done to add the "doesn't satisfy" `span_label`.
672 let _ = format_pred(*pred);
675 let mut spans = if cause.span != *item_span {
676 let mut spans: MultiSpan = cause.span.into();
677 spans.push_span_label(cause.span, unsatisfied_msg);
682 spans.push_span_label(ident.span, "in this trait");
683 let entry = spanned_predicates.entry(spans);
684 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
687 // Unmet obligation coming from an `impl`.
688 Some(Node::Item(hir::Item {
690 hir::ItemKind::Impl(hir::Impl {
691 of_trait, self_ty, generics, ..
696 self_ty.span.ctxt().outer_expn_data().kind,
697 ExpnKind::Macro(MacroKind::Derive, _)
699 of_trait.as_ref().map(|t| t
705 Some(ExpnKind::Macro(MacroKind::Derive, _))
709 unsatisfied_predicates.iter().any(|(pred, _, _)| {
710 match pred.kind().skip_binder() {
711 ty::PredicateKind::Trait(pred) => {
713 == self.tcx.lang_items().sized_trait()
714 && pred.polarity == ty::ImplPolarity::Positive
719 for param in generics.params {
720 if param.span == cause.span && sized_pred {
721 let (sp, sugg) = match param.colon_span {
722 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
723 None => (param.span.shrink_to_hi(), ": ?Sized"),
725 err.span_suggestion_verbose(
727 "consider relaxing the type parameter's implicit \
730 Applicability::MachineApplicable,
734 if let Some(pred) = parent_p {
735 // Done to add the "doesn't satisfy" `span_label`.
736 let _ = format_pred(*pred);
739 let mut spans = if cause.span != *item_span {
740 let mut spans: MultiSpan = cause.span.into();
741 spans.push_span_label(cause.span, unsatisfied_msg);
744 let mut spans = Vec::with_capacity(2);
745 if let Some(trait_ref) = of_trait {
746 spans.push(trait_ref.path.span);
748 spans.push(self_ty.span);
751 if let Some(trait_ref) = of_trait {
752 spans.push_span_label(trait_ref.path.span, "");
754 spans.push_span_label(self_ty.span, "");
756 let entry = spanned_predicates.entry(spans);
757 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
762 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
763 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
764 for (span, (_path, _self_ty, preds)) in spanned_predicates {
765 let mut preds: Vec<_> = preds
767 .filter_map(|pred| format_pred(*pred))
768 .map(|(p, _)| format!("`{}`", p))
772 let msg = if let [pred] = &preds[..] {
773 format!("trait bound {} was not satisfied", pred)
776 "the following trait bounds were not satisfied:\n{}",
780 err.span_note(span, &msg);
781 unsatisfied_bounds = true;
784 // The requirements that didn't have an `impl` span to show.
785 let mut bound_list = unsatisfied_predicates
787 .filter_map(|(pred, parent_pred, _cause)| {
788 format_pred(*pred).map(|(p, self_ty)| {
789 collect_type_param_suggestions(self_ty, *pred, &p);
792 None => format!("`{}`", &p),
793 Some(parent_pred) => match format_pred(*parent_pred) {
794 None => format!("`{}`", &p),
795 Some((parent_p, _)) => {
796 collect_type_param_suggestions(
802 "`{}`\nwhich is required by `{}`",
812 .filter(|(_, pred)| !skip_list.contains(&pred))
815 .collect::<Vec<(usize, String)>>();
817 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
818 restrict_type_params = true;
819 // #74886: Sort here so that the output is always the same.
820 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
822 err.span_suggestion_verbose(
825 "consider restricting the type parameter{s} to satisfy the \
827 s = pluralize!(obligations.len())
829 format!("{} {}", add_where_or_comma, obligations.join(", ")),
830 Applicability::MaybeIncorrect,
834 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
835 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
836 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
838 if !bound_list.is_empty() || !skip_list.is_empty() {
839 let bound_list = bound_list
841 .map(|(_, path)| path)
844 let actual_prefix = actual.prefix_string(self.tcx);
845 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
846 let (primary_message, label) =
847 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
851 .map(|(_, (trait_ref, obligation))| {
852 if trait_ref.self_ty().references_error()
853 || actual.references_error()
858 let OnUnimplementedNote { message, label, .. } =
859 self.on_unimplemented_note(trait_ref, &obligation);
862 .unwrap_or((None, None))
866 let primary_message = primary_message.unwrap_or_else(|| format!(
867 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
869 err.set_primary_message(&primary_message);
870 if let Some(label) = label {
871 custom_span_label = true;
872 err.span_label(span, label);
874 if !bound_list.is_empty() {
876 "the following trait bounds were not satisfied:\n{bound_list}"
879 self.suggest_derive(&mut err, &unsatisfied_predicates);
881 unsatisfied_bounds = true;
885 let label_span_not_found = |err: &mut Diagnostic| {
886 if unsatisfied_predicates.is_empty() {
887 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
888 let is_string_or_ref_str = match actual.kind() {
889 ty::Ref(_, ty, _) => {
893 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
896 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
899 if is_string_or_ref_str && item_name.name == sym::iter {
900 err.span_suggestion_verbose(
902 "because of the in-memory representation of `&str`, to obtain \
903 an `Iterator` over each of its codepoint use method `chars`",
905 Applicability::MachineApplicable,
908 if let ty::Adt(adt, _) = rcvr_ty.kind() {
909 let mut inherent_impls_candidate = self
911 .inherent_impls(adt.did())
915 if let Some(assoc) = self.associated_value(*def_id, item_name) {
916 // Check for both mode is the same so we avoid suggesting
917 // incorrect associated item.
918 match (mode, assoc.fn_has_self_parameter, source) {
919 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
920 // We check that the suggest type is actually
921 // different from the received one
922 // So we avoid suggestion method with Box<Self>
924 self.tcx.at(span).type_of(*def_id) != actual
925 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
927 (Mode::Path, false, _) => true,
934 .collect::<Vec<_>>();
935 if !inherent_impls_candidate.is_empty() {
936 inherent_impls_candidate.sort();
937 inherent_impls_candidate.dedup();
939 // number of type to shows at most.
940 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
941 let type_candidates = inherent_impls_candidate
945 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
949 let additional_types = if inherent_impls_candidate.len() > limit {
951 "\nand {} more types",
952 inherent_impls_candidate.len() - limit
958 "the {item_kind} was found for\n{}{}",
959 type_candidates, additional_types
964 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
968 // If the method name is the name of a field with a function or closure type,
969 // give a helping note that it has to be called as `(x.f)(...)`.
970 if let SelfSource::MethodCall(expr) = source {
971 if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err)
972 && lev_candidate.is_none()
973 && !custom_span_label
975 label_span_not_found(&mut err);
977 } else if !custom_span_label {
978 label_span_not_found(&mut err);
981 // Don't suggest (for example) `expr.field.method()` if `expr.method()`
982 // doesn't exist due to unsatisfied predicates.
983 if unsatisfied_predicates.is_empty() {
984 self.check_for_field_method(&mut err, source, span, actual, item_name);
987 self.check_for_inner_self(&mut err, source, span, actual, item_name);
991 for (span, msg) in bound_spans.into_iter() {
992 err.span_label(span, &msg);
995 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
997 self.suggest_traits_to_import(
1002 args.map(|(_, args)| args.len() + 1),
1004 out_of_scope_traits,
1005 &unsatisfied_predicates,
1010 // Don't emit a suggestion if we found an actual method
1011 // that had unsatisfied trait bounds
1012 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1013 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1014 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1015 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1019 err.span_suggestion(
1021 "there is a variant with a similar name",
1023 Applicability::MaybeIncorrect,
1028 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1029 let msg = "remove this method call";
1030 let mut fallback_span = true;
1031 if let SelfSource::MethodCall(expr) = source {
1033 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1034 if let Some(span) = call_expr.span.trim_start(expr.span) {
1035 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1036 fallback_span = false;
1040 err.span_label(span, msg);
1042 } else if let Some(lev_candidate) = lev_candidate {
1043 // Don't emit a suggestion if we found an actual method
1044 // that had unsatisfied trait bounds
1045 if unsatisfied_predicates.is_empty() {
1046 let def_kind = lev_candidate.kind.as_def_kind();
1047 // Methods are defined within the context of a struct and their first parameter is always self,
1048 // which represents the instance of the struct the method is being called on
1049 // Associated functions don’t take self as a parameter and
1050 // they are not methods because they don’t have an instance of the struct to work with.
1051 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1052 err.span_suggestion(
1054 &format!("there is a method with a similar name",),
1056 Applicability::MaybeIncorrect,
1059 err.span_suggestion(
1062 "there is {} {} with a similar name",
1064 def_kind.descr(lev_candidate.def_id),
1067 Applicability::MaybeIncorrect,
1073 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1078 MethodError::Ambiguity(sources) => {
1079 let mut err = struct_span_err!(
1083 "multiple applicable items in scope"
1085 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1087 report_candidates(span, &mut err, sources, sugg_span);
1091 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1092 let kind = kind.descr(def_id);
1093 let mut err = struct_span_err!(
1097 "{} `{}` is private",
1101 err.span_label(item_name.span, &format!("private {}", kind));
1105 .span_if_local(def_id)
1106 .unwrap_or_else(|| self.tcx.def_span(def_id));
1107 err.span_label(sp, &format!("private {} defined here", kind));
1108 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1112 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1113 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1114 let mut err = self.sess().struct_span_err(span, &msg);
1115 err.span_label(bound_span, "this has a `Sized` requirement");
1116 if !candidates.is_empty() {
1118 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1119 add a `use` for {one_of_them}:",
1120 an = if candidates.len() == 1 { "an" } else { "" },
1121 s = pluralize!(candidates.len()),
1122 were = pluralize!("was", candidates.len()),
1123 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1125 self.suggest_use_candidates(&mut err, help, candidates);
1127 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1129 let trait_type = self.tcx.mk_ref(
1131 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1133 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1139 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1144 fn suggest_field_call(
1148 expr: &hir::Expr<'_>,
1150 err: &mut Diagnostic,
1153 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1154 ty::Adt(def, substs) if !def.is_enum() => {
1155 let variant = &def.non_enum_variant();
1156 tcx.find_field_index(item_name, variant).map(|index| {
1157 let field = &variant.fields[index];
1158 let field_ty = field.ty(tcx, substs);
1164 if let Some((field, field_ty)) = field_receiver {
1165 let scope = tcx.parent_module(self.body_id);
1166 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1169 if self.is_fn_ty(field_ty, span) {
1170 let expr_span = expr.span.to(item_name.span);
1171 err.multipart_suggestion(
1173 "to call the function stored in `{}`, \
1174 surround the field access with parentheses",
1178 (expr_span.shrink_to_lo(), '('.to_string()),
1179 (expr_span.shrink_to_hi(), ')'.to_string()),
1181 Applicability::MachineApplicable,
1184 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1186 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1187 err.span_suggestion(
1189 "remove the arguments",
1191 Applicability::MaybeIncorrect,
1197 let field_kind = if is_accessible { "field" } else { "private field" };
1198 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1204 fn suggest_constraining_numerical_ty(
1208 source: SelfSource<'_>,
1214 let found_candidate = all_traits(self.tcx)
1216 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1217 let found_assoc = |ty: Ty<'tcx>| {
1218 simplify_type(tcx, ty, TreatParams::AsInfer)
1220 tcx.incoherent_impls(simp)
1222 .find_map(|&id| self.associated_value(id, item_name))
1226 let found_candidate = found_candidate
1227 || found_assoc(tcx.types.i8)
1228 || found_assoc(tcx.types.i16)
1229 || found_assoc(tcx.types.i32)
1230 || found_assoc(tcx.types.i64)
1231 || found_assoc(tcx.types.i128)
1232 || found_assoc(tcx.types.u8)
1233 || found_assoc(tcx.types.u16)
1234 || found_assoc(tcx.types.u32)
1235 || found_assoc(tcx.types.u64)
1236 || found_assoc(tcx.types.u128)
1237 || found_assoc(tcx.types.f32)
1238 || found_assoc(tcx.types.f32);
1240 && actual.is_numeric()
1241 && !actual.has_concrete_skeleton()
1242 && let SelfSource::MethodCall(expr) = source
1244 let mut err = struct_span_err!(
1248 "can't call {} `{}` on ambiguous numeric type `{}`",
1253 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1255 ExprKind::Lit(ref lit) => {
1260 .span_to_snippet(lit.span)
1261 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1263 // If this is a floating point literal that ends with '.',
1264 // get rid of it to stop this from becoming a member access.
1265 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1267 err.span_suggestion(
1270 "you must specify a concrete type for this numeric value, \
1274 format!("{snippet}_{concrete_type}"),
1275 Applicability::MaybeIncorrect,
1278 ExprKind::Path(QPath::Resolved(_, path)) => {
1280 if let hir::def::Res::Local(hir_id) = path.res {
1281 let span = tcx.hir().span(hir_id);
1282 let filename = tcx.sess.source_map().span_to_filename(span);
1285 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1287 "you must specify a type for this binding, like `{}`",
1291 match (filename, parent_node) {
1294 Node::Local(hir::Local {
1295 source: hir::LocalSource::Normal,
1300 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1301 err.span_suggestion(
1302 // account for `let x: _ = 42;`
1306 format!(": {concrete_type}"),
1307 Applicability::MaybeIncorrect,
1311 err.span_label(span, msg);
1324 fn check_for_field_method(
1326 err: &mut Diagnostic,
1327 source: SelfSource<'tcx>,
1332 if let SelfSource::MethodCall(expr) = source
1333 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1334 && let Some((fields, substs)) =
1335 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1337 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1339 let lang_items = self.tcx.lang_items();
1340 let never_mention_traits = [
1341 lang_items.clone_trait(),
1342 lang_items.deref_trait(),
1343 lang_items.deref_mut_trait(),
1344 self.tcx.get_diagnostic_item(sym::AsRef),
1345 self.tcx.get_diagnostic_item(sym::AsMut),
1346 self.tcx.get_diagnostic_item(sym::Borrow),
1347 self.tcx.get_diagnostic_item(sym::BorrowMut),
1349 let candidate_fields: Vec<_> = fields
1350 .filter_map(|candidate_field| {
1351 self.check_for_nested_field_satisfying(
1359 ProbeScope::TraitsInScope,
1361 .map_or(false, |pick| {
1362 !never_mention_traits
1365 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1377 .map(|id| id.name.to_ident_string())
1378 .collect::<Vec<String>>()
1383 let len = candidate_fields.len();
1385 err.span_suggestions(
1386 item_name.span.shrink_to_lo(),
1388 "{} of the expressions' fields {} a method of the same name",
1389 if len > 1 { "some" } else { "one" },
1390 if len > 1 { "have" } else { "has" },
1392 candidate_fields.iter().map(|path| format!("{path}.")),
1393 Applicability::MaybeIncorrect,
1399 fn check_for_inner_self(
1401 err: &mut Diagnostic,
1402 source: SelfSource<'tcx>,
1408 let SelfSource::MethodCall(expr) = source else { return; };
1409 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1411 let ty::Adt(kind, substs) = actual.kind() else { return; };
1412 match kind.adt_kind() {
1413 ty::AdtKind::Enum => {
1414 let matching_variants: Vec<_> = kind
1417 .flat_map(|variant| {
1418 let [field] = &variant.fields[..] else { return None; };
1419 let field_ty = field.ty(tcx, substs);
1421 // Skip `_`, since that'll just lead to ambiguity.
1422 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1431 ProbeScope::TraitsInScope,
1434 .map(|pick| (variant, field, pick))
1438 let ret_ty_matches = |diagnostic_item| {
1439 if let Some(ret_ty) = self
1442 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1443 && let ty::Adt(kind, _) = ret_ty.kind()
1444 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1452 match &matching_variants[..] {
1453 [(_, field, pick)] => {
1454 let self_ty = field.ty(tcx, substs);
1456 tcx.def_span(pick.item.def_id),
1457 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1459 let (article, kind, variant, question) =
1460 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1461 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1462 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1463 ("an", "Option", "None", ret_ty_matches(sym::Option))
1468 err.span_suggestion_verbose(
1469 expr.span.shrink_to_hi(),
1471 "use the `?` operator to extract the `{self_ty}` value, propagating \
1472 {article} `{kind}::{variant}` value to the caller"
1475 Applicability::MachineApplicable,
1478 err.span_suggestion_verbose(
1479 expr.span.shrink_to_hi(),
1481 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1482 panicking if the value is {article} `{kind}::{variant}`"
1484 ".expect(\"REASON\")",
1485 Applicability::HasPlaceholders,
1489 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1493 // Target wrapper types - types that wrap or pretend to wrap another type,
1494 // perhaps this inner type is meant to be called?
1495 ty::AdtKind::Struct | ty::AdtKind::Union => {
1496 let [first] = ***substs else { return; };
1497 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1498 let Ok(pick) = self.lookup_probe(
1503 ProbeScope::TraitsInScope,
1506 let name = self.ty_to_value_string(actual);
1507 let inner_id = kind.did();
1508 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1509 pick.autoref_or_ptr_adjustment
1516 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1517 err.help("use `with` or `try_with` to access thread local storage");
1518 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1520 "if this `{name}` has been initialized, \
1521 use one of the `assume_init` methods to access the inner value"
1523 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1524 let (suggestion, borrow_kind, panic_if) = match mutable {
1525 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1526 Some(Mutability::Mut) => {
1527 (".borrow_mut()", "mutably borrow", "any borrows exist")
1531 err.span_suggestion_verbose(
1532 expr.span.shrink_to_hi(),
1534 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1535 panicking if {panic_if}"
1538 Applicability::MaybeIncorrect,
1540 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1541 err.span_suggestion_verbose(
1542 expr.span.shrink_to_hi(),
1544 "use `.lock().unwrap()` to borrow the `{ty}`, \
1545 blocking the current thread until it can be acquired"
1548 Applicability::MaybeIncorrect,
1550 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1551 let (suggestion, borrow_kind) = match mutable {
1552 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1553 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1556 err.span_suggestion_verbose(
1557 expr.span.shrink_to_hi(),
1559 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1560 blocking the current thread until it can be acquired"
1563 Applicability::MaybeIncorrect,
1570 tcx.def_span(pick.item.def_id),
1571 &format!("the method `{item_name}` exists on the type `{ty}`"),
1577 pub(crate) fn note_unmet_impls_on_type(
1579 err: &mut Diagnostic,
1580 errors: Vec<FulfillmentError<'tcx>>,
1582 let all_local_types_needing_impls =
1583 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1584 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1585 ty::Adt(def, _) => def.did().is_local(),
1590 let mut preds: Vec<_> = errors
1592 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1593 ty::PredicateKind::Trait(pred) => Some(pred),
1597 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1600 .filter_map(|pred| match pred.self_ty().kind() {
1601 ty::Adt(def, _) => Some(def.did()),
1604 .collect::<FxHashSet<_>>();
1605 let mut spans: MultiSpan = def_ids
1607 .filter_map(|def_id| {
1608 let span = self.tcx.def_span(*def_id);
1609 if span.is_dummy() { None } else { Some(span) }
1611 .collect::<Vec<_>>()
1614 for pred in &preds {
1615 match pred.self_ty().kind() {
1616 ty::Adt(def, _) if def.did().is_local() => {
1617 spans.push_span_label(
1618 self.tcx.def_span(def.did()),
1619 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1626 if all_local_types_needing_impls && spans.primary_span().is_some() {
1627 let msg = if preds.len() == 1 {
1629 "an implementation of `{}` might be missing for `{}`",
1630 preds[0].trait_ref.print_only_trait_path(),
1635 "the following type{} would have to `impl` {} required trait{} for this \
1636 operation to be valid",
1637 pluralize!(def_ids.len()),
1638 if def_ids.len() == 1 { "its" } else { "their" },
1639 pluralize!(preds.len()),
1642 err.span_note(spans, &msg);
1645 let preds: Vec<_> = errors
1647 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1649 self.suggest_derive(err, &preds);
1654 err: &mut Diagnostic,
1655 unsatisfied_predicates: &[(
1656 ty::Predicate<'tcx>,
1657 Option<ty::Predicate<'tcx>>,
1658 Option<ObligationCause<'tcx>>,
1661 let mut derives = Vec::<(String, Span, Symbol)>::new();
1662 let mut traits = Vec::<Span>::new();
1663 for (pred, _, _) in unsatisfied_predicates {
1664 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1665 let adt = match trait_pred.self_ty().ty_adt_def() {
1666 Some(adt) if adt.did().is_local() => adt,
1669 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1670 let can_derive = match diagnostic_name {
1671 sym::Default => !adt.is_enum(),
1679 | sym::Debug => true,
1683 let self_name = trait_pred.self_ty().to_string();
1684 let self_span = self.tcx.def_span(adt.did());
1685 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1686 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1688 if let Some(parent_diagnostic_name) =
1689 self.tcx.get_diagnostic_name(super_trait.def_id())
1694 parent_diagnostic_name,
1699 derives.push((self_name, self_span, diagnostic_name));
1701 traits.push(self.tcx.def_span(trait_pred.def_id()));
1704 traits.push(self.tcx.def_span(trait_pred.def_id()));
1713 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1714 for (self_name, self_span, trait_name) in derives.into_iter() {
1715 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1717 if last_self_name == &self_name {
1718 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1722 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1725 let len = traits.len();
1727 let span: MultiSpan = traits.into();
1730 &format!("the following trait{} must be implemented", pluralize!(len),),
1734 for (self_name, self_span, traits) in &derives_grouped {
1735 err.span_suggestion_verbose(
1736 self_span.shrink_to_lo(),
1737 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1738 format!("#[derive({})]\n", traits),
1739 Applicability::MaybeIncorrect,
1744 fn check_for_deref_method(
1746 err: &mut Diagnostic,
1747 self_source: SelfSource<'tcx>,
1751 let SelfSource::QPath(ty) = self_source else { return; };
1752 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1753 if let Ok(pick) = self.probe_for_name(
1760 ProbeScope::TraitsInScope,
1762 if deref_ty.is_suggestable(self.tcx, true)
1763 // If this method receives `&self`, then the provided
1764 // argument _should_ coerce, so it's valid to suggest
1765 // just changing the path.
1766 && pick.item.fn_has_self_parameter
1767 && let Some(self_ty) =
1768 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1771 let suggested_path = match deref_ty.kind() {
1780 | ty::Param(_) => format!("{deref_ty}"),
1781 _ => format!("<{deref_ty}>"),
1783 err.span_suggestion_verbose(
1785 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1787 Applicability::MaybeIncorrect,
1792 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1800 /// Print out the type for use in value namespace.
1801 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1803 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1804 _ => self.ty_to_string(ty),
1808 fn suggest_await_before_method(
1810 err: &mut Diagnostic,
1813 call: &hir::Expr<'_>,
1816 let output_ty = match self.get_impl_future_output_ty(ty) {
1817 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1820 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1821 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1823 err.span_suggestion_verbose(
1824 span.shrink_to_lo(),
1825 "consider `await`ing on the `Future` and calling the method on its `Output`",
1827 Applicability::MaybeIncorrect,
1832 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1833 let parent_map = self.tcx.visible_parent_map(());
1835 // Separate out candidates that must be imported with a glob, because they are named `_`
1836 // and cannot be referred with their identifier.
1837 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1838 if let Some(parent_did) = parent_map.get(trait_did) {
1839 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1840 if *parent_did != self.tcx.parent(*trait_did)
1843 .module_children(*parent_did)
1845 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1846 .all(|child| child.ident.name == kw::Underscore)
1855 let module_did = self.tcx.parent_module(self.body_id);
1856 let (module, _, _) = self.tcx.hir().get_module(module_did);
1857 let span = module.spans.inject_use_span;
1859 let path_strings = candidates.iter().map(|trait_did| {
1860 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1863 let glob_path_strings = globs.iter().map(|trait_did| {
1864 let parent_did = parent_map.get(trait_did).unwrap();
1866 "use {}::*; // trait {}\n",
1867 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1868 self.tcx.item_name(*trait_did),
1872 err.span_suggestions(
1875 path_strings.chain(glob_path_strings),
1876 Applicability::MaybeIncorrect,
1880 fn suggest_valid_traits(
1882 err: &mut Diagnostic,
1883 valid_out_of_scope_traits: Vec<DefId>,
1885 if !valid_out_of_scope_traits.is_empty() {
1886 let mut candidates = valid_out_of_scope_traits;
1890 // `TryFrom` and `FromIterator` have no methods
1891 let edition_fix = candidates
1893 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1896 err.help("items from traits can only be used if the trait is in scope");
1898 "the following {traits_are} implemented but not in scope; \
1899 perhaps add a `use` for {one_of_them}:",
1900 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1901 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1904 self.suggest_use_candidates(err, msg, candidates);
1905 if let Some(did) = edition_fix {
1907 "'{}' is included in the prelude starting in Edition 2021",
1908 with_crate_prefix!(self.tcx.def_path_str(did))
1918 fn suggest_traits_to_import(
1920 err: &mut Diagnostic,
1924 inputs_len: Option<usize>,
1925 source: SelfSource<'tcx>,
1926 valid_out_of_scope_traits: Vec<DefId>,
1927 unsatisfied_predicates: &[(
1928 ty::Predicate<'tcx>,
1929 Option<ty::Predicate<'tcx>>,
1930 Option<ObligationCause<'tcx>>,
1932 unsatisfied_bounds: bool,
1934 let mut alt_rcvr_sugg = false;
1935 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1936 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1938 self.tcx.lang_items().clone_trait(),
1939 self.tcx.lang_items().deref_trait(),
1940 self.tcx.lang_items().deref_mut_trait(),
1941 self.tcx.lang_items().drop_trait(),
1942 self.tcx.get_diagnostic_item(sym::AsRef),
1944 // Try alternative arbitrary self types that could fulfill this call.
1945 // FIXME: probe for all types that *could* be arbitrary self-types, not
1947 for (rcvr_ty, post) in &[
1949 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1950 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1952 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1954 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1955 // We point at the method, but we just skip the rest of the check for arbitrary
1956 // self types and rely on the suggestion to `use` the trait from
1957 // `suggest_valid_traits`.
1958 let did = Some(pick.item.container_id(self.tcx));
1959 let skip = skippable.contains(&did);
1960 if pick.autoderefs == 0 && !skip {
1962 pick.item.ident(self.tcx).span,
1963 &format!("the method is available for `{}` here", rcvr_ty),
1968 Err(MethodError::Ambiguity(_)) => {
1969 // If the method is defined (but ambiguous) for the receiver we have, it is also
1970 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1971 // the receiver, then it might disambiguate this method, but I think these
1972 // suggestions are generally misleading (see #94218).
1978 for (rcvr_ty, pre) in &[
1979 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1980 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1981 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1982 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1984 if let Some(new_rcvr_t) = *rcvr_ty
1985 && let Ok(pick) = self.lookup_probe(
1990 ProbeScope::AllTraits,
1993 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1994 let did = Some(pick.item.container_id(self.tcx));
1995 // We don't want to suggest a container type when the missing
1996 // method is `.clone()` or `.deref()` otherwise we'd suggest
1997 // `Arc::new(foo).clone()`, which is far from what the user wants.
1998 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1999 // implement the `AsRef` trait.
2000 let skip = skippable.contains(&did)
2001 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2002 || 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);
2003 // Make sure the method is defined for the *actual* receiver: we don't
2004 // want to treat `Box<Self>` as a receiver if it only works because of
2005 // an autoderef to `&self`
2006 if pick.autoderefs == 0 && !skip {
2008 pick.item.ident(self.tcx).span,
2009 &format!("the method is available for `{}` here", new_rcvr_t),
2011 err.multipart_suggestion(
2012 "consider wrapping the receiver expression with the \
2015 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2016 (rcvr.span.shrink_to_hi(), ")".to_string()),
2018 Applicability::MaybeIncorrect,
2020 // We don't care about the other suggestions.
2021 alt_rcvr_sugg = true;
2027 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2031 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2033 let mut arbitrary_rcvr = vec![];
2034 // There are no traits implemented, so lets suggest some traits to
2035 // implement, by finding ones that have the item name, and are
2036 // legal to implement.
2037 let mut candidates = all_traits(self.tcx)
2039 // Don't issue suggestions for unstable traits since they're
2040 // unlikely to be implementable anyway
2041 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2042 Some(attr) => attr.level.is_stable(),
2046 // We approximate the coherence rules to only suggest
2047 // traits that are legal to implement by requiring that
2048 // either the type or trait is local. Multi-dispatch means
2049 // this isn't perfect (that is, there are cases when
2050 // implementing a trait would be legal but is rejected
2052 unsatisfied_predicates.iter().all(|(p, _, _)| {
2053 match p.kind().skip_binder() {
2054 // Hide traits if they are present in predicates as they can be fixed without
2055 // having to implement them.
2056 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2057 ty::PredicateKind::Projection(p) => {
2058 p.projection_ty.item_def_id == info.def_id
2062 }) && (type_is_local || info.def_id.is_local())
2064 .associated_value(info.def_id, item_name)
2066 if let ty::AssocKind::Fn = item.kind {
2070 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2071 if let Some(hir::Node::TraitItem(hir::TraitItem {
2072 kind: hir::TraitItemKind::Fn(fn_sig, method),
2074 })) = id.map(|id| self.tcx.hir().get(id))
2076 let self_first_arg = match method {
2077 hir::TraitFn::Required([ident, ..]) => {
2078 ident.name == kw::SelfLower
2080 hir::TraitFn::Provided(body_id) => {
2081 self.tcx.hir().body(*body_id).params.first().map_or(
2086 hir::PatKind::Binding(_, _, ident, _)
2087 if ident.name == kw::SelfLower
2095 if !fn_sig.decl.implicit_self.has_implicit_self()
2098 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2099 arbitrary_rcvr.push(ty.span);
2105 // We only want to suggest public or local traits (#45781).
2106 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2110 .collect::<Vec<_>>();
2111 for span in &arbitrary_rcvr {
2114 "the method might not be found because of this arbitrary self type",
2121 if !candidates.is_empty() {
2122 // Sort from most relevant to least relevant.
2123 candidates.sort_by(|a, b| a.cmp(b).reverse());
2126 let param_type = match rcvr_ty.kind() {
2127 ty::Param(param) => Some(param),
2128 ty::Ref(_, ty, _) => match ty.kind() {
2129 ty::Param(param) => Some(param),
2134 err.help(if param_type.is_some() {
2135 "items from traits can only be used if the type parameter is bounded by the trait"
2137 "items from traits can only be used if the trait is implemented and in scope"
2139 let candidates_len = candidates.len();
2140 let message = |action| {
2142 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2145 if candidates_len == 1 { "trait defines" } else { "traits define" },
2147 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2151 // Obtain the span for `param` and use it for a structured suggestion.
2152 if let Some(param) = param_type {
2153 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2154 let type_param = generics.type_param(param, self.tcx);
2155 let hir = self.tcx.hir();
2156 if let Some(def_id) = type_param.def_id.as_local() {
2157 let id = hir.local_def_id_to_hir_id(def_id);
2158 // Get the `hir::Param` to verify whether it already has any bounds.
2159 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2160 // instead we suggest `T: Foo + Bar` in that case.
2162 Node::GenericParam(param) => {
2168 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2169 let (sp, mut introducer) = if let Some(span) =
2170 ast_generics.bounds_span_for_suggestions(def_id)
2172 (span, Introducer::Plus)
2173 } else if let Some(colon_span) = param.colon_span {
2174 (colon_span.shrink_to_hi(), Introducer::Nothing)
2176 (param.span.shrink_to_hi(), Introducer::Colon)
2180 hir::GenericParamKind::Type { synthetic: true, .. },
2182 introducer = Introducer::Plus
2184 let trait_def_ids: FxHashSet<DefId> = ast_generics
2185 .bounds_for_param(def_id)
2186 .flat_map(|bp| bp.bounds.iter())
2187 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2189 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2190 err.span_suggestions(
2193 "restrict type parameter `{}` with",
2196 candidates.iter().map(|t| {
2200 Introducer::Plus => " +",
2201 Introducer::Colon => ":",
2202 Introducer::Nothing => "",
2204 self.tcx.def_path_str(t.def_id),
2207 Applicability::MaybeIncorrect,
2212 Node::Item(hir::Item {
2213 kind: hir::ItemKind::Trait(.., bounds, _),
2217 let (sp, sep, article) = if bounds.is_empty() {
2218 (ident.span.shrink_to_hi(), ":", "a")
2220 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2222 err.span_suggestions(
2224 &message(format!("add {} supertrait for", article)),
2225 candidates.iter().map(|t| {
2226 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2228 Applicability::MaybeIncorrect,
2237 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2238 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2239 // cases where a positive bound implies a negative impl.
2240 (candidates, Vec::new())
2241 } else if let Some(simp_rcvr_ty) =
2242 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2244 let mut potential_candidates = Vec::new();
2245 let mut explicitly_negative = Vec::new();
2246 for candidate in candidates {
2247 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2250 .all_impls(candidate.def_id)
2252 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2255 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2257 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2258 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2261 explicitly_negative.push(candidate);
2263 potential_candidates.push(candidate);
2266 (potential_candidates, explicitly_negative)
2268 // We don't know enough about `recv_ty` to make proper suggestions.
2269 (candidates, Vec::new())
2272 let action = if let Some(param) = param_type {
2273 format!("restrict type parameter `{}` with", param)
2275 // FIXME: it might only need to be imported into scope, not implemented.
2276 "implement".to_string()
2278 match &potential_candidates[..] {
2280 [trait_info] if trait_info.def_id.is_local() => {
2282 self.tcx.def_span(trait_info.def_id),
2284 "`{}` defines an item `{}`, perhaps you need to {} it",
2285 self.tcx.def_path_str(trait_info.def_id),
2292 let mut msg = message(action);
2293 for (i, trait_info) in trait_infos.iter().enumerate() {
2294 msg.push_str(&format!(
2295 "\ncandidate #{}: `{}`",
2297 self.tcx.def_path_str(trait_info.def_id),
2303 match &explicitly_negative[..] {
2307 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2308 self.tcx.def_path_str(trait_info.def_id),
2314 let mut msg = format!(
2315 "the following traits define an item `{}`, but are explicitly unimplemented:",
2318 for trait_info in trait_infos {
2319 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2327 /// Checks whether there is a local type somewhere in the chain of
2328 /// autoderefs of `rcvr_ty`.
2329 fn type_derefs_to_local(
2333 source: SelfSource<'tcx>,
2335 fn is_local(ty: Ty<'_>) -> bool {
2337 ty::Adt(def, _) => def.did().is_local(),
2338 ty::Foreign(did) => did.is_local(),
2339 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2340 ty::Param(_) => true,
2342 // Everything else (primitive types, etc.) is effectively
2343 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2344 // the noise from these sort of types is usually just really
2345 // annoying, rather than any sort of help).
2350 // This occurs for UFCS desugaring of `T::method`, where there is no
2351 // receiver expression for the method call, and thus no autoderef.
2352 if let SelfSource::QPath(_) = source {
2353 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2356 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2360 #[derive(Copy, Clone, Debug)]
2361 pub enum SelfSource<'a> {
2362 QPath(&'a hir::Ty<'a>),
2363 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2366 #[derive(Copy, Clone)]
2367 pub struct TraitInfo {
2371 impl PartialEq for TraitInfo {
2372 fn eq(&self, other: &TraitInfo) -> bool {
2373 self.cmp(other) == Ordering::Equal
2376 impl Eq for TraitInfo {}
2377 impl PartialOrd for TraitInfo {
2378 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2379 Some(self.cmp(other))
2382 impl Ord for TraitInfo {
2383 fn cmp(&self, other: &TraitInfo) -> Ordering {
2384 // Local crates are more important than remote ones (local:
2385 // `cnum == 0`), and otherwise we throw in the defid for totality.
2387 let lhs = (other.def_id.krate, other.def_id);
2388 let rhs = (self.def_id.krate, self.def_id);
2393 /// Retrieves all traits in this crate and any dependent crates,
2394 /// and wraps them into `TraitInfo` for custom sorting.
2395 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2396 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2399 fn print_disambiguation_help<'tcx>(
2401 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2402 err: &mut Diagnostic,
2405 kind: ty::AssocKind,
2408 candidate: Option<usize>,
2409 source_map: &source_map::SourceMap,
2410 fn_has_self_parameter: bool,
2412 let mut applicability = Applicability::MachineApplicable;
2413 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2416 if rcvr_ty.is_region_ptr() {
2417 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2421 std::iter::once(receiver)
2423 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2424 applicability = Applicability::HasPlaceholders;
2427 .collect::<Vec<_>>()
2430 let trait_name = if !fn_has_self_parameter {
2431 format!("<{} as {}>", rcvr_ty, trait_name)
2435 (span, format!("{}::{}{}", trait_name, item_name, args))
2437 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2439 err.span_suggestion_verbose(
2442 "disambiguate the {} for {}",
2443 kind.as_def_kind().descr(def_id),
2444 if let Some(candidate) = candidate {
2445 format!("candidate #{}", candidate)
2447 "the candidate".to_string()