1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
4 use crate::check::FnCtxt;
5 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
11 use rustc_hir::def::DefKind;
12 use rustc_hir::def_id::DefId;
13 use rustc_hir::lang_items::LangItem;
14 use rustc_hir::{ExprKind, Node, QPath};
15 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
16 use rustc_middle::traits::util::supertraits;
17 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
18 use rustc_middle::ty::print::with_crate_prefix;
19 use rustc_middle::ty::ToPolyTraitRef;
20 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
21 use rustc_span::symbol::{kw, sym, Ident};
22 use rustc_span::Symbol;
23 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
24 use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
25 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
26 use rustc_trait_selection::traits::{
27 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
30 use std::cmp::Ordering;
33 use super::probe::{Mode, ProbeScope};
34 use super::{super::suggest_call_constructor, CandidateSource, MethodError, NoMatchData};
36 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
40 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
41 // so we look for these beforehand.
42 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
43 // If it's not a simple function, look for things which implement `FnOnce`.
45 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
49 // This conditional prevents us from asking to call errors and unresolved types.
50 // It might seem that we can use `predicate_must_hold_modulo_regions`,
51 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
52 // type resolution always gives a "maybe" here.
53 if self.autoderef(span, ty).any(|(ty, _)| {
54 info!("check deref {:?} error", ty);
55 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
60 self.autoderef(span, ty).any(|(ty, _)| {
61 info!("check deref {:?} impl FnOnce", ty);
63 let fn_once_substs = tcx.mk_substs_trait(
66 .next_ty_var(TypeVariableOrigin {
67 kind: TypeVariableOriginKind::MiscVariable,
72 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
73 let poly_trait_ref = ty::Binder::dummy(trait_ref);
74 let obligation = Obligation::misc(
78 poly_trait_ref.without_const().to_predicate(tcx),
80 self.predicate_may_hold(&obligation)
87 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
88 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
91 pub fn report_method_error(
96 source: SelfSource<'tcx>,
97 error: MethodError<'tcx>,
98 args: Option<&'tcx [hir::Expr<'tcx>]>,
99 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
100 // Avoid suggestions when we don't know what's going on.
101 if rcvr_ty.references_error() {
105 let report_candidates = |span: Span,
106 err: &mut Diagnostic,
107 mut sources: Vec<CandidateSource>,
111 // Dynamic limit to avoid hiding just one candidate, which is silly.
112 let limit = if sources.len() == 5 { 5 } else { 4 };
114 for (idx, source) in sources.iter().take(limit).enumerate() {
116 CandidateSource::Impl(impl_did) => {
117 // Provide the best span we can. Use the item, if local to crate, else
118 // the impl, if local to crate (item may be defaulted), else nothing.
119 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
120 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
121 self.associated_value(impl_trait_ref.def_id, item_name)
126 let note_span = if item.def_id.is_local() {
127 Some(self.tcx.def_span(item.def_id))
128 } else if impl_did.is_local() {
129 Some(self.tcx.def_span(impl_did))
134 let impl_ty = self.tcx.at(span).type_of(impl_did);
136 let insertion = match self.tcx.impl_trait_ref(impl_did) {
137 None => String::new(),
138 Some(trait_ref) => format!(
139 " of the trait `{}`",
140 self.tcx.def_path_str(trait_ref.def_id)
144 let (note_str, idx) = if sources.len() > 1 {
147 "candidate #{} is defined in an impl{} for the type `{}`",
157 "the candidate is defined in an impl{} for the type `{}`",
163 if let Some(note_span) = note_span {
164 // We have a span pointing to the method. Show note with snippet.
165 err.span_note(note_span, ¬e_str);
169 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
170 let path = self.tcx.def_path_str(trait_ref.def_id);
172 let ty = match item.kind {
173 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
174 ty::AssocKind::Fn => self
180 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
184 print_disambiguation_help(
194 self.tcx.sess.source_map(),
195 item.fn_has_self_parameter,
199 CandidateSource::Trait(trait_did) => {
200 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
201 let item_span = self.tcx.def_span(item.def_id);
202 let idx = if sources.len() > 1 {
204 "candidate #{} is defined in the trait `{}`",
206 self.tcx.def_path_str(trait_did)
208 err.span_note(item_span, msg);
212 "the candidate is defined in the trait `{}`",
213 self.tcx.def_path_str(trait_did)
215 err.span_note(item_span, msg);
218 let path = self.tcx.def_path_str(trait_did);
219 print_disambiguation_help(
229 self.tcx.sess.source_map(),
230 item.fn_has_self_parameter,
235 if sources.len() > limit {
236 err.note(&format!("and {} others", sources.len() - limit));
240 let sugg_span = if let SelfSource::MethodCall(expr) = source {
241 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
242 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
248 MethodError::NoMatch(NoMatchData {
249 static_candidates: static_sources,
250 unsatisfied_predicates,
257 let actual = self.resolve_vars_if_possible(rcvr_ty);
258 let ty_str = self.ty_to_string(actual);
259 let is_method = mode == Mode::MethodCall;
260 let item_kind = if is_method {
262 } else if actual.is_enum() {
263 "variant or associated item"
265 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
266 (Some(name), false) if name.is_lowercase() => "function or associated item",
267 (Some(_), false) => "associated item",
268 (Some(_), true) | (None, false) => "variant or associated item",
269 (None, true) => "variant",
273 if self.suggest_constraining_numerical_ty(
274 tcx, actual, source, span, item_kind, item_name, &ty_str,
279 span = item_name.span;
281 // Don't show generic arguments when the method can't be found in any implementation (#81576).
282 let mut ty_str_reported = ty_str.clone();
283 if let ty::Adt(_, generics) = actual.kind() {
284 if generics.len() > 0 {
285 let mut autoderef = self.autoderef(span, actual);
286 let candidate_found = autoderef.any(|(ty, _)| {
287 if let ty::Adt(adt_deref, _) = ty.kind() {
289 .inherent_impls(adt_deref.did())
291 .filter_map(|def_id| self.associated_value(*def_id, item_name))
298 let has_deref = autoderef.step_count() > 0;
299 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
300 if let Some((path_string, _)) = ty_str.split_once('<') {
301 ty_str_reported = path_string.to_string();
307 let mut err = struct_span_err!(
311 "no {} named `{}` found for {} `{}` in the current scope",
314 actual.prefix_string(self.tcx),
317 if actual.references_error() {
318 err.downgrade_to_delayed_bug();
321 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
322 self.suggest_await_before_method(
323 &mut err, item_name, actual, cal, span,
326 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
329 "you are looking for the module in `std`, not the primitive type",
331 Applicability::MachineApplicable,
334 if let ty::RawPtr(_) = &actual.kind() {
336 "try using `<*const T>::as_ref()` to get a reference to the \
337 type behind the pointer: https://doc.rust-lang.org/std/\
338 primitive.pointer.html#method.as_ref",
341 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
342 to invalid or uninitialized memory is undefined behavior",
346 let ty_span = match actual.kind() {
347 ty::Param(param_type) => {
348 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
349 let type_param = generics.type_param(param_type, self.tcx);
350 Some(self.tcx.def_span(type_param.def_id))
352 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
356 if let Some(span) = ty_span {
360 "{item_kind} `{item_name}` not found for this {}",
361 actual.prefix_string(self.tcx)
366 if self.is_fn_ty(rcvr_ty, span) {
367 if let SelfSource::MethodCall(expr) = source {
368 let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() {
369 if let Some(local_id) = def_id.as_local() {
370 let hir_id = tcx.hir().local_def_id_to_hir_id(local_id);
371 let node = tcx.hir().get(hir_id);
372 let fields = node.tuple_fields();
373 if let Some(fields) = fields
374 && let Some(DefKind::Ctor(of, _)) = self.tcx.opt_def_kind(local_id) {
375 Some((fields.len(), of))
380 // The logic here isn't smart but `associated_item_def_ids`
381 // doesn't work nicely on local.
382 if let DefKind::Ctor(of, _) = tcx.def_kind(def_id) {
383 let parent_def_id = tcx.parent(*def_id);
384 Some((tcx.associated_item_def_ids(parent_def_id).len(), of))
393 // If the function is a tuple constructor, we recommend that they call it
394 if let Some((fields, kind)) = suggest {
395 suggest_call_constructor(expr.span, kind, fields, &mut err);
400 "this is a function, perhaps you wish to call it",
406 let mut custom_span_label = false;
408 if !static_sources.is_empty() {
410 "found the following associated functions; to be used as methods, \
411 functions must have a `self` parameter",
413 err.span_label(span, "this is an associated function, not a method");
414 custom_span_label = true;
416 if static_sources.len() == 1 {
418 if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) {
419 // When the "method" is resolved through dereferencing, we really want the
420 // original type that has the associated function for accurate suggestions.
422 let ty = tcx.at(span).type_of(*impl_did);
423 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
424 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
425 // Use `actual` as it will have more `substs` filled in.
426 self.ty_to_value_string(actual.peel_refs())
428 _ => self.ty_to_value_string(ty.peel_refs()),
431 self.ty_to_value_string(actual.peel_refs())
433 if let SelfSource::MethodCall(expr) = source {
436 "use associated function syntax instead",
437 format!("{}::{}", ty_str, item_name),
438 Applicability::MachineApplicable,
441 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
444 report_candidates(span, &mut err, static_sources, sugg_span);
445 } else if static_sources.len() > 1 {
446 report_candidates(span, &mut err, static_sources, sugg_span);
449 let mut bound_spans = vec![];
450 let mut restrict_type_params = false;
451 let mut unsatisfied_bounds = false;
452 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
453 let msg = "consider using `len` instead";
454 if let SelfSource::MethodCall(_expr) = source {
455 err.span_suggestion_short(
459 Applicability::MachineApplicable,
462 err.span_label(span, msg);
464 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
465 let iterator_trait = self.tcx.def_path_str(iterator_trait);
466 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
468 } else if !unsatisfied_predicates.is_empty() {
469 let mut type_params = FxHashMap::default();
471 // Pick out the list of unimplemented traits on the receiver.
472 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
473 let mut unimplemented_traits = FxHashMap::default();
474 let mut unimplemented_traits_only = true;
475 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
476 if let (ty::PredicateKind::Trait(p), Some(cause)) =
477 (predicate.kind().skip_binder(), cause.as_ref())
479 if p.trait_ref.self_ty() != rcvr_ty {
480 // This is necessary, not just to keep the errors clean, but also
481 // because our derived obligations can wind up with a trait ref that
482 // requires a different param_env to be correctly compared.
485 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
486 predicate.kind().rebind(p.trait_ref),
488 cause: cause.clone(),
489 param_env: self.param_env,
490 predicate: *predicate,
497 // Make sure that, if any traits other than the found ones were involved,
498 // we don't don't report an unimplemented trait.
499 // We don't want to say that `iter::Cloned` is not an iterator, just
500 // because of some non-Clone item being iterated over.
501 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
502 match predicate.kind().skip_binder() {
503 ty::PredicateKind::Trait(p)
504 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
506 unimplemented_traits_only = false;
512 let mut collect_type_param_suggestions =
513 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
514 // We don't care about regions here, so it's fine to skip the binder here.
515 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
516 (self_ty.kind(), parent_pred.kind().skip_binder())
518 let node = match p.trait_ref.self_ty().kind() {
520 // Account for `fn` items like in `issue-35677.rs` to
521 // suggest restricting its type params.
522 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
523 hir_id: self.body_id,
528 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
531 ty::Adt(def, _) => def.did().as_local().map(|def_id| {
534 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
538 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
539 if let Some(g) = kind.generics() {
541 g.tail_span_for_predicate_suggestion(),
542 g.add_where_or_trailing_comma(),
546 .or_insert_with(FxHashSet::default)
547 .insert(obligation.to_owned());
552 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
554 "doesn't satisfy `{}`",
555 if obligation.len() > 50 { quiet } else { obligation }
557 match &self_ty.kind() {
558 // Point at the type that couldn't satisfy the bound.
560 bound_spans.push((self.tcx.def_span(def.did()), msg))
562 // Point at the trait object that couldn't satisfy the bound.
563 ty::Dynamic(preds, _) => {
564 for pred in preds.iter() {
565 match pred.skip_binder() {
566 ty::ExistentialPredicate::Trait(tr) => bound_spans
567 .push((self.tcx.def_span(tr.def_id), msg.clone())),
568 ty::ExistentialPredicate::Projection(_)
569 | ty::ExistentialPredicate::AutoTrait(_) => {}
573 // Point at the closure that couldn't satisfy the bound.
574 ty::Closure(def_id, _) => bound_spans.push((
575 tcx.def_span(*def_id),
576 format!("doesn't satisfy `{}`", quiet),
581 let mut format_pred = |pred: ty::Predicate<'tcx>| {
582 let bound_predicate = pred.kind();
583 match bound_predicate.skip_binder() {
584 ty::PredicateKind::Projection(pred) => {
585 let pred = bound_predicate.rebind(pred);
586 // `<Foo as Iterator>::Item = String`.
587 let projection_ty = pred.skip_binder().projection_ty;
589 let substs_with_infer_self = tcx.mk_substs(
590 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
591 .chain(projection_ty.substs.iter().skip(1)),
594 let quiet_projection_ty = ty::ProjectionTy {
595 substs: substs_with_infer_self,
596 item_def_id: projection_ty.item_def_id,
599 let term = pred.skip_binder().term;
601 let obligation = format!("{} = {}", projection_ty, term);
602 let quiet = format!("{} = {}", quiet_projection_ty, term);
604 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
605 Some((obligation, projection_ty.self_ty()))
607 ty::PredicateKind::Trait(poly_trait_ref) => {
608 let p = poly_trait_ref.trait_ref;
609 let self_ty = p.self_ty();
610 let path = p.print_only_trait_path();
611 let obligation = format!("{}: {}", self_ty, path);
612 let quiet = format!("_: {}", path);
613 bound_span_label(self_ty, &obligation, &quiet);
614 Some((obligation, self_ty))
620 // Find all the requirements that come from a local `impl` block.
621 let mut skip_list: FxHashSet<_> = Default::default();
622 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
623 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
625 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
626 .filter_map(|(p, parent, c)| match c.code() {
627 ObligationCauseCode::ImplDerivedObligation(ref data) => {
628 Some((&data.derived, p, parent, data.impl_def_id, data))
633 let parent_trait_ref = data.parent_trait_pred;
634 let path = parent_trait_ref.print_modifiers_and_trait_path();
635 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
636 let unsatisfied_msg = "unsatisfied trait bound introduced here";
638 "unsatisfied trait bound introduced in this `derive` macro";
639 match self.tcx.hir().get_if_local(impl_def_id) {
640 // Unmet obligation comes from a `derive` macro, point at it once to
641 // avoid multiple span labels pointing at the same place.
642 Some(Node::Item(hir::Item {
643 kind: hir::ItemKind::Trait(..),
647 ident.span.ctxt().outer_expn_data().kind,
648 ExpnKind::Macro(MacroKind::Derive, _)
651 let span = ident.span.ctxt().outer_expn_data().call_site;
652 let mut spans: MultiSpan = span.into();
653 spans.push_span_label(span, derive_msg);
654 let entry = spanned_predicates.entry(spans);
655 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
658 Some(Node::Item(hir::Item {
659 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
662 self_ty.span.ctxt().outer_expn_data().kind,
663 ExpnKind::Macro(MacroKind::Derive, _)
665 of_trait.as_ref().map(|t| t
671 Some(ExpnKind::Macro(MacroKind::Derive, _))
674 let span = self_ty.span.ctxt().outer_expn_data().call_site;
675 let mut spans: MultiSpan = span.into();
676 spans.push_span_label(span, derive_msg);
677 let entry = spanned_predicates.entry(spans);
678 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
681 // Unmet obligation coming from a `trait`.
682 Some(Node::Item(hir::Item {
683 kind: hir::ItemKind::Trait(..),
688 ident.span.ctxt().outer_expn_data().kind,
689 ExpnKind::Macro(MacroKind::Derive, _)
692 if let Some(pred) = parent_p {
693 // Done to add the "doesn't satisfy" `span_label`.
694 let _ = format_pred(*pred);
697 let mut spans = if cause.span != *item_span {
698 let mut spans: MultiSpan = cause.span.into();
699 spans.push_span_label(cause.span, unsatisfied_msg);
704 spans.push_span_label(ident.span, "in this trait");
705 let entry = spanned_predicates.entry(spans);
706 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
709 // Unmet obligation coming from an `impl`.
710 Some(Node::Item(hir::Item {
712 hir::ItemKind::Impl(hir::Impl {
713 of_trait, self_ty, generics, ..
718 self_ty.span.ctxt().outer_expn_data().kind,
719 ExpnKind::Macro(MacroKind::Derive, _)
721 of_trait.as_ref().map(|t| t
727 Some(ExpnKind::Macro(MacroKind::Derive, _))
731 unsatisfied_predicates.iter().any(|(pred, _, _)| {
732 match pred.kind().skip_binder() {
733 ty::PredicateKind::Trait(pred) => {
735 == self.tcx.lang_items().sized_trait()
736 && pred.polarity == ty::ImplPolarity::Positive
741 for param in generics.params {
742 if param.span == cause.span && sized_pred {
743 let (sp, sugg) = match param.colon_span {
744 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
745 None => (param.span.shrink_to_hi(), ": ?Sized"),
747 err.span_suggestion_verbose(
749 "consider relaxing the type parameter's implicit \
752 Applicability::MachineApplicable,
756 if let Some(pred) = parent_p {
757 // Done to add the "doesn't satisfy" `span_label`.
758 let _ = format_pred(*pred);
761 let mut spans = if cause.span != *item_span {
762 let mut spans: MultiSpan = cause.span.into();
763 spans.push_span_label(cause.span, unsatisfied_msg);
766 let mut spans = Vec::with_capacity(2);
767 if let Some(trait_ref) = of_trait {
768 spans.push(trait_ref.path.span);
770 spans.push(self_ty.span);
773 if let Some(trait_ref) = of_trait {
774 spans.push_span_label(trait_ref.path.span, "");
776 spans.push_span_label(self_ty.span, "");
778 let entry = spanned_predicates.entry(spans);
779 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
784 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
785 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
786 for (span, (_path, _self_ty, preds)) in spanned_predicates {
787 let mut preds: Vec<_> = preds
789 .filter_map(|pred| format_pred(*pred))
790 .map(|(p, _)| format!("`{}`", p))
794 let msg = if let [pred] = &preds[..] {
795 format!("trait bound {} was not satisfied", pred)
798 "the following trait bounds were not satisfied:\n{}",
802 err.span_note(span, &msg);
803 unsatisfied_bounds = true;
806 // The requirements that didn't have an `impl` span to show.
807 let mut bound_list = unsatisfied_predicates
809 .filter_map(|(pred, parent_pred, _cause)| {
810 format_pred(*pred).map(|(p, self_ty)| {
811 collect_type_param_suggestions(self_ty, *pred, &p);
814 None => format!("`{}`", &p),
815 Some(parent_pred) => match format_pred(*parent_pred) {
816 None => format!("`{}`", &p),
817 Some((parent_p, _)) => {
818 collect_type_param_suggestions(
824 "`{}`\nwhich is required by `{}`",
834 .filter(|(_, pred)| !skip_list.contains(&pred))
837 .collect::<Vec<(usize, String)>>();
839 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
840 restrict_type_params = true;
841 // #74886: Sort here so that the output is always the same.
842 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
844 err.span_suggestion_verbose(
847 "consider restricting the type parameter{s} to satisfy the \
849 s = pluralize!(obligations.len())
851 format!("{} {}", add_where_or_comma, obligations.join(", ")),
852 Applicability::MaybeIncorrect,
856 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
857 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
858 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
860 if !bound_list.is_empty() || !skip_list.is_empty() {
861 let bound_list = bound_list
863 .map(|(_, path)| path)
866 let actual_prefix = actual.prefix_string(self.tcx);
867 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
868 let (primary_message, label) = if unimplemented_traits.len() == 1
869 && unimplemented_traits_only
874 .map(|(_, (trait_ref, obligation))| {
875 if trait_ref.self_ty().references_error()
876 || actual.references_error()
881 let OnUnimplementedNote { message, label, .. } =
882 self.infcx.on_unimplemented_note(trait_ref, &obligation);
885 .unwrap_or((None, None))
889 let primary_message = primary_message.unwrap_or_else(|| format!(
890 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
892 err.set_primary_message(&primary_message);
893 if let Some(label) = label {
894 custom_span_label = true;
895 err.span_label(span, label);
897 if !bound_list.is_empty() {
899 "the following trait bounds were not satisfied:\n{bound_list}"
902 self.suggest_derive(&mut err, &unsatisfied_predicates);
904 unsatisfied_bounds = true;
908 let label_span_not_found = |err: &mut DiagnosticBuilder<'_, _>| {
909 if unsatisfied_predicates.is_empty() {
910 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
911 let is_string_or_ref_str = match actual.kind() {
912 ty::Ref(_, ty, _) => {
916 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
919 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
922 if is_string_or_ref_str && item_name.name == sym::iter {
923 err.span_suggestion_verbose(
925 "because of the in-memory representation of `&str`, to obtain \
926 an `Iterator` over each of its codepoint use method `chars`",
928 Applicability::MachineApplicable,
931 if let ty::Adt(adt, _) = rcvr_ty.kind() {
932 let mut inherent_impls_candidate = self
934 .inherent_impls(adt.did())
938 if let Some(assoc) = self.associated_value(*def_id, item_name) {
939 // Check for both mode is the same so we avoid suggesting
940 // incorrect associated item.
941 match (mode, assoc.fn_has_self_parameter, source) {
942 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
943 // We check that the suggest type is actually
944 // different from the received one
945 // So we avoid suggestion method with Box<Self>
947 self.tcx.at(span).type_of(*def_id) != actual
948 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
950 (Mode::Path, false, _) => true,
957 .collect::<Vec<_>>();
958 if !inherent_impls_candidate.is_empty() {
959 inherent_impls_candidate.sort();
960 inherent_impls_candidate.dedup();
962 // number of type to shows at most.
963 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
964 let type_candidates = inherent_impls_candidate
968 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
972 let additional_types = if inherent_impls_candidate.len() > limit {
974 "\nand {} more types",
975 inherent_impls_candidate.len() - limit
981 "the {item_kind} was found for\n{}{}",
982 type_candidates, additional_types
987 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
991 // If the method name is the name of a field with a function or closure type,
992 // give a helping note that it has to be called as `(x.f)(...)`.
993 if let SelfSource::MethodCall(expr) = source {
994 if !self.suggest_field_call(span, rcvr_ty, expr, item_name, &mut err)
995 && lev_candidate.is_none()
996 && !custom_span_label
998 label_span_not_found(&mut err);
1000 } else if !custom_span_label {
1001 label_span_not_found(&mut err);
1004 self.check_for_field_method(&mut err, source, span, actual, item_name);
1006 self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
1009 bound_spans.dedup();
1010 for (span, msg) in bound_spans.into_iter() {
1011 err.span_label(span, &msg);
1014 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
1016 self.suggest_traits_to_import(
1021 args.map(|args| args.len()),
1023 out_of_scope_traits,
1024 &unsatisfied_predicates,
1029 // Don't emit a suggestion if we found an actual method
1030 // that had unsatisfied trait bounds
1031 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1032 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1033 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1034 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1038 err.span_suggestion(
1040 "there is a variant with a similar name",
1042 Applicability::MaybeIncorrect,
1047 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1048 let msg = "remove this method call";
1049 let mut fallback_span = true;
1050 if let SelfSource::MethodCall(expr) = source {
1052 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1053 if let Some(span) = call_expr.span.trim_start(expr.span) {
1054 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1055 fallback_span = false;
1059 err.span_label(span, msg);
1061 } else if let Some(lev_candidate) = lev_candidate {
1062 // Don't emit a suggestion if we found an actual method
1063 // that had unsatisfied trait bounds
1064 if unsatisfied_predicates.is_empty() {
1065 let def_kind = lev_candidate.kind.as_def_kind();
1066 err.span_suggestion(
1069 "there is {} {} with a similar name",
1071 def_kind.descr(lev_candidate.def_id),
1074 Applicability::MaybeIncorrect,
1082 MethodError::Ambiguity(sources) => {
1083 let mut err = struct_span_err!(
1087 "multiple applicable items in scope"
1089 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1091 report_candidates(span, &mut err, sources, sugg_span);
1095 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1096 let kind = kind.descr(def_id);
1097 let mut err = struct_span_err!(
1101 "{} `{}` is private",
1105 err.span_label(item_name.span, &format!("private {}", kind));
1109 .span_if_local(def_id)
1110 .unwrap_or_else(|| self.tcx.def_span(def_id));
1111 err.span_label(sp, &format!("private {} defined here", kind));
1112 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1116 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1117 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1118 let mut err = self.sess().struct_span_err(span, &msg);
1119 err.span_label(bound_span, "this has a `Sized` requirement");
1120 if !candidates.is_empty() {
1122 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1123 add a `use` for {one_of_them}:",
1124 an = if candidates.len() == 1 { "an" } else { "" },
1125 s = pluralize!(candidates.len()),
1126 were = pluralize!("was", candidates.len()),
1127 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1129 self.suggest_use_candidates(&mut err, help, candidates);
1131 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1133 let trait_type = self.tcx.mk_ref(
1135 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1137 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1143 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1148 fn suggest_field_call(
1152 expr: &hir::Expr<'_>,
1154 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1157 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1158 ty::Adt(def, substs) if !def.is_enum() => {
1159 let variant = &def.non_enum_variant();
1160 tcx.find_field_index(item_name, variant).map(|index| {
1161 let field = &variant.fields[index];
1162 let field_ty = field.ty(tcx, substs);
1168 if let Some((field, field_ty)) = field_receiver {
1169 let scope = tcx.parent_module(self.body_id).to_def_id();
1170 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1173 if self.is_fn_ty(field_ty, span) {
1174 let expr_span = expr.span.to(item_name.span);
1175 err.multipart_suggestion(
1177 "to call the function stored in `{}`, \
1178 surround the field access with parentheses",
1182 (expr_span.shrink_to_lo(), '('.to_string()),
1183 (expr_span.shrink_to_hi(), ')'.to_string()),
1185 Applicability::MachineApplicable,
1188 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1190 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1191 err.span_suggestion(
1193 "remove the arguments",
1195 Applicability::MaybeIncorrect,
1201 let field_kind = if is_accessible { "field" } else { "private field" };
1202 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1208 fn suggest_constraining_numerical_ty(
1212 source: SelfSource<'_>,
1218 let found_candidate = all_traits(self.tcx)
1220 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1221 let found_assoc = |ty: Ty<'tcx>| {
1222 simplify_type(tcx, ty, TreatParams::AsInfer)
1224 tcx.incoherent_impls(simp)
1226 .find_map(|&id| self.associated_value(id, item_name))
1230 let found_candidate = found_candidate
1231 || found_assoc(tcx.types.i8)
1232 || found_assoc(tcx.types.i16)
1233 || found_assoc(tcx.types.i32)
1234 || found_assoc(tcx.types.i64)
1235 || found_assoc(tcx.types.i128)
1236 || found_assoc(tcx.types.u8)
1237 || found_assoc(tcx.types.u16)
1238 || found_assoc(tcx.types.u32)
1239 || found_assoc(tcx.types.u64)
1240 || found_assoc(tcx.types.u128)
1241 || found_assoc(tcx.types.f32)
1242 || found_assoc(tcx.types.f32);
1244 && actual.is_numeric()
1245 && !actual.has_concrete_skeleton()
1246 && let SelfSource::MethodCall(expr) = source
1248 let mut err = struct_span_err!(
1252 "can't call {} `{}` on ambiguous numeric type `{}`",
1257 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1259 ExprKind::Lit(ref lit) => {
1264 .span_to_snippet(lit.span)
1265 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1267 // If this is a floating point literal that ends with '.',
1268 // get rid of it to stop this from becoming a member access.
1269 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1271 err.span_suggestion(
1274 "you must specify a concrete type for this numeric value, \
1278 format!("{snippet}_{concrete_type}"),
1279 Applicability::MaybeIncorrect,
1282 ExprKind::Path(QPath::Resolved(_, path)) => {
1284 if let hir::def::Res::Local(hir_id) = path.res {
1285 let span = tcx.hir().span(hir_id);
1286 let snippet = tcx.sess.source_map().span_to_snippet(span);
1287 let filename = tcx.sess.source_map().span_to_filename(span);
1290 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1292 "you must specify a type for this binding, like `{}`",
1296 match (filename, parent_node, snippet) {
1299 Node::Local(hir::Local {
1300 source: hir::LocalSource::Normal,
1306 err.span_suggestion(
1307 // account for `let x: _ = 42;`
1309 span.to(ty.as_ref().map(|ty| ty.span).unwrap_or(span)),
1311 format!("{}: {}", snippet, concrete_type),
1312 Applicability::MaybeIncorrect,
1316 err.span_label(span, msg);
1329 fn check_for_field_method(
1331 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1332 source: SelfSource<'tcx>,
1337 if let SelfSource::MethodCall(expr) = source
1338 && let Some((fields, substs)) = self.get_field_candidates(span, actual)
1340 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1341 for candidate_field in fields.iter() {
1342 if let Some(field_path) = self.check_for_nested_field_satisfying(
1350 ProbeScope::AllTraits,
1357 self.tcx.parent_module(expr.hir_id).to_def_id(),
1359 let field_path_str = field_path
1361 .map(|id| id.name.to_ident_string())
1362 .collect::<Vec<String>>()
1364 debug!("field_path_str: {:?}", field_path_str);
1366 err.span_suggestion_verbose(
1367 item_name.span.shrink_to_lo(),
1368 "one of the expressions' fields has a method of the same name",
1369 format!("{field_path_str}."),
1370 Applicability::MaybeIncorrect,
1377 fn check_for_unwrap_self(
1379 err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1380 source: SelfSource<'tcx>,
1386 let SelfSource::MethodCall(expr) = source else { return; };
1387 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1389 let ty::Adt(kind, substs) = actual.kind() else { return; };
1390 if !kind.is_enum() {
1394 let matching_variants: Vec<_> = kind
1397 .flat_map(|variant| {
1398 let [field] = &variant.fields[..] else { return None; };
1399 let field_ty = field.ty(tcx, substs);
1401 // Skip `_`, since that'll just lead to ambiguity.
1402 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1406 self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
1408 .map(|pick| (variant, field, pick))
1412 let ret_ty_matches = |diagnostic_item| {
1413 if let Some(ret_ty) = self
1416 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1417 && let ty::Adt(kind, _) = ret_ty.kind()
1418 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1426 match &matching_variants[..] {
1427 [(_, field, pick)] => {
1428 let self_ty = field.ty(tcx, substs);
1430 tcx.def_span(pick.item.def_id),
1431 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1433 let (article, kind, variant, question) =
1434 if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
1435 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1436 } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
1437 ("an", "Option", "None", ret_ty_matches(sym::Option))
1442 err.span_suggestion_verbose(
1443 expr.span.shrink_to_hi(),
1445 "use the `?` operator to extract the `{self_ty}` value, propagating \
1446 {article} `{kind}::{variant}` value to the caller"
1449 Applicability::MachineApplicable,
1452 err.span_suggestion_verbose(
1453 expr.span.shrink_to_hi(),
1455 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1456 panicking if the value is {article} `{kind}::{variant}`"
1458 ".expect(\"REASON\")",
1459 Applicability::HasPlaceholders,
1463 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1468 pub(crate) fn note_unmet_impls_on_type(
1470 err: &mut Diagnostic,
1471 errors: Vec<FulfillmentError<'tcx>>,
1473 let all_local_types_needing_impls =
1474 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1475 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1476 ty::Adt(def, _) => def.did().is_local(),
1481 let mut preds: Vec<_> = errors
1483 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1484 ty::PredicateKind::Trait(pred) => Some(pred),
1488 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1491 .filter_map(|pred| match pred.self_ty().kind() {
1492 ty::Adt(def, _) => Some(def.did()),
1495 .collect::<FxHashSet<_>>();
1496 let mut spans: MultiSpan = def_ids
1498 .filter_map(|def_id| {
1499 let span = self.tcx.def_span(*def_id);
1500 if span.is_dummy() { None } else { Some(span) }
1502 .collect::<Vec<_>>()
1505 for pred in &preds {
1506 match pred.self_ty().kind() {
1507 ty::Adt(def, _) if def.did().is_local() => {
1508 spans.push_span_label(
1509 self.tcx.def_span(def.did()),
1510 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1517 if all_local_types_needing_impls && spans.primary_span().is_some() {
1518 let msg = if preds.len() == 1 {
1520 "an implementation of `{}` might be missing for `{}`",
1521 preds[0].trait_ref.print_only_trait_path(),
1526 "the following type{} would have to `impl` {} required trait{} for this \
1527 operation to be valid",
1528 pluralize!(def_ids.len()),
1529 if def_ids.len() == 1 { "its" } else { "their" },
1530 pluralize!(preds.len()),
1533 err.span_note(spans, &msg);
1536 let preds: Vec<_> = errors
1538 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1540 self.suggest_derive(err, &preds);
1545 err: &mut Diagnostic,
1546 unsatisfied_predicates: &[(
1547 ty::Predicate<'tcx>,
1548 Option<ty::Predicate<'tcx>>,
1549 Option<ObligationCause<'tcx>>,
1552 let mut derives = Vec::<(String, Span, Symbol)>::new();
1553 let mut traits = Vec::<Span>::new();
1554 for (pred, _, _) in unsatisfied_predicates {
1555 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1556 let adt = match trait_pred.self_ty().ty_adt_def() {
1557 Some(adt) if adt.did().is_local() => adt,
1560 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1561 let can_derive = match diagnostic_name {
1562 sym::Default => !adt.is_enum(),
1570 | sym::Debug => true,
1574 let self_name = trait_pred.self_ty().to_string();
1575 let self_span = self.tcx.def_span(adt.did());
1576 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1577 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1579 if let Some(parent_diagnostic_name) =
1580 self.tcx.get_diagnostic_name(super_trait.def_id())
1585 parent_diagnostic_name,
1590 derives.push((self_name, self_span, diagnostic_name));
1592 traits.push(self.tcx.def_span(trait_pred.def_id()));
1595 traits.push(self.tcx.def_span(trait_pred.def_id()));
1604 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1605 for (self_name, self_span, trait_name) in derives.into_iter() {
1606 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1608 if last_self_name == &self_name {
1609 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1613 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1616 let len = traits.len();
1618 let span: MultiSpan = traits.into();
1621 &format!("the following trait{} must be implemented", pluralize!(len),),
1625 for (self_name, self_span, traits) in &derives_grouped {
1626 err.span_suggestion_verbose(
1627 self_span.shrink_to_lo(),
1628 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1629 format!("#[derive({})]\n", traits),
1630 Applicability::MaybeIncorrect,
1635 /// Print out the type for use in value namespace.
1636 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1638 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1639 _ => self.ty_to_string(ty),
1643 fn suggest_await_before_method(
1645 err: &mut Diagnostic,
1648 call: &hir::Expr<'_>,
1651 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
1652 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1655 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1656 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1658 err.span_suggestion_verbose(
1659 span.shrink_to_lo(),
1660 "consider `await`ing on the `Future` and calling the method on its `Output`",
1662 Applicability::MaybeIncorrect,
1667 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1668 let parent_map = self.tcx.visible_parent_map(());
1670 // Separate out candidates that must be imported with a glob, because they are named `_`
1671 // and cannot be referred with their identifier.
1672 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1673 if let Some(parent_did) = parent_map.get(trait_did) {
1674 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1675 if *parent_did != self.tcx.parent(*trait_did)
1678 .module_children(*parent_did)
1680 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1681 .all(|child| child.ident.name == kw::Underscore)
1690 let module_did = self.tcx.parent_module(self.body_id);
1691 let (module, _, _) = self.tcx.hir().get_module(module_did);
1692 let span = module.spans.inject_use_span;
1694 let path_strings = candidates.iter().map(|trait_did| {
1695 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1698 let glob_path_strings = globs.iter().map(|trait_did| {
1699 let parent_did = parent_map.get(trait_did).unwrap();
1701 "use {}::*; // trait {}\n",
1702 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1703 self.tcx.item_name(*trait_did),
1707 err.span_suggestions(
1710 path_strings.chain(glob_path_strings),
1711 Applicability::MaybeIncorrect,
1715 fn suggest_valid_traits(
1717 err: &mut Diagnostic,
1718 valid_out_of_scope_traits: Vec<DefId>,
1720 if !valid_out_of_scope_traits.is_empty() {
1721 let mut candidates = valid_out_of_scope_traits;
1725 // `TryFrom` and `FromIterator` have no methods
1726 let edition_fix = candidates
1728 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1731 err.help("items from traits can only be used if the trait is in scope");
1733 "the following {traits_are} implemented but not in scope; \
1734 perhaps add a `use` for {one_of_them}:",
1735 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1736 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1739 self.suggest_use_candidates(err, msg, candidates);
1740 if let Some(did) = edition_fix {
1742 "'{}' is included in the prelude starting in Edition 2021",
1743 with_crate_prefix!(self.tcx.def_path_str(did))
1753 fn suggest_traits_to_import(
1755 err: &mut Diagnostic,
1759 inputs_len: Option<usize>,
1760 source: SelfSource<'tcx>,
1761 valid_out_of_scope_traits: Vec<DefId>,
1762 unsatisfied_predicates: &[(
1763 ty::Predicate<'tcx>,
1764 Option<ty::Predicate<'tcx>>,
1765 Option<ObligationCause<'tcx>>,
1767 unsatisfied_bounds: bool,
1769 let mut alt_rcvr_sugg = false;
1770 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1771 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1773 self.tcx.lang_items().clone_trait(),
1774 self.tcx.lang_items().deref_trait(),
1775 self.tcx.lang_items().deref_mut_trait(),
1776 self.tcx.lang_items().drop_trait(),
1777 self.tcx.get_diagnostic_item(sym::AsRef),
1779 // Try alternative arbitrary self types that could fulfill this call.
1780 // FIXME: probe for all types that *could* be arbitrary self-types, not
1782 for (rcvr_ty, post) in &[
1784 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1785 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1787 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1789 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1790 // We point at the method, but we just skip the rest of the check for arbitrary
1791 // self types and rely on the suggestion to `use` the trait from
1792 // `suggest_valid_traits`.
1793 let did = Some(pick.item.container.id());
1794 let skip = skippable.contains(&did);
1795 if pick.autoderefs == 0 && !skip {
1797 pick.item.ident(self.tcx).span,
1798 &format!("the method is available for `{}` here", rcvr_ty),
1803 Err(MethodError::Ambiguity(_)) => {
1804 // If the method is defined (but ambiguous) for the receiver we have, it is also
1805 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1806 // the receiver, then it might disambiguate this method, but I think these
1807 // suggestions are generally misleading (see #94218).
1813 for (rcvr_ty, pre) in &[
1814 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1815 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1816 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1817 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1819 if let Some(new_rcvr_t) = *rcvr_ty
1820 && let Ok(pick) = self.lookup_probe(
1825 ProbeScope::AllTraits,
1828 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1829 let did = Some(pick.item.container.id());
1830 // We don't want to suggest a container type when the missing
1831 // method is `.clone()` or `.deref()` otherwise we'd suggest
1832 // `Arc::new(foo).clone()`, which is far from what the user wants.
1833 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1834 // implement the `AsRef` trait.
1835 let skip = skippable.contains(&did)
1836 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
1837 || 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);
1838 // Make sure the method is defined for the *actual* receiver: we don't
1839 // want to treat `Box<Self>` as a receiver if it only works because of
1840 // an autoderef to `&self`
1841 if pick.autoderefs == 0 && !skip {
1843 pick.item.ident(self.tcx).span,
1844 &format!("the method is available for `{}` here", new_rcvr_t),
1846 err.multipart_suggestion(
1847 "consider wrapping the receiver expression with the \
1850 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1851 (rcvr.span.shrink_to_hi(), ")".to_string()),
1853 Applicability::MaybeIncorrect,
1855 // We don't care about the other suggestions.
1856 alt_rcvr_sugg = true;
1862 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1866 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1868 let mut arbitrary_rcvr = vec![];
1869 // There are no traits implemented, so lets suggest some traits to
1870 // implement, by finding ones that have the item name, and are
1871 // legal to implement.
1872 let mut candidates = all_traits(self.tcx)
1874 // Don't issue suggestions for unstable traits since they're
1875 // unlikely to be implementable anyway
1876 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1877 Some(attr) => attr.level.is_stable(),
1881 // We approximate the coherence rules to only suggest
1882 // traits that are legal to implement by requiring that
1883 // either the type or trait is local. Multi-dispatch means
1884 // this isn't perfect (that is, there are cases when
1885 // implementing a trait would be legal but is rejected
1887 unsatisfied_predicates.iter().all(|(p, _, _)| {
1888 match p.kind().skip_binder() {
1889 // Hide traits if they are present in predicates as they can be fixed without
1890 // having to implement them.
1891 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1892 ty::PredicateKind::Projection(p) => {
1893 p.projection_ty.item_def_id == info.def_id
1897 }) && (type_is_local || info.def_id.is_local())
1899 .associated_value(info.def_id, item_name)
1901 if let ty::AssocKind::Fn = item.kind {
1905 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1906 if let Some(hir::Node::TraitItem(hir::TraitItem {
1907 kind: hir::TraitItemKind::Fn(fn_sig, method),
1909 })) = id.map(|id| self.tcx.hir().get(id))
1911 let self_first_arg = match method {
1912 hir::TraitFn::Required([ident, ..]) => {
1913 ident.name == kw::SelfLower
1915 hir::TraitFn::Provided(body_id) => {
1916 self.tcx.hir().body(*body_id).params.first().map_or(
1921 hir::PatKind::Binding(_, _, ident, _)
1922 if ident.name == kw::SelfLower
1930 if !fn_sig.decl.implicit_self.has_implicit_self()
1933 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1934 arbitrary_rcvr.push(ty.span);
1940 // We only want to suggest public or local traits (#45781).
1941 item.vis.is_public() || info.def_id.is_local()
1945 .collect::<Vec<_>>();
1946 for span in &arbitrary_rcvr {
1949 "the method might not be found because of this arbitrary self type",
1956 if !candidates.is_empty() {
1957 // Sort from most relevant to least relevant.
1958 candidates.sort_by(|a, b| a.cmp(b).reverse());
1961 let param_type = match rcvr_ty.kind() {
1962 ty::Param(param) => Some(param),
1963 ty::Ref(_, ty, _) => match ty.kind() {
1964 ty::Param(param) => Some(param),
1969 err.help(if param_type.is_some() {
1970 "items from traits can only be used if the type parameter is bounded by the trait"
1972 "items from traits can only be used if the trait is implemented and in scope"
1974 let candidates_len = candidates.len();
1975 let message = |action| {
1977 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1980 if candidates_len == 1 { "trait defines" } else { "traits define" },
1982 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1986 // Obtain the span for `param` and use it for a structured suggestion.
1987 if let Some(param) = param_type {
1988 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
1989 let type_param = generics.type_param(param, self.tcx);
1990 let hir = self.tcx.hir();
1991 if let Some(def_id) = type_param.def_id.as_local() {
1992 let id = hir.local_def_id_to_hir_id(def_id);
1993 // Get the `hir::Param` to verify whether it already has any bounds.
1994 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1995 // instead we suggest `T: Foo + Bar` in that case.
1997 Node::GenericParam(param) => {
2003 let ast_generics = hir.get_generics(id.owner).unwrap();
2004 let (sp, mut introducer) = if let Some(span) =
2005 ast_generics.bounds_span_for_suggestions(def_id)
2007 (span, Introducer::Plus)
2008 } else if let Some(colon_span) = param.colon_span {
2009 (colon_span.shrink_to_hi(), Introducer::Nothing)
2011 (param.span.shrink_to_hi(), Introducer::Colon)
2015 hir::GenericParamKind::Type { synthetic: true, .. },
2017 introducer = Introducer::Plus
2019 let trait_def_ids: FxHashSet<DefId> = ast_generics
2020 .bounds_for_param(def_id)
2021 .flat_map(|bp| bp.bounds.iter())
2022 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2024 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2025 err.span_suggestions(
2028 "restrict type parameter `{}` with",
2031 candidates.iter().map(|t| {
2035 Introducer::Plus => " +",
2036 Introducer::Colon => ":",
2037 Introducer::Nothing => "",
2039 self.tcx.def_path_str(t.def_id),
2042 Applicability::MaybeIncorrect,
2047 Node::Item(hir::Item {
2048 kind: hir::ItemKind::Trait(.., bounds, _),
2052 let (sp, sep, article) = if bounds.is_empty() {
2053 (ident.span.shrink_to_hi(), ":", "a")
2055 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2057 err.span_suggestions(
2059 &message(format!("add {} supertrait for", article)),
2060 candidates.iter().map(|t| {
2061 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2063 Applicability::MaybeIncorrect,
2072 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2073 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2074 // cases where a positive bound implies a negative impl.
2075 (candidates, Vec::new())
2076 } else if let Some(simp_rcvr_ty) =
2077 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2079 let mut potential_candidates = Vec::new();
2080 let mut explicitly_negative = Vec::new();
2081 for candidate in candidates {
2082 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2085 .all_impls(candidate.def_id)
2087 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2090 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2092 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2093 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2096 explicitly_negative.push(candidate);
2098 potential_candidates.push(candidate);
2101 (potential_candidates, explicitly_negative)
2103 // We don't know enough about `recv_ty` to make proper suggestions.
2104 (candidates, Vec::new())
2107 let action = if let Some(param) = param_type {
2108 format!("restrict type parameter `{}` with", param)
2110 // FIXME: it might only need to be imported into scope, not implemented.
2111 "implement".to_string()
2113 match &potential_candidates[..] {
2115 [trait_info] if trait_info.def_id.is_local() => {
2117 self.tcx.def_span(trait_info.def_id),
2119 "`{}` defines an item `{}`, perhaps you need to {} it",
2120 self.tcx.def_path_str(trait_info.def_id),
2127 let mut msg = message(action);
2128 for (i, trait_info) in trait_infos.iter().enumerate() {
2129 msg.push_str(&format!(
2130 "\ncandidate #{}: `{}`",
2132 self.tcx.def_path_str(trait_info.def_id),
2138 match &explicitly_negative[..] {
2142 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2143 self.tcx.def_path_str(trait_info.def_id),
2149 let mut msg = format!(
2150 "the following traits define an item `{}`, but are explicitly unimplemented:",
2153 for trait_info in trait_infos {
2154 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2162 /// Checks whether there is a local type somewhere in the chain of
2163 /// autoderefs of `rcvr_ty`.
2164 fn type_derefs_to_local(
2168 source: SelfSource<'tcx>,
2170 fn is_local(ty: Ty<'_>) -> bool {
2172 ty::Adt(def, _) => def.did().is_local(),
2173 ty::Foreign(did) => did.is_local(),
2174 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2175 ty::Param(_) => true,
2177 // Everything else (primitive types, etc.) is effectively
2178 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2179 // the noise from these sort of types is usually just really
2180 // annoying, rather than any sort of help).
2185 // This occurs for UFCS desugaring of `T::method`, where there is no
2186 // receiver expression for the method call, and thus no autoderef.
2187 if let SelfSource::QPath(_) = source {
2188 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2191 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2195 #[derive(Copy, Clone, Debug)]
2196 pub enum SelfSource<'a> {
2197 QPath(&'a hir::Ty<'a>),
2198 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2201 #[derive(Copy, Clone)]
2202 pub struct TraitInfo {
2206 impl PartialEq for TraitInfo {
2207 fn eq(&self, other: &TraitInfo) -> bool {
2208 self.cmp(other) == Ordering::Equal
2211 impl Eq for TraitInfo {}
2212 impl PartialOrd for TraitInfo {
2213 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2214 Some(self.cmp(other))
2217 impl Ord for TraitInfo {
2218 fn cmp(&self, other: &TraitInfo) -> Ordering {
2219 // Local crates are more important than remote ones (local:
2220 // `cnum == 0`), and otherwise we throw in the defid for totality.
2222 let lhs = (other.def_id.krate, other.def_id);
2223 let rhs = (self.def_id.krate, self.def_id);
2228 /// Retrieves all traits in this crate and any dependent crates,
2229 /// and wraps them into `TraitInfo` for custom sorting.
2230 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2231 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2234 fn print_disambiguation_help<'tcx>(
2236 args: Option<&'tcx [hir::Expr<'tcx>]>,
2237 err: &mut Diagnostic,
2240 kind: ty::AssocKind,
2243 candidate: Option<usize>,
2244 source_map: &source_map::SourceMap,
2245 fn_has_self_parameter: bool,
2247 let mut applicability = Applicability::MachineApplicable;
2248 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
2251 if rcvr_ty.is_region_ptr() {
2252 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2257 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2258 applicability = Applicability::HasPlaceholders;
2261 .collect::<Vec<_>>()
2264 let trait_name = if !fn_has_self_parameter {
2265 format!("<{} as {}>", rcvr_ty, trait_name)
2269 (span, format!("{}::{}{}", trait_name, item_name, args))
2271 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2273 err.span_suggestion_verbose(
2276 "disambiguate the {} for {}",
2277 kind.as_def_kind().descr(def_id),
2278 if let Some(candidate) = candidate {
2279 format!("candidate #{}", candidate)
2281 "the candidate".to_string()