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,
10 use rustc_hir::def_id::DefId;
11 use rustc_hir::lang_items::LangItem;
12 use rustc_hir::{ExprKind, Node, QPath};
13 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
14 use rustc_middle::traits::util::supertraits;
15 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
16 use rustc_middle::ty::print::with_crate_prefix;
17 use rustc_middle::ty::ToPolyTraitRef;
18 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
19 use rustc_span::symbol::{kw, sym, Ident};
20 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, MultiSpan, Span};
21 use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
22 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
23 use rustc_trait_selection::traits::{
24 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
27 use std::cmp::Ordering;
30 use super::probe::Mode;
31 use super::{CandidateSource, MethodError, NoMatchData};
33 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
37 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
38 // so we look for these beforehand.
39 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
40 // If it's not a simple function, look for things which implement `FnOnce`.
42 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
46 // This conditional prevents us from asking to call errors and unresolved types.
47 // It might seem that we can use `predicate_must_hold_modulo_regions`,
48 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
49 // type resolution always gives a "maybe" here.
50 if self.autoderef(span, ty).any(|(ty, _)| {
51 info!("check deref {:?} error", ty);
52 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
57 self.autoderef(span, ty).any(|(ty, _)| {
58 info!("check deref {:?} impl FnOnce", ty);
60 let fn_once_substs = tcx.mk_substs_trait(
63 .next_ty_var(TypeVariableOrigin {
64 kind: TypeVariableOriginKind::MiscVariable,
69 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
70 let poly_trait_ref = ty::Binder::dummy(trait_ref);
71 let obligation = Obligation::misc(
75 poly_trait_ref.without_const().to_predicate(tcx),
77 self.predicate_may_hold(&obligation)
84 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
85 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
88 pub fn report_method_error(
93 source: SelfSource<'tcx>,
94 error: MethodError<'tcx>,
95 args: Option<&'tcx [hir::Expr<'tcx>]>,
96 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
97 // Avoid suggestions when we don't know what's going on.
98 if rcvr_ty.references_error() {
102 let report_candidates = |span: Span,
103 err: &mut Diagnostic,
104 mut sources: Vec<CandidateSource>,
108 // Dynamic limit to avoid hiding just one candidate, which is silly.
109 let limit = if sources.len() == 5 { 5 } else { 4 };
111 for (idx, source) in sources.iter().take(limit).enumerate() {
113 CandidateSource::ImplSource(impl_did) => {
114 // Provide the best span we can. Use the item, if local to crate, else
115 // the impl, if local to crate (item may be defaulted), else nothing.
116 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
117 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
118 self.associated_value(impl_trait_ref.def_id, item_name)
125 .span_if_local(item.def_id)
126 .or_else(|| self.tcx.hir().span_if_local(impl_did));
128 let impl_ty = self.tcx.at(span).type_of(impl_did);
130 let insertion = match self.tcx.impl_trait_ref(impl_did) {
131 None => String::new(),
132 Some(trait_ref) => format!(
133 " of the trait `{}`",
134 self.tcx.def_path_str(trait_ref.def_id)
138 let (note_str, idx) = if sources.len() > 1 {
141 "candidate #{} is defined in an impl{} for the type `{}`",
151 "the candidate is defined in an impl{} for the type `{}`",
157 if let Some(note_span) = note_span {
158 // We have a span pointing to the method. Show note with snippet.
160 self.tcx.sess.source_map().guess_head_span(note_span),
166 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
167 let path = self.tcx.def_path_str(trait_ref.def_id);
169 let ty = match item.kind {
170 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
171 ty::AssocKind::Fn => self
177 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
181 print_disambiguation_help(
191 self.tcx.sess.source_map(),
192 item.fn_has_self_parameter,
196 CandidateSource::TraitSource(trait_did) => {
197 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
202 .guess_head_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",
273 // FIXME(eddyb) this indentation is probably unnecessary.
275 // Suggest clamping down the type if the method that is being attempted to
276 // be used exists at all, and the type is an ambiguous numeric type
277 // ({integer}/{float}).
278 let mut candidates = all_traits(self.tcx)
280 .filter_map(|info| self.associated_value(info.def_id, item_name));
281 // There are methods that are defined on the primitive types and won't be
282 // found when exploring `all_traits`, but we also need them to be accurate on
283 // our suggestions (#47759).
284 let found_assoc = |ty: Ty<'tcx>| {
285 simplify_type(tcx, ty, TreatParams::AsPlaceholders)
287 tcx.incoherent_impls(simp)
289 .find_map(|&id| self.associated_value(id, item_name))
293 let found_candidate = candidates.next().is_some()
294 || found_assoc(tcx.types.i8)
295 || found_assoc(tcx.types.i16)
296 || found_assoc(tcx.types.i32)
297 || found_assoc(tcx.types.i64)
298 || found_assoc(tcx.types.i128)
299 || found_assoc(tcx.types.u8)
300 || found_assoc(tcx.types.u16)
301 || found_assoc(tcx.types.u32)
302 || found_assoc(tcx.types.u64)
303 || found_assoc(tcx.types.u128)
304 || found_assoc(tcx.types.f32)
305 || found_assoc(tcx.types.f32);
306 if let (true, false, SelfSource::MethodCall(expr), true) = (
308 actual.has_concrete_skeleton(),
312 let mut err = struct_span_err!(
316 "can't call {} `{}` on ambiguous numeric type `{}`",
321 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
323 ExprKind::Lit(ref lit) => {
328 .span_to_snippet(lit.span)
329 .unwrap_or_else(|_| "<numeric literal>".to_owned());
331 // If this is a floating point literal that ends with '.',
332 // get rid of it to stop this from becoming a member access.
333 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
338 "you must specify a concrete type for this numeric value, \
342 format!("{snippet}_{concrete_type}"),
343 Applicability::MaybeIncorrect,
346 ExprKind::Path(QPath::Resolved(_, path)) => {
348 if let hir::def::Res::Local(hir_id) = path.res {
349 let span = tcx.hir().span(hir_id);
350 let snippet = tcx.sess.source_map().span_to_snippet(span);
351 let filename = tcx.sess.source_map().span_to_filename(span);
354 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
356 "you must specify a type for this binding, like `{}`",
360 match (filename, parent_node, snippet) {
363 Node::Local(hir::Local {
364 source: hir::LocalSource::Normal,
371 // account for `let x: _ = 42;`
378 format!("{}: {}", snippet, concrete_type),
379 Applicability::MaybeIncorrect,
383 err.span_label(span, msg);
393 span = item_name.span;
395 // Don't show generic arguments when the method can't be found in any implementation (#81576).
396 let mut ty_str_reported = ty_str.clone();
397 if let ty::Adt(_, generics) = actual.kind() {
398 if generics.len() > 0 {
399 let mut autoderef = self.autoderef(span, actual);
400 let candidate_found = autoderef.any(|(ty, _)| {
401 if let ty::Adt(adt_deref, _) = ty.kind() {
403 .inherent_impls(adt_deref.did())
405 .filter_map(|def_id| {
406 self.associated_value(*def_id, item_name)
414 let has_deref = autoderef.step_count() > 0;
417 && unsatisfied_predicates.is_empty()
419 if let Some((path_string, _)) = ty_str.split_once('<') {
420 ty_str_reported = path_string.to_string();
426 let mut err = struct_span_err!(
430 "no {} named `{}` found for {} `{}` in the current scope",
433 actual.prefix_string(self.tcx),
436 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
437 self.suggest_await_before_method(
438 &mut err, item_name, actual, cal, span,
442 tcx.resolutions(()).confused_type_with_std_module.get(&span)
444 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
447 "you are looking for the module in `std`, \
448 not the primitive type",
449 format!("std::{}", snippet),
450 Applicability::MachineApplicable,
454 if let ty::RawPtr(_) = &actual.kind() {
456 "try using `<*const T>::as_ref()` to get a reference to the \
457 type behind the pointer: https://doc.rust-lang.org/std/\
458 primitive.pointer.html#method.as_ref",
461 "using `<*const T>::as_ref()` on a pointer \
462 which is unaligned or points to invalid \
463 or uninitialized memory is undefined behavior",
470 if actual.references_error() {
471 err.downgrade_to_delayed_bug();
474 if let Some(def) = actual.ty_adt_def() {
475 if let Some(full_sp) = tcx.hir().span_if_local(def.did()) {
476 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
480 "{} `{}` not found {}",
483 if def.is_enum() && !is_method { "here" } else { "for this" }
489 if self.is_fn_ty(rcvr_ty, span) {
490 fn report_function<T: std::fmt::Display>(err: &mut Diagnostic, name: T) {
492 &format!("`{}` is a function, perhaps you wish to call it", name,),
496 if let SelfSource::MethodCall(expr) = source {
497 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
498 report_function(&mut err, expr_string);
499 } else if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind {
500 if let Some(segment) = path.segments.last() {
501 report_function(&mut err, segment.ident);
507 let mut custom_span_label = false;
509 if !static_sources.is_empty() {
511 "found the following associated functions; to be used as methods, \
512 functions must have a `self` parameter",
514 err.span_label(span, "this is an associated function, not a method");
515 custom_span_label = true;
517 if static_sources.len() == 1 {
518 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
519 static_sources.get(0)
521 // When the "method" is resolved through dereferencing, we really want the
522 // original type that has the associated function for accurate suggestions.
524 let ty = tcx.at(span).type_of(*impl_did);
525 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
526 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
527 // Use `actual` as it will have more `substs` filled in.
528 self.ty_to_value_string(actual.peel_refs())
530 _ => self.ty_to_value_string(ty.peel_refs()),
533 self.ty_to_value_string(actual.peel_refs())
535 if let SelfSource::MethodCall(expr) = source {
538 "use associated function syntax instead",
539 format!("{}::{}", ty_str, item_name),
540 Applicability::MachineApplicable,
543 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
546 report_candidates(span, &mut err, static_sources, sugg_span);
547 } else if static_sources.len() > 1 {
548 report_candidates(span, &mut err, static_sources, sugg_span);
551 let mut bound_spans = vec![];
552 let mut restrict_type_params = false;
553 let mut unsatisfied_bounds = false;
554 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
555 let msg = "consider using `len` instead";
556 if let SelfSource::MethodCall(_expr) = source {
557 err.span_suggestion_short(
561 Applicability::MachineApplicable,
564 err.span_label(span, msg);
566 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
567 let iterator_trait = self.tcx.def_path_str(iterator_trait);
568 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
570 } else if !unsatisfied_predicates.is_empty() {
571 let def_span = |def_id| {
572 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
574 let mut type_params = FxHashMap::default();
576 // Pick out the list of unimplemented traits on the receiver.
577 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
578 let mut unimplemented_traits = FxHashMap::default();
579 let mut unimplemented_traits_only = true;
580 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
581 if let (ty::PredicateKind::Trait(p), Some(cause)) =
582 (predicate.kind().skip_binder(), cause.as_ref())
584 if p.trait_ref.self_ty() != rcvr_ty {
585 // This is necessary, not just to keep the errors clean, but also
586 // because our derived obligations can wind up with a trait ref that
587 // requires a different param_env to be correctly compared.
590 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
591 predicate.kind().rebind(p.trait_ref),
593 cause: cause.clone(),
594 param_env: self.param_env,
595 predicate: predicate.clone(),
602 // Make sure that, if any traits other than the found ones were involved,
603 // we don't don't report an unimplemented trait.
604 // We don't want to say that `iter::Cloned` is not an iterator, just
605 // because of some non-Clone item being iterated over.
606 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
607 match predicate.kind().skip_binder() {
608 ty::PredicateKind::Trait(p)
609 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
611 unimplemented_traits_only = false;
617 let mut collect_type_param_suggestions =
618 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
619 // We don't care about regions here, so it's fine to skip the binder here.
620 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
621 (self_ty.kind(), parent_pred.kind().skip_binder())
623 let node = match p.trait_ref.self_ty().kind() {
625 // Account for `fn` items like in `issue-35677.rs` to
626 // suggest restricting its type params.
627 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
628 hir_id: self.body_id,
633 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
636 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
639 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
643 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
644 if let Some(g) = kind.generics() {
645 let key = match g.where_clause.predicates {
646 [.., pred] => (pred.span().shrink_to_hi(), false),
648 g.where_clause.span_for_predicates_or_empty_place(),
654 .or_insert_with(FxHashSet::default)
655 .insert(obligation.to_owned());
660 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
662 "doesn't satisfy `{}`",
663 if obligation.len() > 50 { quiet } else { obligation }
665 match &self_ty.kind() {
666 // Point at the type that couldn't satisfy the bound.
667 ty::Adt(def, _) => bound_spans.push((def_span(def.did()), msg)),
668 // Point at the trait object that couldn't satisfy the bound.
669 ty::Dynamic(preds, _) => {
670 for pred in preds.iter() {
671 match pred.skip_binder() {
672 ty::ExistentialPredicate::Trait(tr) => {
673 bound_spans.push((def_span(tr.def_id), msg.clone()))
675 ty::ExistentialPredicate::Projection(_)
676 | ty::ExistentialPredicate::AutoTrait(_) => {}
680 // Point at the closure that couldn't satisfy the bound.
681 ty::Closure(def_id, _) => bound_spans
682 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
686 let mut format_pred = |pred: ty::Predicate<'tcx>| {
687 let bound_predicate = pred.kind();
688 match bound_predicate.skip_binder() {
689 ty::PredicateKind::Projection(pred) => {
690 let pred = bound_predicate.rebind(pred);
691 // `<Foo as Iterator>::Item = String`.
692 let projection_ty = pred.skip_binder().projection_ty;
694 let substs_with_infer_self = tcx.mk_substs(
695 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
696 .chain(projection_ty.substs.iter().skip(1)),
699 let quiet_projection_ty = ty::ProjectionTy {
700 substs: substs_with_infer_self,
701 item_def_id: projection_ty.item_def_id,
704 let term = pred.skip_binder().term;
706 let obligation = format!("{} = {}", projection_ty, term);
707 let quiet = format!("{} = {}", quiet_projection_ty, term);
709 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
710 Some((obligation, projection_ty.self_ty()))
712 ty::PredicateKind::Trait(poly_trait_ref) => {
713 let p = poly_trait_ref.trait_ref;
714 let self_ty = p.self_ty();
715 let path = p.print_only_trait_path();
716 let obligation = format!("{}: {}", self_ty, path);
717 let quiet = format!("_: {}", path);
718 bound_span_label(self_ty, &obligation, &quiet);
719 Some((obligation, self_ty))
725 // Find all the requirements that come from a local `impl` block.
726 let mut skip_list: FxHashSet<_> = Default::default();
727 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
728 for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates
730 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
731 .filter_map(|(p, parent, c)| match c.code() {
732 ObligationCauseCode::ImplDerivedObligation(ref data) => {
733 Some((&data.derived, p, parent, data.impl_def_id, data.span))
738 let parent_trait_ref = data.parent_trait_pred;
739 let path = parent_trait_ref.print_modifiers_and_trait_path();
740 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
741 let unsatisfied_msg = "unsatisfied trait bound introduced here".to_string();
743 "unsatisfied trait bound introduced in this `derive` macro";
744 match self.tcx.hir().get_if_local(impl_def_id) {
745 // Unmet obligation comes from a `derive` macro, point at it once to
746 // avoid multiple span labels pointing at the same place.
747 Some(Node::Item(hir::Item {
748 kind: hir::ItemKind::Trait(..),
752 ident.span.ctxt().outer_expn_data().kind,
753 ExpnKind::Macro(MacroKind::Derive, _)
756 let span = ident.span.ctxt().outer_expn_data().call_site;
757 let mut spans: MultiSpan = span.into();
758 spans.push_span_label(span, derive_msg.to_string());
759 let entry = spanned_predicates.entry(spans);
760 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
763 Some(Node::Item(hir::Item {
764 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
767 self_ty.span.ctxt().outer_expn_data().kind,
768 ExpnKind::Macro(MacroKind::Derive, _)
770 of_trait.as_ref().map(|t| t
776 Some(ExpnKind::Macro(MacroKind::Derive, _))
779 let span = self_ty.span.ctxt().outer_expn_data().call_site;
780 let mut spans: MultiSpan = span.into();
781 spans.push_span_label(span, derive_msg.to_string());
782 let entry = spanned_predicates.entry(spans.into());
783 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
786 // Unmet obligation coming from a `trait`.
787 Some(Node::Item(hir::Item {
788 kind: hir::ItemKind::Trait(..),
793 ident.span.ctxt().outer_expn_data().kind,
794 ExpnKind::Macro(MacroKind::Derive, _)
797 if let Some(pred) = parent_p {
798 // Done to add the "doesn't satisfy" `span_label`.
799 let _ = format_pred(*pred);
802 let mut spans = if cause_span != *item_span {
803 let mut spans: MultiSpan = cause_span.into();
804 spans.push_span_label(cause_span, unsatisfied_msg);
809 spans.push_span_label(ident.span, "in this trait".to_string());
810 let entry = spanned_predicates.entry(spans.into());
811 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
814 // Unmet obligation coming from an `impl`.
815 Some(Node::Item(hir::Item {
816 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
820 self_ty.span.ctxt().outer_expn_data().kind,
821 ExpnKind::Macro(MacroKind::Derive, _)
823 of_trait.as_ref().map(|t| t
829 Some(ExpnKind::Macro(MacroKind::Derive, _))
832 if let Some(pred) = parent_p {
833 // Done to add the "doesn't satisfy" `span_label`.
834 let _ = format_pred(*pred);
837 let mut spans = if cause_span != *item_span {
838 let mut spans: MultiSpan = cause_span.into();
839 spans.push_span_label(cause_span, unsatisfied_msg);
842 let mut spans = Vec::with_capacity(2);
843 if let Some(trait_ref) = of_trait {
844 spans.push(trait_ref.path.span);
846 spans.push(self_ty.span);
849 if let Some(trait_ref) = of_trait {
850 spans.push_span_label(trait_ref.path.span, String::new());
852 spans.push_span_label(self_ty.span, String::new());
854 let entry = spanned_predicates.entry(spans.into());
855 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
860 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
861 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
862 for (span, (_path, _self_ty, preds)) in spanned_predicates {
863 let mut preds: Vec<_> = preds
865 .filter_map(|pred| format_pred(*pred))
866 .map(|(p, _)| format!("`{}`", p))
870 let msg = if let [pred] = &preds[..] {
871 format!("trait bound {} was not satisfied", pred)
874 "the following trait bounds were not satisfied:\n{}",
878 err.span_note(span, &msg);
879 unsatisfied_bounds = true;
882 // The requirements that didn't have an `impl` span to show.
883 let mut bound_list = unsatisfied_predicates
885 .filter_map(|(pred, parent_pred, _cause)| {
886 format_pred(*pred).map(|(p, self_ty)| {
887 collect_type_param_suggestions(self_ty, *pred, &p);
890 None => format!("`{}`", &p),
891 Some(parent_pred) => match format_pred(*parent_pred) {
892 None => format!("`{}`", &p),
893 Some((parent_p, _)) => {
894 collect_type_param_suggestions(
900 "`{}`\nwhich is required by `{}`",
910 .filter(|(_, pred)| !skip_list.contains(&pred))
913 .collect::<Vec<(usize, String)>>();
915 for ((span, empty_where), obligations) in type_params.into_iter() {
916 restrict_type_params = true;
917 // #74886: Sort here so that the output is always the same.
918 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
920 err.span_suggestion_verbose(
923 "consider restricting the type parameter{s} to satisfy the \
925 s = pluralize!(obligations.len())
929 if empty_where { " where" } else { "," },
930 obligations.join(", ")
932 Applicability::MaybeIncorrect,
936 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
937 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
938 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
940 if !bound_list.is_empty() || !skip_list.is_empty() {
941 let bound_list = bound_list
943 .map(|(_, path)| path)
946 let actual_prefix = actual.prefix_string(self.tcx);
947 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
948 let (primary_message, label) = if unimplemented_traits.len() == 1
949 && unimplemented_traits_only
954 .map(|(_, (trait_ref, obligation))| {
955 if trait_ref.self_ty().references_error()
956 || actual.references_error()
961 let OnUnimplementedNote { message, label, .. } =
962 self.infcx.on_unimplemented_note(trait_ref, &obligation);
965 .unwrap_or((None, None))
969 let primary_message = primary_message.unwrap_or_else(|| format!(
970 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
972 err.set_primary_message(&primary_message);
973 if let Some(label) = label {
974 custom_span_label = true;
975 err.span_label(span, label);
977 if !bound_list.is_empty() {
979 "the following trait bounds were not satisfied:\n{bound_list}"
982 self.suggest_derive(&mut err, &unsatisfied_predicates);
984 unsatisfied_bounds = true;
988 let mut label_span_not_found = || {
989 if unsatisfied_predicates.is_empty() {
990 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
991 let is_string_or_ref_str = match actual.kind() {
992 ty::Ref(_, ty, _) => {
996 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
999 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
1002 if is_string_or_ref_str && item_name.name == sym::iter {
1003 err.span_suggestion_verbose(
1005 "because of the in-memory representation of `&str`, to obtain \
1006 an `Iterator` over each of its codepoint use method `chars`",
1007 String::from("chars"),
1008 Applicability::MachineApplicable,
1011 if let ty::Adt(adt, _) = rcvr_ty.kind() {
1012 let mut inherent_impls_candidate = self
1014 .inherent_impls(adt.did())
1018 if let Some(assoc) = self.associated_value(*def_id, item_name) {
1019 // Check for both mode is the same so we avoid suggesting
1020 // incorrect associated item.
1021 match (mode, assoc.fn_has_self_parameter, source) {
1022 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
1023 // We check that the suggest type is actually
1024 // different from the received one
1025 // So we avoid suggestion method with Box<Self>
1027 self.tcx.at(span).type_of(*def_id) != actual
1028 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
1030 (Mode::Path, false, _) => true,
1037 .collect::<Vec<_>>();
1038 if !inherent_impls_candidate.is_empty() {
1039 inherent_impls_candidate.sort();
1040 inherent_impls_candidate.dedup();
1042 // number of type to shows at most.
1043 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
1044 let type_candidates = inherent_impls_candidate
1048 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
1050 .collect::<Vec<_>>()
1052 let additional_types = if inherent_impls_candidate.len() > limit {
1054 "\nand {} more types",
1055 inherent_impls_candidate.len() - limit
1061 "the {item_kind} was found for\n{}{}",
1062 type_candidates, additional_types
1067 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
1071 // If the method name is the name of a field with a function or closure type,
1072 // give a helping note that it has to be called as `(x.f)(...)`.
1073 if let SelfSource::MethodCall(expr) = source {
1074 let field_receiver =
1075 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1076 ty::Adt(def, substs) if !def.is_enum() => {
1077 let variant = &def.non_enum_variant();
1078 self.tcx.find_field_index(item_name, variant).map(|index| {
1079 let field = &variant.fields[index];
1080 let field_ty = field.ty(tcx, substs);
1087 if let Some((field, field_ty)) = field_receiver {
1088 let scope = self.tcx.parent_module(self.body_id).to_def_id();
1089 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
1092 if self.is_fn_ty(field_ty, span) {
1093 let expr_span = expr.span.to(item_name.span);
1094 err.multipart_suggestion(
1096 "to call the function stored in `{}`, \
1097 surround the field access with parentheses",
1101 (expr_span.shrink_to_lo(), '('.to_string()),
1102 (expr_span.shrink_to_hi(), ')'.to_string()),
1104 Applicability::MachineApplicable,
1107 let call_expr = self
1110 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1112 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1113 err.span_suggestion(
1115 "remove the arguments",
1117 Applicability::MaybeIncorrect,
1123 let field_kind = if is_accessible { "field" } else { "private field" };
1124 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1125 } else if lev_candidate.is_none() && !custom_span_label {
1126 label_span_not_found();
1128 } else if !custom_span_label {
1129 label_span_not_found();
1133 bound_spans.dedup();
1134 for (span, msg) in bound_spans.into_iter() {
1135 err.span_label(span, &msg);
1138 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
1140 self.suggest_traits_to_import(
1146 out_of_scope_traits,
1147 &unsatisfied_predicates,
1152 // Don't emit a suggestion if we found an actual method
1153 // that had unsatisfied trait bounds
1154 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1155 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1156 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1157 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1161 err.span_suggestion(
1163 "there is a variant with a similar name",
1164 suggestion.to_string(),
1165 Applicability::MaybeIncorrect,
1170 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1171 let msg = "remove this method call";
1172 let mut fallback_span = true;
1173 if let SelfSource::MethodCall(expr) = source {
1175 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1176 if let Some(span) = call_expr.span.trim_start(expr.span) {
1177 err.span_suggestion(
1181 Applicability::MachineApplicable,
1183 fallback_span = false;
1187 err.span_label(span, msg);
1189 } else if let Some(lev_candidate) = lev_candidate {
1190 // Don't emit a suggestion if we found an actual method
1191 // that had unsatisfied trait bounds
1192 if unsatisfied_predicates.is_empty() {
1193 let def_kind = lev_candidate.kind.as_def_kind();
1194 err.span_suggestion(
1197 "there is {} {} with a similar name",
1199 def_kind.descr(lev_candidate.def_id),
1201 lev_candidate.name.to_string(),
1202 Applicability::MaybeIncorrect,
1210 MethodError::Ambiguity(sources) => {
1211 let mut err = struct_span_err!(
1215 "multiple applicable items in scope"
1217 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1219 report_candidates(span, &mut err, sources, sugg_span);
1223 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1224 let kind = kind.descr(def_id);
1225 let mut err = struct_span_err!(
1229 "{} `{}` is private",
1233 err.span_label(item_name.span, &format!("private {}", kind));
1237 .span_if_local(def_id)
1238 .unwrap_or_else(|| self.tcx.def_span(def_id));
1239 err.span_label(sp, &format!("private {} defined here", kind));
1240 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1244 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1245 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1246 let mut err = self.sess().struct_span_err(span, &msg);
1247 err.span_label(bound_span, "this has a `Sized` requirement");
1248 if !candidates.is_empty() {
1250 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1251 add a `use` for {one_of_them}:",
1252 an = if candidates.len() == 1 { "an" } else { "" },
1253 s = pluralize!(candidates.len()),
1254 were = if candidates.len() == 1 { "was" } else { "were" },
1255 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1257 self.suggest_use_candidates(&mut err, help, candidates);
1259 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1261 let trait_type = self.tcx.mk_ref(
1263 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1265 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1271 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1276 crate fn note_unmet_impls_on_type(
1278 err: &mut Diagnostic,
1279 errors: Vec<FulfillmentError<'tcx>>,
1281 let all_local_types_needing_impls =
1282 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1283 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1284 ty::Adt(def, _) => def.did().is_local(),
1289 let mut preds: Vec<_> = errors
1291 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1292 ty::PredicateKind::Trait(pred) => Some(pred),
1296 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1299 .filter_map(|pred| match pred.self_ty().kind() {
1300 ty::Adt(def, _) => Some(def.did()),
1303 .collect::<FxHashSet<_>>();
1304 let sm = self.tcx.sess.source_map();
1305 let mut spans: MultiSpan = def_ids
1307 .filter_map(|def_id| {
1308 let span = self.tcx.def_span(*def_id);
1309 if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) }
1311 .collect::<Vec<_>>()
1314 for pred in &preds {
1315 match pred.self_ty().kind() {
1316 ty::Adt(def, _) => {
1317 spans.push_span_label(
1318 sm.guess_head_span(self.tcx.def_span(def.did())),
1319 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1326 if all_local_types_needing_impls && spans.primary_span().is_some() {
1327 let msg = if preds.len() == 1 {
1329 "an implementation of `{}` might be missing for `{}`",
1330 preds[0].trait_ref.print_only_trait_path(),
1335 "the following type{} would have to `impl` {} required trait{} for this \
1336 operation to be valid",
1337 pluralize!(def_ids.len()),
1338 if def_ids.len() == 1 { "its" } else { "their" },
1339 pluralize!(preds.len()),
1342 err.span_note(spans, &msg);
1345 let preds: Vec<_> = errors
1347 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1349 self.suggest_derive(err, &preds);
1354 err: &mut Diagnostic,
1355 unsatisfied_predicates: &[(
1356 ty::Predicate<'tcx>,
1357 Option<ty::Predicate<'tcx>>,
1358 Option<ObligationCause<'tcx>>,
1361 let mut derives = Vec::<(String, Span, String)>::new();
1362 let mut traits = Vec::<Span>::new();
1363 for (pred, _, _) in unsatisfied_predicates {
1364 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1365 let adt = match trait_pred.self_ty().ty_adt_def() {
1366 Some(adt) if adt.did().is_local() => adt,
1369 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1370 let can_derive = match diagnostic_name {
1371 sym::Default => !adt.is_enum(),
1379 | sym::Debug => true,
1383 let self_name = trait_pred.self_ty().to_string();
1384 let self_span = self.tcx.def_span(adt.did());
1385 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1386 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1388 if let Some(parent_diagnostic_name) =
1389 self.tcx.get_diagnostic_name(super_trait.def_id())
1394 parent_diagnostic_name.to_string(),
1399 derives.push((self_name, self_span, diagnostic_name.to_string()));
1401 traits.push(self.tcx.def_span(trait_pred.def_id()));
1404 traits.push(self.tcx.def_span(trait_pred.def_id()));
1413 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1414 for (self_name, self_span, trait_name) in derives.into_iter() {
1415 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1417 if last_self_name == &self_name {
1418 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1422 derives_grouped.push((self_name, self_span, trait_name));
1425 let len = traits.len();
1427 let span: MultiSpan = traits.into();
1430 &format!("the following trait{} must be implemented", pluralize!(len),),
1434 for (self_name, self_span, traits) in &derives_grouped {
1435 err.span_suggestion_verbose(
1436 self_span.shrink_to_lo(),
1437 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1438 format!("#[derive({})]\n", traits),
1439 Applicability::MaybeIncorrect,
1444 /// Print out the type for use in value namespace.
1445 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1447 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1448 _ => self.ty_to_string(ty),
1452 fn suggest_await_before_method(
1454 err: &mut Diagnostic,
1457 call: &hir::Expr<'_>,
1460 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
1461 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1464 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1465 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1467 err.span_suggestion_verbose(
1468 span.shrink_to_lo(),
1469 "consider `await`ing on the `Future` and calling the method on its `Output`",
1470 "await.".to_string(),
1471 Applicability::MaybeIncorrect,
1476 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1477 let parent_map = self.tcx.visible_parent_map(());
1479 // Separate out candidates that must be imported with a glob, because they are named `_`
1480 // and cannot be referred with their identifier.
1481 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1482 if let Some(parent_did) = parent_map.get(trait_did) {
1483 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1484 if Some(*parent_did) != self.tcx.parent(*trait_did)
1487 .module_children(*parent_did)
1489 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1490 .all(|child| child.ident.name == kw::Underscore)
1499 let module_did = self.tcx.parent_module(self.body_id);
1500 let (module, _, _) = self.tcx.hir().get_module(module_did);
1501 let span = module.spans.inject_use_span;
1503 let path_strings = candidates.iter().map(|trait_did| {
1504 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1507 let glob_path_strings = globs.iter().map(|trait_did| {
1508 let parent_did = parent_map.get(trait_did).unwrap();
1510 "use {}::*; // trait {}\n",
1511 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1512 self.tcx.item_name(*trait_did),
1516 err.span_suggestions(
1519 path_strings.chain(glob_path_strings),
1520 Applicability::MaybeIncorrect,
1524 fn suggest_valid_traits(
1526 err: &mut Diagnostic,
1527 valid_out_of_scope_traits: Vec<DefId>,
1529 if !valid_out_of_scope_traits.is_empty() {
1530 let mut candidates = valid_out_of_scope_traits;
1534 // `TryFrom` and `FromIterator` have no methods
1535 let edition_fix = candidates
1537 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1540 err.help("items from traits can only be used if the trait is in scope");
1542 "the following {traits_are} implemented but not in scope; \
1543 perhaps add a `use` for {one_of_them}:",
1544 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1545 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1548 self.suggest_use_candidates(err, msg, candidates);
1549 if let Some(did) = edition_fix {
1551 "'{}' is included in the prelude starting in Edition 2021",
1552 with_crate_prefix!(self.tcx.def_path_str(did))
1562 fn suggest_traits_to_import(
1564 err: &mut Diagnostic,
1568 source: SelfSource<'tcx>,
1569 valid_out_of_scope_traits: Vec<DefId>,
1570 unsatisfied_predicates: &[(
1571 ty::Predicate<'tcx>,
1572 Option<ty::Predicate<'tcx>>,
1573 Option<ObligationCause<'tcx>>,
1575 unsatisfied_bounds: bool,
1577 let mut alt_rcvr_sugg = false;
1578 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1579 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1581 self.tcx.lang_items().clone_trait(),
1582 self.tcx.lang_items().deref_trait(),
1583 self.tcx.lang_items().deref_mut_trait(),
1584 self.tcx.lang_items().drop_trait(),
1585 self.tcx.get_diagnostic_item(sym::AsRef),
1587 // Try alternative arbitrary self types that could fulfill this call.
1588 // FIXME: probe for all types that *could* be arbitrary self-types, not
1590 for (rcvr_ty, post) in &[
1592 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1593 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1595 match self.lookup_probe(
1600 crate::check::method::probe::ProbeScope::AllTraits,
1603 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1604 // We point at the method, but we just skip the rest of the check for arbitrary
1605 // self types and rely on the suggestion to `use` the trait from
1606 // `suggest_valid_traits`.
1607 let did = Some(pick.item.container.id());
1608 let skip = skippable.contains(&did);
1609 if pick.autoderefs == 0 && !skip {
1611 pick.item.ident(self.tcx).span,
1612 &format!("the method is available for `{}` here", rcvr_ty),
1617 Err(MethodError::Ambiguity(_)) => {
1618 // If the method is defined (but ambiguous) for the receiver we have, it is also
1619 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1620 // the receiver, then it might disambiguate this method, but I think these
1621 // suggestions are generally misleading (see #94218).
1627 for (rcvr_ty, pre) in &[
1628 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1629 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1630 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1631 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1633 if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe(
1638 crate::check::method::probe::ProbeScope::AllTraits,
1640 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1641 let did = Some(pick.item.container.id());
1642 // We don't want to suggest a container type when the missing
1643 // method is `.clone()` or `.deref()` otherwise we'd suggest
1644 // `Arc::new(foo).clone()`, which is far from what the user wants.
1645 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1646 // implement the `AsRef` trait.
1647 let skip = skippable.contains(&did)
1648 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
1649 // Make sure the method is defined for the *actual* receiver: we don't
1650 // want to treat `Box<Self>` as a receiver if it only works because of
1651 // an autoderef to `&self`
1652 if pick.autoderefs == 0 && !skip {
1654 pick.item.ident(self.tcx).span,
1655 &format!("the method is available for `{}` here", new_rcvr_t),
1657 err.multipart_suggestion(
1658 "consider wrapping the receiver expression with the \
1661 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1662 (rcvr.span.shrink_to_hi(), ")".to_string()),
1664 Applicability::MaybeIncorrect,
1666 // We don't care about the other suggestions.
1667 alt_rcvr_sugg = true;
1673 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1677 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1679 let mut arbitrary_rcvr = vec![];
1680 // There are no traits implemented, so lets suggest some traits to
1681 // implement, by finding ones that have the item name, and are
1682 // legal to implement.
1683 let mut candidates = all_traits(self.tcx)
1685 // Don't issue suggestions for unstable traits since they're
1686 // unlikely to be implementable anyway
1687 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1688 Some(attr) => attr.level.is_stable(),
1692 // We approximate the coherence rules to only suggest
1693 // traits that are legal to implement by requiring that
1694 // either the type or trait is local. Multi-dispatch means
1695 // this isn't perfect (that is, there are cases when
1696 // implementing a trait would be legal but is rejected
1698 unsatisfied_predicates.iter().all(|(p, _, _)| {
1699 match p.kind().skip_binder() {
1700 // Hide traits if they are present in predicates as they can be fixed without
1701 // having to implement them.
1702 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1703 ty::PredicateKind::Projection(p) => {
1704 p.projection_ty.item_def_id == info.def_id
1708 }) && (type_is_local || info.def_id.is_local())
1710 .associated_value(info.def_id, item_name)
1712 if let ty::AssocKind::Fn = item.kind {
1716 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1717 if let Some(hir::Node::TraitItem(hir::TraitItem {
1718 kind: hir::TraitItemKind::Fn(fn_sig, method),
1720 })) = id.map(|id| self.tcx.hir().get(id))
1722 let self_first_arg = match method {
1723 hir::TraitFn::Required([ident, ..]) => {
1724 ident.name == kw::SelfLower
1726 hir::TraitFn::Provided(body_id) => {
1727 self.tcx.hir().body(*body_id).params.first().map_or(
1732 hir::PatKind::Binding(_, _, ident, _)
1733 if ident.name == kw::SelfLower
1741 if !fn_sig.decl.implicit_self.has_implicit_self()
1744 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1745 arbitrary_rcvr.push(ty.span);
1751 // We only want to suggest public or local traits (#45781).
1752 item.vis.is_public() || info.def_id.is_local()
1756 .collect::<Vec<_>>();
1757 for span in &arbitrary_rcvr {
1760 "the method might not be found because of this arbitrary self type",
1767 if !candidates.is_empty() {
1768 // Sort from most relevant to least relevant.
1769 candidates.sort_by(|a, b| a.cmp(b).reverse());
1772 let param_type = match rcvr_ty.kind() {
1773 ty::Param(param) => Some(param),
1774 ty::Ref(_, ty, _) => match ty.kind() {
1775 ty::Param(param) => Some(param),
1780 err.help(if param_type.is_some() {
1781 "items from traits can only be used if the type parameter is bounded by the trait"
1783 "items from traits can only be used if the trait is implemented and in scope"
1785 let candidates_len = candidates.len();
1786 let message = |action| {
1788 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1791 if candidates_len == 1 { "trait defines" } else { "traits define" },
1793 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1797 // Obtain the span for `param` and use it for a structured suggestion.
1798 if let (Some(param), Some(table)) = (param_type, self.in_progress_typeck_results) {
1799 let table_owner = table.borrow().hir_owner;
1800 let generics = self.tcx.generics_of(table_owner.to_def_id());
1801 let type_param = generics.type_param(param, self.tcx);
1802 let hir = self.tcx.hir();
1803 if let Some(def_id) = type_param.def_id.as_local() {
1804 let id = hir.local_def_id_to_hir_id(def_id);
1805 // Get the `hir::Param` to verify whether it already has any bounds.
1806 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1807 // instead we suggest `T: Foo + Bar` in that case.
1809 Node::GenericParam(param) => {
1810 let mut impl_trait = false;
1812 if let hir::GenericParamKind::Type { synthetic: true, .. } =
1815 // We've found `fn foo(x: impl Trait)` instead of
1816 // `fn foo<T>(x: T)`. We want to suggest the correct
1817 // `fn foo(x: impl Trait + TraitBound)` instead of
1818 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1824 let sp = hir.span(id);
1825 let sp = if let Some(first_bound) = has_bounds {
1826 // `sp` only covers `T`, change it so that it covers
1827 // `T:` when appropriate
1828 sp.until(first_bound.span())
1832 let trait_def_ids: FxHashSet<DefId> = param
1835 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1837 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1838 err.span_suggestions(
1841 "restrict type parameter `{}` with",
1844 candidates.iter().map(|t| {
1848 if impl_trait { " +" } else { ":" },
1849 self.tcx.def_path_str(t.def_id),
1850 if has_bounds.is_some() { " + " } else { "" },
1853 Applicability::MaybeIncorrect,
1858 Node::Item(hir::Item {
1859 kind: hir::ItemKind::Trait(.., bounds, _),
1863 let (sp, sep, article) = if bounds.is_empty() {
1864 (ident.span.shrink_to_hi(), ":", "a")
1866 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1868 err.span_suggestions(
1870 &message(format!("add {} supertrait for", article)),
1871 candidates.iter().map(|t| {
1872 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1874 Applicability::MaybeIncorrect,
1883 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1884 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1885 // cases where a positive bound implies a negative impl.
1886 (candidates, Vec::new())
1887 } else if let Some(simp_rcvr_ty) =
1888 simplify_type(self.tcx, rcvr_ty, TreatParams::AsBoundTypes)
1890 let mut potential_candidates = Vec::new();
1891 let mut explicitly_negative = Vec::new();
1892 for candidate in candidates {
1893 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1896 .all_impls(candidate.def_id)
1898 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1901 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1903 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsBoundTypes);
1904 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1907 explicitly_negative.push(candidate);
1909 potential_candidates.push(candidate);
1912 (potential_candidates, explicitly_negative)
1914 // We don't know enough about `recv_ty` to make proper suggestions.
1915 (candidates, Vec::new())
1918 let action = if let Some(param) = param_type {
1919 format!("restrict type parameter `{}` with", param)
1921 // FIXME: it might only need to be imported into scope, not implemented.
1922 "implement".to_string()
1924 match &potential_candidates[..] {
1926 [trait_info] if trait_info.def_id.is_local() => {
1927 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1929 self.tcx.sess.source_map().guess_head_span(span),
1931 "`{}` defines an item `{}`, perhaps you need to {} it",
1932 self.tcx.def_path_str(trait_info.def_id),
1939 let mut msg = message(action);
1940 for (i, trait_info) in trait_infos.iter().enumerate() {
1941 msg.push_str(&format!(
1942 "\ncandidate #{}: `{}`",
1944 self.tcx.def_path_str(trait_info.def_id),
1950 match &explicitly_negative[..] {
1954 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
1955 self.tcx.def_path_str(trait_info.def_id),
1961 let mut msg = format!(
1962 "the following traits define an item `{}`, but are explicitly unimplemented:",
1965 for trait_info in trait_infos {
1966 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1974 /// Checks whether there is a local type somewhere in the chain of
1975 /// autoderefs of `rcvr_ty`.
1976 fn type_derefs_to_local(
1980 source: SelfSource<'tcx>,
1982 fn is_local(ty: Ty<'_>) -> bool {
1984 ty::Adt(def, _) => def.did().is_local(),
1985 ty::Foreign(did) => did.is_local(),
1986 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1987 ty::Param(_) => true,
1989 // Everything else (primitive types, etc.) is effectively
1990 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1991 // the noise from these sort of types is usually just really
1992 // annoying, rather than any sort of help).
1997 // This occurs for UFCS desugaring of `T::method`, where there is no
1998 // receiver expression for the method call, and thus no autoderef.
1999 if let SelfSource::QPath(_) = source {
2000 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2003 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2007 #[derive(Copy, Clone, Debug)]
2008 pub enum SelfSource<'a> {
2009 QPath(&'a hir::Ty<'a>),
2010 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2013 #[derive(Copy, Clone)]
2014 pub struct TraitInfo {
2018 impl PartialEq for TraitInfo {
2019 fn eq(&self, other: &TraitInfo) -> bool {
2020 self.cmp(other) == Ordering::Equal
2023 impl Eq for TraitInfo {}
2024 impl PartialOrd for TraitInfo {
2025 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2026 Some(self.cmp(other))
2029 impl Ord for TraitInfo {
2030 fn cmp(&self, other: &TraitInfo) -> Ordering {
2031 // Local crates are more important than remote ones (local:
2032 // `cnum == 0`), and otherwise we throw in the defid for totality.
2034 let lhs = (other.def_id.krate, other.def_id);
2035 let rhs = (self.def_id.krate, self.def_id);
2040 /// Retrieves all traits in this crate and any dependent crates,
2041 /// and wraps them into `TraitInfo` for custom sorting.
2042 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2043 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2046 fn print_disambiguation_help<'tcx>(
2048 args: Option<&'tcx [hir::Expr<'tcx>]>,
2049 err: &mut Diagnostic,
2052 kind: ty::AssocKind,
2055 candidate: Option<usize>,
2056 source_map: &source_map::SourceMap,
2057 fn_has_self_parameter: bool,
2059 let mut applicability = Applicability::MachineApplicable;
2060 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
2063 if rcvr_ty.is_region_ptr() {
2064 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2069 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2070 applicability = Applicability::HasPlaceholders;
2073 .collect::<Vec<_>>()
2076 let trait_name = if !fn_has_self_parameter {
2077 format!("<{} as {}>", rcvr_ty, trait_name)
2081 (span, format!("{}::{}{}", trait_name, item_name, args))
2083 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2085 err.span_suggestion_verbose(
2088 "disambiguate the {} for {}",
2089 kind.as_def_kind().descr(def_id),
2090 if let Some(candidate) = candidate {
2091 format!("candidate #{}", candidate)
2093 "the candidate".to_string()