1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
13 use rustc_hir::def::DefKind;
14 use rustc_hir::def_id::DefId;
15 use rustc_hir::lang_items::LangItem;
16 use rustc_hir::{ExprKind, Node, QPath};
17 use rustc_infer::infer::{
18 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
21 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
22 use rustc_middle::traits::util::supertraits;
23 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
24 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
25 use rustc_middle::ty::print::with_crate_prefix;
26 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable};
27 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
28 use rustc_span::symbol::{kw, sym, Ident};
29 use rustc_span::Symbol;
30 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
31 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
32 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
33 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
34 use rustc_trait_selection::traits::{
35 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
38 use std::cmp::Ordering;
41 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
42 use super::{CandidateSource, MethodError, NoMatchData};
44 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
45 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
48 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
49 // so we look for these beforehand.
50 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
51 // If it's not a simple function, look for things which implement `FnOnce`.
53 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
57 // This conditional prevents us from asking to call errors and unresolved types.
58 // It might seem that we can use `predicate_must_hold_modulo_regions`,
59 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
60 // type resolution always gives a "maybe" here.
61 if self.autoderef(span, ty).any(|(ty, _)| {
62 info!("check deref {:?} error", ty);
63 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
68 self.autoderef(span, ty).any(|(ty, _)| {
69 info!("check deref {:?} impl FnOnce", ty);
71 let fn_once_substs = tcx.mk_substs_trait(
74 .next_ty_var(TypeVariableOrigin {
75 kind: TypeVariableOriginKind::MiscVariable,
80 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
81 let poly_trait_ref = ty::Binder::dummy(trait_ref);
82 let obligation = Obligation::misc(
86 poly_trait_ref.without_const().to_predicate(tcx),
88 self.predicate_may_hold(&obligation)
95 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
96 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
99 pub fn report_method_error(
104 source: SelfSource<'tcx>,
105 error: MethodError<'tcx>,
106 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
107 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
108 // Avoid suggestions when we don't know what's going on.
109 if rcvr_ty.references_error() {
113 let report_candidates = |span: Span,
114 err: &mut Diagnostic,
115 sources: &mut Vec<CandidateSource>,
119 // Dynamic limit to avoid hiding just one candidate, which is silly.
120 let limit = if sources.len() == 5 { 5 } else { 4 };
122 for (idx, source) in sources.iter().take(limit).enumerate() {
124 CandidateSource::Impl(impl_did) => {
125 // Provide the best span we can. Use the item, if local to crate, else
126 // the impl, if local to crate (item may be defaulted), else nothing.
127 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
128 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
129 self.associated_value(impl_trait_ref.def_id, item_name)
134 let note_span = if item.def_id.is_local() {
135 Some(self.tcx.def_span(item.def_id))
136 } else if impl_did.is_local() {
137 Some(self.tcx.def_span(impl_did))
142 let impl_ty = self.tcx.at(span).type_of(impl_did);
144 let insertion = match self.tcx.impl_trait_ref(impl_did) {
145 None => String::new(),
146 Some(trait_ref) => format!(
147 " of the trait `{}`",
148 self.tcx.def_path_str(trait_ref.def_id)
152 let (note_str, idx) = if sources.len() > 1 {
155 "candidate #{} is defined in an impl{} for the type `{}`",
165 "the candidate is defined in an impl{} for the type `{}`",
171 if let Some(note_span) = note_span {
172 // We have a span pointing to the method. Show note with snippet.
173 err.span_note(note_span, ¬e_str);
177 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
178 let path = self.tcx.def_path_str(trait_ref.def_id);
180 let ty = match item.kind {
181 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
182 ty::AssocKind::Fn => self
188 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
192 print_disambiguation_help(
202 self.tcx.sess.source_map(),
203 item.fn_has_self_parameter,
207 CandidateSource::Trait(trait_did) => {
208 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
209 let item_span = self.tcx.def_span(item.def_id);
210 let idx = if sources.len() > 1 {
212 "candidate #{} is defined in the trait `{}`",
214 self.tcx.def_path_str(trait_did)
216 err.span_note(item_span, msg);
220 "the candidate is defined in the trait `{}`",
221 self.tcx.def_path_str(trait_did)
223 err.span_note(item_span, msg);
226 let path = self.tcx.def_path_str(trait_did);
227 print_disambiguation_help(
237 self.tcx.sess.source_map(),
238 item.fn_has_self_parameter,
243 if sources.len() > limit {
244 err.note(&format!("and {} others", sources.len() - limit));
248 let sugg_span = if let SelfSource::MethodCall(expr) = source {
249 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
250 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
256 MethodError::NoMatch(NoMatchData {
257 mut static_candidates,
258 unsatisfied_predicates,
265 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
266 let ty_str = self.ty_to_string(rcvr_ty);
267 let is_method = mode == Mode::MethodCall;
268 let item_kind = if is_method {
270 } else if rcvr_ty.is_enum() {
271 "variant or associated item"
273 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
274 (Some(name), false) if name.is_lowercase() => "function or associated item",
275 (Some(_), false) => "associated item",
276 (Some(_), true) | (None, false) => "variant or associated item",
277 (None, true) => "variant",
281 if self.suggest_wrapping_range_with_parens(
282 tcx, rcvr_ty, source, span, item_name, &ty_str,
283 ) || self.suggest_constraining_numerical_ty(
284 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
288 span = item_name.span;
290 // Don't show generic arguments when the method can't be found in any implementation (#81576).
291 let mut ty_str_reported = ty_str.clone();
292 if let ty::Adt(_, generics) = rcvr_ty.kind() {
293 if generics.len() > 0 {
294 let mut autoderef = self.autoderef(span, rcvr_ty);
295 let candidate_found = autoderef.any(|(ty, _)| {
296 if let ty::Adt(adt_def, _) = ty.kind() {
298 .inherent_impls(adt_def.did())
300 .filter_map(|def_id| self.associated_value(*def_id, item_name))
307 let has_deref = autoderef.step_count() > 0;
308 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
309 if let Some((path_string, _)) = ty_str.split_once('<') {
310 ty_str_reported = path_string.to_string();
316 let mut err = struct_span_err!(
320 "no {} named `{}` found for {} `{}` in the current scope",
323 rcvr_ty.prefix_string(self.tcx),
326 if rcvr_ty.references_error() {
327 err.downgrade_to_delayed_bug();
330 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
331 self.suggest_await_before_method(
332 &mut err, item_name, rcvr_ty, cal, span,
335 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
338 "you are looking for the module in `std`, not the primitive type",
340 Applicability::MachineApplicable,
343 if let ty::RawPtr(_) = &rcvr_ty.kind() {
345 "try using `<*const T>::as_ref()` to get a reference to the \
346 type behind the pointer: https://doc.rust-lang.org/std/\
347 primitive.pointer.html#method.as_ref",
350 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
351 to invalid or uninitialized memory is undefined behavior",
355 let ty_span = match rcvr_ty.kind() {
356 ty::Param(param_type) => Some(
357 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
359 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
362 if let Some(span) = ty_span {
366 "{item_kind} `{item_name}` not found for this {}",
367 rcvr_ty.prefix_string(self.tcx)
372 if let SelfSource::MethodCall(rcvr_expr) = source {
373 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
377 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
378 let probe = self.lookup_probe(
382 ProbeScope::AllTraits,
388 let mut custom_span_label = false;
390 if !static_candidates.is_empty() {
392 "found the following associated functions; to be used as methods, \
393 functions must have a `self` parameter",
395 err.span_label(span, "this is an associated function, not a method");
396 custom_span_label = true;
398 if static_candidates.len() == 1 {
399 self.suggest_associated_call_syntax(
409 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
410 } else if static_candidates.len() > 1 {
411 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
414 let mut bound_spans = vec![];
415 let mut restrict_type_params = false;
416 let mut unsatisfied_bounds = false;
417 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
418 let msg = "consider using `len` instead";
419 if let SelfSource::MethodCall(_expr) = source {
420 err.span_suggestion_short(
424 Applicability::MachineApplicable,
427 err.span_label(span, msg);
429 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
430 let iterator_trait = self.tcx.def_path_str(iterator_trait);
431 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
433 } else if !unsatisfied_predicates.is_empty() {
434 let mut type_params = FxHashMap::default();
436 // Pick out the list of unimplemented traits on the receiver.
437 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
438 let mut unimplemented_traits = FxHashMap::default();
439 let mut unimplemented_traits_only = true;
440 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
441 if let (ty::PredicateKind::Trait(p), Some(cause)) =
442 (predicate.kind().skip_binder(), cause.as_ref())
444 if p.trait_ref.self_ty() != rcvr_ty {
445 // This is necessary, not just to keep the errors clean, but also
446 // because our derived obligations can wind up with a trait ref that
447 // requires a different param_env to be correctly compared.
450 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
451 predicate.kind().rebind(p.trait_ref),
453 cause: cause.clone(),
454 param_env: self.param_env,
455 predicate: *predicate,
462 // Make sure that, if any traits other than the found ones were involved,
463 // we don't don't report an unimplemented trait.
464 // We don't want to say that `iter::Cloned` is not an iterator, just
465 // because of some non-Clone item being iterated over.
466 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
467 match predicate.kind().skip_binder() {
468 ty::PredicateKind::Trait(p)
469 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
471 unimplemented_traits_only = false;
477 let mut collect_type_param_suggestions =
478 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
479 // We don't care about regions here, so it's fine to skip the binder here.
480 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
481 (self_ty.kind(), parent_pred.kind().skip_binder())
483 let hir = self.tcx.hir();
484 let node = match p.trait_ref.self_ty().kind() {
486 // Account for `fn` items like in `issue-35677.rs` to
487 // suggest restricting its type params.
489 hir.body_owner(hir::BodyId { hir_id: self.body_id });
490 Some(hir.get(parent_body))
493 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
497 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
498 if let Some(g) = kind.generics() {
500 g.tail_span_for_predicate_suggestion(),
501 g.add_where_or_trailing_comma(),
505 .or_insert_with(FxHashSet::default)
506 .insert(obligation.to_owned());
511 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
513 "doesn't satisfy `{}`",
514 if obligation.len() > 50 { quiet } else { obligation }
516 match &self_ty.kind() {
517 // Point at the type that couldn't satisfy the bound.
519 bound_spans.push((self.tcx.def_span(def.did()), msg))
521 // Point at the trait object that couldn't satisfy the bound.
522 ty::Dynamic(preds, _, _) => {
523 for pred in preds.iter() {
524 match pred.skip_binder() {
525 ty::ExistentialPredicate::Trait(tr) => bound_spans
526 .push((self.tcx.def_span(tr.def_id), msg.clone())),
527 ty::ExistentialPredicate::Projection(_)
528 | ty::ExistentialPredicate::AutoTrait(_) => {}
532 // Point at the closure that couldn't satisfy the bound.
533 ty::Closure(def_id, _) => bound_spans.push((
534 tcx.def_span(*def_id),
535 format!("doesn't satisfy `{}`", quiet),
540 let mut format_pred = |pred: ty::Predicate<'tcx>| {
541 let bound_predicate = pred.kind();
542 match bound_predicate.skip_binder() {
543 ty::PredicateKind::Projection(pred) => {
544 let pred = bound_predicate.rebind(pred);
545 // `<Foo as Iterator>::Item = String`.
546 let projection_ty = pred.skip_binder().projection_ty;
548 let substs_with_infer_self = tcx.mk_substs(
549 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
550 .chain(projection_ty.substs.iter().skip(1)),
553 let quiet_projection_ty = ty::ProjectionTy {
554 substs: substs_with_infer_self,
555 item_def_id: projection_ty.item_def_id,
558 let term = pred.skip_binder().term;
560 let obligation = format!("{} = {}", projection_ty, term);
561 let quiet = format!("{} = {}", quiet_projection_ty, term);
563 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
564 Some((obligation, projection_ty.self_ty()))
566 ty::PredicateKind::Trait(poly_trait_ref) => {
567 let p = poly_trait_ref.trait_ref;
568 let self_ty = p.self_ty();
569 let path = p.print_only_trait_path();
570 let obligation = format!("{}: {}", self_ty, path);
571 let quiet = format!("_: {}", path);
572 bound_span_label(self_ty, &obligation, &quiet);
573 Some((obligation, self_ty))
579 // Find all the requirements that come from a local `impl` block.
580 let mut skip_list: FxHashSet<_> = Default::default();
581 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
582 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
584 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
585 .filter_map(|(p, parent, c)| match c.code() {
586 ObligationCauseCode::ImplDerivedObligation(data) => {
587 Some((&data.derived, p, parent, data.impl_def_id, data))
592 let parent_trait_ref = data.parent_trait_pred;
593 let path = parent_trait_ref.print_modifiers_and_trait_path();
594 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
595 let unsatisfied_msg = "unsatisfied trait bound introduced here";
597 "unsatisfied trait bound introduced in this `derive` macro";
598 match self.tcx.hir().get_if_local(impl_def_id) {
599 // Unmet obligation comes from a `derive` macro, point at it once to
600 // avoid multiple span labels pointing at the same place.
601 Some(Node::Item(hir::Item {
602 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
605 self_ty.span.ctxt().outer_expn_data().kind,
606 ExpnKind::Macro(MacroKind::Derive, _)
608 of_trait.as_ref().map(|t| t
614 Some(ExpnKind::Macro(MacroKind::Derive, _))
617 let span = self_ty.span.ctxt().outer_expn_data().call_site;
618 let mut spans: MultiSpan = span.into();
619 spans.push_span_label(span, derive_msg);
620 let entry = spanned_predicates.entry(spans);
621 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
624 // Unmet obligation coming from an `impl`.
625 Some(Node::Item(hir::Item {
627 hir::ItemKind::Impl(hir::Impl {
628 of_trait, self_ty, generics, ..
634 unsatisfied_predicates.iter().any(|(pred, _, _)| {
635 match pred.kind().skip_binder() {
636 ty::PredicateKind::Trait(pred) => {
638 == self.tcx.lang_items().sized_trait()
639 && pred.polarity == ty::ImplPolarity::Positive
644 for param in generics.params {
645 if param.span == cause.span && sized_pred {
646 let (sp, sugg) = match param.colon_span {
647 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
648 None => (param.span.shrink_to_hi(), ": ?Sized"),
650 err.span_suggestion_verbose(
652 "consider relaxing the type parameter's implicit \
655 Applicability::MachineApplicable,
659 if let Some(pred) = parent_p {
660 // Done to add the "doesn't satisfy" `span_label`.
661 let _ = format_pred(*pred);
664 let mut spans = if cause.span != *item_span {
665 let mut spans: MultiSpan = cause.span.into();
666 spans.push_span_label(cause.span, unsatisfied_msg);
669 let mut spans = Vec::with_capacity(2);
670 if let Some(trait_ref) = of_trait {
671 spans.push(trait_ref.path.span);
673 spans.push(self_ty.span);
676 if let Some(trait_ref) = of_trait {
677 spans.push_span_label(trait_ref.path.span, "");
679 spans.push_span_label(self_ty.span, "");
681 let entry = spanned_predicates.entry(spans);
682 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
684 Some(_) => unreachable!(),
688 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
689 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
690 for (span, (_path, _self_ty, preds)) in spanned_predicates {
691 let mut preds: Vec<_> = preds
693 .filter_map(|pred| format_pred(*pred))
694 .map(|(p, _)| format!("`{}`", p))
698 let msg = if let [pred] = &preds[..] {
699 format!("trait bound {} was not satisfied", pred)
702 "the following trait bounds were not satisfied:\n{}",
706 err.span_note(span, &msg);
707 unsatisfied_bounds = true;
710 // The requirements that didn't have an `impl` span to show.
711 let mut bound_list = unsatisfied_predicates
713 .filter_map(|(pred, parent_pred, _cause)| {
714 format_pred(*pred).map(|(p, self_ty)| {
715 collect_type_param_suggestions(self_ty, *pred, &p);
718 None => format!("`{}`", &p),
719 Some(parent_pred) => match format_pred(*parent_pred) {
720 None => format!("`{}`", &p),
721 Some((parent_p, _)) => {
722 collect_type_param_suggestions(
728 "`{}`\nwhich is required by `{}`",
738 .filter(|(_, pred)| !skip_list.contains(&pred))
741 .collect::<Vec<(usize, String)>>();
743 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
744 restrict_type_params = true;
745 // #74886: Sort here so that the output is always the same.
746 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
748 err.span_suggestion_verbose(
751 "consider restricting the type parameter{s} to satisfy the \
753 s = pluralize!(obligations.len())
755 format!("{} {}", add_where_or_comma, obligations.join(", ")),
756 Applicability::MaybeIncorrect,
760 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
761 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
762 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
764 if !bound_list.is_empty() || !skip_list.is_empty() {
765 let bound_list = bound_list
767 .map(|(_, path)| path)
770 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
771 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
772 let (primary_message, label) =
773 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
777 .map(|(_, (trait_ref, obligation))| {
778 if trait_ref.self_ty().references_error()
779 || rcvr_ty.references_error()
784 let OnUnimplementedNote { message, label, .. } = self
786 .on_unimplemented_note(trait_ref, &obligation);
793 let primary_message = primary_message.unwrap_or_else(|| format!(
794 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
796 err.set_primary_message(&primary_message);
797 if let Some(label) = label {
798 custom_span_label = true;
799 err.span_label(span, label);
801 if !bound_list.is_empty() {
803 "the following trait bounds were not satisfied:\n{bound_list}"
806 self.suggest_derive(&mut err, &unsatisfied_predicates);
808 unsatisfied_bounds = true;
812 let label_span_not_found = |err: &mut Diagnostic| {
813 if unsatisfied_predicates.is_empty() {
814 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
815 let is_string_or_ref_str = match rcvr_ty.kind() {
816 ty::Ref(_, ty, _) => {
820 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
823 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
826 if is_string_or_ref_str && item_name.name == sym::iter {
827 err.span_suggestion_verbose(
829 "because of the in-memory representation of `&str`, to obtain \
830 an `Iterator` over each of its codepoint use method `chars`",
832 Applicability::MachineApplicable,
835 if let ty::Adt(adt, _) = rcvr_ty.kind() {
836 let mut inherent_impls_candidate = self
838 .inherent_impls(adt.did())
842 if let Some(assoc) = self.associated_value(*def_id, item_name) {
843 // Check for both mode is the same so we avoid suggesting
844 // incorrect associated item.
845 match (mode, assoc.fn_has_self_parameter, source) {
846 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
847 // We check that the suggest type is actually
848 // different from the received one
849 // So we avoid suggestion method with Box<Self>
851 self.tcx.at(span).type_of(*def_id) != rcvr_ty
852 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
854 (Mode::Path, false, _) => true,
861 .collect::<Vec<_>>();
862 if !inherent_impls_candidate.is_empty() {
863 inherent_impls_candidate.sort();
864 inherent_impls_candidate.dedup();
866 // number of type to shows at most.
867 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
868 let type_candidates = inherent_impls_candidate
872 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
876 let additional_types = if inherent_impls_candidate.len() > limit {
878 "\nand {} more types",
879 inherent_impls_candidate.len() - limit
885 "the {item_kind} was found for\n{}{}",
886 type_candidates, additional_types
891 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
895 // If the method name is the name of a field with a function or closure type,
896 // give a helping note that it has to be called as `(x.f)(...)`.
897 if let SelfSource::MethodCall(expr) = source {
898 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
899 && lev_candidate.is_none()
900 && !custom_span_label
902 label_span_not_found(&mut err);
904 } else if !custom_span_label {
905 label_span_not_found(&mut err);
908 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
909 // can't be called due to `typeof(expr): Clone` not holding.
910 if unsatisfied_predicates.is_empty() {
911 self.suggest_calling_method_on_field(
912 &mut err, source, span, rcvr_ty, item_name,
916 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
920 for (span, msg) in bound_spans.into_iter() {
921 err.span_label(span, &msg);
924 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
926 self.suggest_traits_to_import(
931 args.map(|(_, args)| args.len() + 1),
934 &unsatisfied_predicates,
940 // Don't emit a suggestion if we found an actual method
941 // that had unsatisfied trait bounds
942 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
943 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
944 if let Some(suggestion) = lev_distance::find_best_match_for_name(
945 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
951 "there is a variant with a similar name",
953 Applicability::MaybeIncorrect,
958 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
959 let msg = "remove this method call";
960 let mut fallback_span = true;
961 if let SelfSource::MethodCall(expr) = source {
963 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
964 if let Some(span) = call_expr.span.trim_start(expr.span) {
965 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
966 fallback_span = false;
970 err.span_label(span, msg);
972 } else if let Some(lev_candidate) = lev_candidate {
973 // Don't emit a suggestion if we found an actual method
974 // that had unsatisfied trait bounds
975 if unsatisfied_predicates.is_empty() {
976 let def_kind = lev_candidate.kind.as_def_kind();
977 // Methods are defined within the context of a struct and their first parameter is always self,
978 // which represents the instance of the struct the method is being called on
979 // Associated functions don’t take self as a parameter and
980 // they are not methods because they don’t have an instance of the struct to work with.
981 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
984 &format!("there is a method with a similar name",),
986 Applicability::MaybeIncorrect,
992 "there is {} {} with a similar name",
994 def_kind.descr(lev_candidate.def_id),
997 Applicability::MaybeIncorrect,
1003 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1008 MethodError::Ambiguity(mut sources) => {
1009 let mut err = struct_span_err!(
1013 "multiple applicable items in scope"
1015 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1017 report_candidates(span, &mut err, &mut sources, sugg_span);
1021 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1022 let kind = kind.descr(def_id);
1023 let mut err = struct_span_err!(
1027 "{} `{}` is private",
1031 err.span_label(item_name.span, &format!("private {}", kind));
1035 .span_if_local(def_id)
1036 .unwrap_or_else(|| self.tcx.def_span(def_id));
1037 err.span_label(sp, &format!("private {} defined here", kind));
1038 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1042 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1043 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1044 let mut err = self.sess().struct_span_err(span, &msg);
1045 err.span_label(bound_span, "this has a `Sized` requirement");
1046 if !candidates.is_empty() {
1048 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1049 add a `use` for {one_of_them}:",
1050 an = if candidates.len() == 1 { "an" } else { "" },
1051 s = pluralize!(candidates.len()),
1052 were = pluralize!("was", candidates.len()),
1053 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1055 self.suggest_use_candidates(&mut err, help, candidates);
1057 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1059 let trait_type = self.tcx.mk_ref(
1061 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1063 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1069 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1074 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1075 /// doesn't take a `self` receiver.
1076 fn suggest_associated_call_syntax(
1078 err: &mut Diagnostic,
1079 static_candidates: &Vec<CandidateSource>,
1081 source: SelfSource<'tcx>,
1083 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1086 let mut has_unsuggestable_args = false;
1087 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1088 // When the "method" is resolved through dereferencing, we really want the
1089 // original type that has the associated function for accurate suggestions.
1091 let impl_ty = self.tcx.type_of(*impl_did);
1092 let target_ty = self
1093 .autoderef(sugg_span, rcvr_ty)
1094 .find(|(rcvr_ty, _)| {
1095 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1096 .types_may_unify(*rcvr_ty, impl_ty)
1098 .map_or(impl_ty, |(ty, _)| ty)
1100 if let ty::Adt(def, substs) = target_ty.kind() {
1101 // If there are any inferred arguments, (`{integer}`), we should replace
1102 // them with underscores to allow the compiler to infer them
1103 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1104 if !arg.is_suggestable(self.tcx, true) {
1105 has_unsuggestable_args = true;
1106 match arg.unpack() {
1107 GenericArgKind::Lifetime(_) => self
1108 .next_region_var(RegionVariableOrigin::MiscVariable(
1109 rustc_span::DUMMY_SP,
1112 GenericArgKind::Type(_) => self
1113 .next_ty_var(TypeVariableOrigin {
1114 span: rustc_span::DUMMY_SP,
1115 kind: TypeVariableOriginKind::MiscVariable,
1118 GenericArgKind::Const(arg) => self
1121 ConstVariableOrigin {
1122 span: rustc_span::DUMMY_SP,
1123 kind: ConstVariableOriginKind::MiscVariable,
1133 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1135 self.ty_to_value_string(target_ty)
1138 self.ty_to_value_string(rcvr_ty.peel_refs())
1140 if let SelfSource::MethodCall(_) = source {
1141 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1142 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1143 && assoc.kind == ty::AssocKind::Fn
1145 let sig = self.tcx.fn_sig(assoc.def_id);
1146 if let Some(first) = sig.inputs().skip_binder().get(0) {
1147 if first.peel_refs() == rcvr_ty.peel_refs() {
1150 Some(if first.is_region_ptr() {
1151 if first.is_mutable_ptr() { "&mut " } else { "&" }
1162 let mut applicability = Applicability::MachineApplicable;
1163 let args = if let Some((receiver, args)) = args {
1164 // The first arg is the same kind as the receiver
1165 let explicit_args = if first_arg.is_some() {
1166 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1168 // There is no `Self` kind to infer the arguments from
1169 if has_unsuggestable_args {
1170 applicability = Applicability::HasPlaceholders;
1172 args.iter().collect()
1176 first_arg.unwrap_or(""),
1183 .span_to_snippet(arg.span)
1184 .unwrap_or_else(|_| {
1185 applicability = Applicability::HasPlaceholders;
1188 .collect::<Vec<_>>()
1192 applicability = Applicability::HasPlaceholders;
1195 err.span_suggestion(
1197 "use associated function syntax instead",
1198 format!("{}::{}{}", ty_str, item_name, args),
1202 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1206 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1207 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1208 fn suggest_calling_field_as_fn(
1212 expr: &hir::Expr<'_>,
1214 err: &mut Diagnostic,
1217 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1218 ty::Adt(def, substs) if !def.is_enum() => {
1219 let variant = &def.non_enum_variant();
1220 tcx.find_field_index(item_name, variant).map(|index| {
1221 let field = &variant.fields[index];
1222 let field_ty = field.ty(tcx, substs);
1228 if let Some((field, field_ty)) = field_receiver {
1229 let scope = tcx.parent_module(self.body_id);
1230 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1233 if self.is_fn_ty(field_ty, span) {
1234 let expr_span = expr.span.to(item_name.span);
1235 err.multipart_suggestion(
1237 "to call the function stored in `{}`, \
1238 surround the field access with parentheses",
1242 (expr_span.shrink_to_lo(), '('.to_string()),
1243 (expr_span.shrink_to_hi(), ')'.to_string()),
1245 Applicability::MachineApplicable,
1248 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1250 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1251 err.span_suggestion(
1253 "remove the arguments",
1255 Applicability::MaybeIncorrect,
1261 let field_kind = if is_accessible { "field" } else { "private field" };
1262 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1268 /// Suggest possible range with adding parentheses, for example:
1269 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1270 fn suggest_wrapping_range_with_parens(
1274 source: SelfSource<'tcx>,
1279 if let SelfSource::MethodCall(expr) = source {
1280 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1281 if let Node::Expr(parent_expr) = parent {
1282 let lang_item = match parent_expr.kind {
1283 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1284 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1285 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1286 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1287 Some(LangItem::RangeToInclusive)
1291 ExprKind::Call(ref func, _) => match func.kind {
1292 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1293 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1294 Some(LangItem::RangeInclusiveStruct)
1301 if lang_item.is_none() {
1305 let span_included = match parent_expr.kind {
1306 hir::ExprKind::Struct(_, eps, _) => {
1307 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1309 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1310 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1318 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1320 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1322 let pick = self.probe_for_name(
1328 ProbeScope::AllTraits,
1331 let range_span = parent_expr.span.with_hi(expr.span.hi());
1332 tcx.sess.emit_err(errors::MissingParentheseInRange {
1334 ty_str: ty_str.to_string(),
1335 method_name: item_name.as_str().to_string(),
1336 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1337 func_name: item_name.name.as_str().to_string(),
1338 left: range_span.shrink_to_lo(),
1339 right: range_span.shrink_to_hi(),
1350 fn suggest_constraining_numerical_ty(
1354 source: SelfSource<'_>,
1360 let found_candidate = all_traits(self.tcx)
1362 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1363 let found_assoc = |ty: Ty<'tcx>| {
1364 simplify_type(tcx, ty, TreatParams::AsInfer)
1366 tcx.incoherent_impls(simp)
1368 .find_map(|&id| self.associated_value(id, item_name))
1372 let found_candidate = found_candidate
1373 || found_assoc(tcx.types.i8)
1374 || found_assoc(tcx.types.i16)
1375 || found_assoc(tcx.types.i32)
1376 || found_assoc(tcx.types.i64)
1377 || found_assoc(tcx.types.i128)
1378 || found_assoc(tcx.types.u8)
1379 || found_assoc(tcx.types.u16)
1380 || found_assoc(tcx.types.u32)
1381 || found_assoc(tcx.types.u64)
1382 || found_assoc(tcx.types.u128)
1383 || found_assoc(tcx.types.f32)
1384 || found_assoc(tcx.types.f32);
1386 && actual.is_numeric()
1387 && !actual.has_concrete_skeleton()
1388 && let SelfSource::MethodCall(expr) = source
1390 let mut err = struct_span_err!(
1394 "can't call {} `{}` on ambiguous numeric type `{}`",
1399 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1401 ExprKind::Lit(ref lit) => {
1406 .span_to_snippet(lit.span)
1407 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1409 // If this is a floating point literal that ends with '.',
1410 // get rid of it to stop this from becoming a member access.
1411 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1412 err.span_suggestion(
1415 "you must specify a concrete type for this numeric value, \
1419 format!("{snippet}_{concrete_type}"),
1420 Applicability::MaybeIncorrect,
1423 ExprKind::Path(QPath::Resolved(_, path)) => {
1425 if let hir::def::Res::Local(hir_id) = path.res {
1426 let span = tcx.hir().span(hir_id);
1427 let filename = tcx.sess.source_map().span_to_filename(span);
1430 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1432 "you must specify a type for this binding, like `{}`",
1436 match (filename, parent_node) {
1439 Node::Local(hir::Local {
1440 source: hir::LocalSource::Normal,
1445 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1446 err.span_suggestion(
1447 // account for `let x: _ = 42;`
1451 format!(": {concrete_type}"),
1452 Applicability::MaybeIncorrect,
1456 err.span_label(span, msg);
1469 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1470 fn suggest_calling_method_on_field(
1472 err: &mut Diagnostic,
1473 source: SelfSource<'tcx>,
1478 if let SelfSource::MethodCall(expr) = source
1479 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1480 && let Some((fields, substs)) =
1481 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1483 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1485 let lang_items = self.tcx.lang_items();
1486 let never_mention_traits = [
1487 lang_items.clone_trait(),
1488 lang_items.deref_trait(),
1489 lang_items.deref_mut_trait(),
1490 self.tcx.get_diagnostic_item(sym::AsRef),
1491 self.tcx.get_diagnostic_item(sym::AsMut),
1492 self.tcx.get_diagnostic_item(sym::Borrow),
1493 self.tcx.get_diagnostic_item(sym::BorrowMut),
1495 let candidate_fields: Vec<_> = fields
1496 .filter_map(|candidate_field| {
1497 self.check_for_nested_field_satisfying(
1504 ProbeScope::TraitsInScope,
1506 .map_or(false, |pick| {
1507 !never_mention_traits
1510 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1522 .map(|id| id.name.to_ident_string())
1523 .collect::<Vec<String>>()
1528 let len = candidate_fields.len();
1530 err.span_suggestions(
1531 item_name.span.shrink_to_lo(),
1533 "{} of the expressions' fields {} a method of the same name",
1534 if len > 1 { "some" } else { "one" },
1535 if len > 1 { "have" } else { "has" },
1537 candidate_fields.iter().map(|path| format!("{path}.")),
1538 Applicability::MaybeIncorrect,
1544 fn check_for_inner_self(
1546 err: &mut Diagnostic,
1547 source: SelfSource<'tcx>,
1552 let SelfSource::MethodCall(expr) = source else { return; };
1553 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1555 let ty::Adt(kind, substs) = actual.kind() else { return; };
1556 match kind.adt_kind() {
1557 ty::AdtKind::Enum => {
1558 let matching_variants: Vec<_> = kind
1561 .flat_map(|variant| {
1562 let [field] = &variant.fields[..] else { return None; };
1563 let field_ty = field.ty(tcx, substs);
1565 // Skip `_`, since that'll just lead to ambiguity.
1566 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1570 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1572 .map(|pick| (variant, field, pick))
1576 let ret_ty_matches = |diagnostic_item| {
1577 if let Some(ret_ty) = self
1580 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1581 && let ty::Adt(kind, _) = ret_ty.kind()
1582 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1590 match &matching_variants[..] {
1591 [(_, field, pick)] => {
1592 let self_ty = field.ty(tcx, substs);
1594 tcx.def_span(pick.item.def_id),
1595 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1597 let (article, kind, variant, question) =
1598 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1599 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1600 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1601 ("an", "Option", "None", ret_ty_matches(sym::Option))
1606 err.span_suggestion_verbose(
1607 expr.span.shrink_to_hi(),
1609 "use the `?` operator to extract the `{self_ty}` value, propagating \
1610 {article} `{kind}::{variant}` value to the caller"
1613 Applicability::MachineApplicable,
1616 err.span_suggestion_verbose(
1617 expr.span.shrink_to_hi(),
1619 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1620 panicking if the value is {article} `{kind}::{variant}`"
1622 ".expect(\"REASON\")",
1623 Applicability::HasPlaceholders,
1627 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1631 // Target wrapper types - types that wrap or pretend to wrap another type,
1632 // perhaps this inner type is meant to be called?
1633 ty::AdtKind::Struct | ty::AdtKind::Union => {
1634 let [first] = ***substs else { return; };
1635 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1636 let Ok(pick) = self.lookup_probe(
1640 ProbeScope::TraitsInScope,
1643 let name = self.ty_to_value_string(actual);
1644 let inner_id = kind.did();
1645 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1646 pick.autoref_or_ptr_adjustment
1653 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1654 err.help("use `with` or `try_with` to access thread local storage");
1655 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1657 "if this `{name}` has been initialized, \
1658 use one of the `assume_init` methods to access the inner value"
1660 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1661 let (suggestion, borrow_kind, panic_if) = match mutable {
1662 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1663 Some(Mutability::Mut) => {
1664 (".borrow_mut()", "mutably borrow", "any borrows exist")
1668 err.span_suggestion_verbose(
1669 expr.span.shrink_to_hi(),
1671 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1672 panicking if {panic_if}"
1675 Applicability::MaybeIncorrect,
1677 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1678 err.span_suggestion_verbose(
1679 expr.span.shrink_to_hi(),
1681 "use `.lock().unwrap()` to borrow the `{ty}`, \
1682 blocking the current thread until it can be acquired"
1685 Applicability::MaybeIncorrect,
1687 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1688 let (suggestion, borrow_kind) = match mutable {
1689 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1690 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1693 err.span_suggestion_verbose(
1694 expr.span.shrink_to_hi(),
1696 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1697 blocking the current thread until it can be acquired"
1700 Applicability::MaybeIncorrect,
1707 tcx.def_span(pick.item.def_id),
1708 &format!("the method `{item_name}` exists on the type `{ty}`"),
1714 pub(crate) fn note_unmet_impls_on_type(
1716 err: &mut Diagnostic,
1717 errors: Vec<FulfillmentError<'tcx>>,
1719 let all_local_types_needing_impls =
1720 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1721 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1722 ty::Adt(def, _) => def.did().is_local(),
1727 let mut preds: Vec<_> = errors
1729 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1730 ty::PredicateKind::Trait(pred) => Some(pred),
1734 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1737 .filter_map(|pred| match pred.self_ty().kind() {
1738 ty::Adt(def, _) => Some(def.did()),
1741 .collect::<FxHashSet<_>>();
1742 let mut spans: MultiSpan = def_ids
1744 .filter_map(|def_id| {
1745 let span = self.tcx.def_span(*def_id);
1746 if span.is_dummy() { None } else { Some(span) }
1748 .collect::<Vec<_>>()
1751 for pred in &preds {
1752 match pred.self_ty().kind() {
1753 ty::Adt(def, _) if def.did().is_local() => {
1754 spans.push_span_label(
1755 self.tcx.def_span(def.did()),
1756 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1763 if all_local_types_needing_impls && spans.primary_span().is_some() {
1764 let msg = if preds.len() == 1 {
1766 "an implementation of `{}` might be missing for `{}`",
1767 preds[0].trait_ref.print_only_trait_path(),
1772 "the following type{} would have to `impl` {} required trait{} for this \
1773 operation to be valid",
1774 pluralize!(def_ids.len()),
1775 if def_ids.len() == 1 { "its" } else { "their" },
1776 pluralize!(preds.len()),
1779 err.span_note(spans, &msg);
1782 let preds: Vec<_> = errors
1784 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1786 self.suggest_derive(err, &preds);
1791 err: &mut Diagnostic,
1792 unsatisfied_predicates: &[(
1793 ty::Predicate<'tcx>,
1794 Option<ty::Predicate<'tcx>>,
1795 Option<ObligationCause<'tcx>>,
1798 let mut derives = Vec::<(String, Span, Symbol)>::new();
1799 let mut traits = Vec::<Span>::new();
1800 for (pred, _, _) in unsatisfied_predicates {
1801 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1802 let adt = match trait_pred.self_ty().ty_adt_def() {
1803 Some(adt) if adt.did().is_local() => adt,
1806 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1807 let can_derive = match diagnostic_name {
1808 sym::Default => !adt.is_enum(),
1816 | sym::Debug => true,
1820 let self_name = trait_pred.self_ty().to_string();
1821 let self_span = self.tcx.def_span(adt.did());
1822 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1823 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1825 if let Some(parent_diagnostic_name) =
1826 self.tcx.get_diagnostic_name(super_trait.def_id())
1831 parent_diagnostic_name,
1836 derives.push((self_name, self_span, diagnostic_name));
1838 traits.push(self.tcx.def_span(trait_pred.def_id()));
1841 traits.push(self.tcx.def_span(trait_pred.def_id()));
1850 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1851 for (self_name, self_span, trait_name) in derives.into_iter() {
1852 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1854 if last_self_name == &self_name {
1855 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1859 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1862 let len = traits.len();
1864 let span: MultiSpan = traits.into();
1867 &format!("the following trait{} must be implemented", pluralize!(len),),
1871 for (self_name, self_span, traits) in &derives_grouped {
1872 err.span_suggestion_verbose(
1873 self_span.shrink_to_lo(),
1874 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1875 format!("#[derive({})]\n", traits),
1876 Applicability::MaybeIncorrect,
1881 fn check_for_deref_method(
1883 err: &mut Diagnostic,
1884 self_source: SelfSource<'tcx>,
1888 let SelfSource::QPath(ty) = self_source else { return; };
1889 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1890 if let Ok(pick) = self.probe_for_name(
1896 ProbeScope::TraitsInScope,
1898 if deref_ty.is_suggestable(self.tcx, true)
1899 // If this method receives `&self`, then the provided
1900 // argument _should_ coerce, so it's valid to suggest
1901 // just changing the path.
1902 && pick.item.fn_has_self_parameter
1903 && let Some(self_ty) =
1904 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1907 let suggested_path = match deref_ty.kind() {
1916 | ty::Param(_) => format!("{deref_ty}"),
1917 // we need to test something like <&[_]>::len
1918 // and Vec::function();
1919 // <&[_]>::len doesn't need an extra "<>" between
1920 // but for Adt type like Vec::function()
1921 // we would suggest <[_]>::function();
1922 _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
1923 _ => format!("<{deref_ty}>"),
1925 err.span_suggestion_verbose(
1927 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1929 Applicability::MaybeIncorrect,
1934 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1942 /// Print out the type for use in value namespace.
1943 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1945 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1946 _ => self.ty_to_string(ty),
1950 fn suggest_await_before_method(
1952 err: &mut Diagnostic,
1955 call: &hir::Expr<'_>,
1958 let output_ty = match self.get_impl_future_output_ty(ty) {
1959 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1962 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1963 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1965 err.span_suggestion_verbose(
1966 span.shrink_to_lo(),
1967 "consider `await`ing on the `Future` and calling the method on its `Output`",
1969 Applicability::MaybeIncorrect,
1974 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1975 let parent_map = self.tcx.visible_parent_map(());
1977 // Separate out candidates that must be imported with a glob, because they are named `_`
1978 // and cannot be referred with their identifier.
1979 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1980 if let Some(parent_did) = parent_map.get(trait_did) {
1981 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1982 if *parent_did != self.tcx.parent(*trait_did)
1985 .module_children(*parent_did)
1987 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1988 .all(|child| child.ident.name == kw::Underscore)
1997 let module_did = self.tcx.parent_module(self.body_id);
1998 let (module, _, _) = self.tcx.hir().get_module(module_did);
1999 let span = module.spans.inject_use_span;
2001 let path_strings = candidates.iter().map(|trait_did| {
2002 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2005 let glob_path_strings = globs.iter().map(|trait_did| {
2006 let parent_did = parent_map.get(trait_did).unwrap();
2008 "use {}::*; // trait {}\n",
2009 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2010 self.tcx.item_name(*trait_did),
2014 err.span_suggestions(
2017 path_strings.chain(glob_path_strings),
2018 Applicability::MaybeIncorrect,
2022 fn suggest_valid_traits(
2024 err: &mut Diagnostic,
2025 valid_out_of_scope_traits: Vec<DefId>,
2027 if !valid_out_of_scope_traits.is_empty() {
2028 let mut candidates = valid_out_of_scope_traits;
2032 // `TryFrom` and `FromIterator` have no methods
2033 let edition_fix = candidates
2035 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2038 err.help("items from traits can only be used if the trait is in scope");
2040 "the following {traits_are} implemented but not in scope; \
2041 perhaps add a `use` for {one_of_them}:",
2042 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2043 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2046 self.suggest_use_candidates(err, msg, candidates);
2047 if let Some(did) = edition_fix {
2049 "'{}' is included in the prelude starting in Edition 2021",
2050 with_crate_prefix!(self.tcx.def_path_str(did))
2060 fn suggest_traits_to_import(
2062 err: &mut Diagnostic,
2066 inputs_len: Option<usize>,
2067 source: SelfSource<'tcx>,
2068 valid_out_of_scope_traits: Vec<DefId>,
2069 unsatisfied_predicates: &[(
2070 ty::Predicate<'tcx>,
2071 Option<ty::Predicate<'tcx>>,
2072 Option<ObligationCause<'tcx>>,
2074 static_candidates: &[CandidateSource],
2075 unsatisfied_bounds: bool,
2077 let mut alt_rcvr_sugg = false;
2078 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2080 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2081 span, item_name, rcvr_ty, rcvr
2084 self.tcx.lang_items().clone_trait(),
2085 self.tcx.lang_items().deref_trait(),
2086 self.tcx.lang_items().deref_mut_trait(),
2087 self.tcx.lang_items().drop_trait(),
2088 self.tcx.get_diagnostic_item(sym::AsRef),
2090 // Try alternative arbitrary self types that could fulfill this call.
2091 // FIXME: probe for all types that *could* be arbitrary self-types, not
2093 for (rcvr_ty, post) in &[
2095 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2096 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2098 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2100 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2101 // We point at the method, but we just skip the rest of the check for arbitrary
2102 // self types and rely on the suggestion to `use` the trait from
2103 // `suggest_valid_traits`.
2104 let did = Some(pick.item.container_id(self.tcx));
2105 let skip = skippable.contains(&did);
2106 if pick.autoderefs == 0 && !skip {
2108 pick.item.ident(self.tcx).span,
2109 &format!("the method is available for `{}` here", rcvr_ty),
2114 Err(MethodError::Ambiguity(_)) => {
2115 // If the method is defined (but ambiguous) for the receiver we have, it is also
2116 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2117 // the receiver, then it might disambiguate this method, but I think these
2118 // suggestions are generally misleading (see #94218).
2124 for (rcvr_ty, pre) in &[
2125 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2126 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2127 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2128 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2130 if let Some(new_rcvr_t) = *rcvr_ty
2131 && let Ok(pick) = self.lookup_probe(
2135 ProbeScope::AllTraits,
2138 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2139 let did = Some(pick.item.container_id(self.tcx));
2140 // We don't want to suggest a container type when the missing
2141 // method is `.clone()` or `.deref()` otherwise we'd suggest
2142 // `Arc::new(foo).clone()`, which is far from what the user wants.
2143 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2144 // implement the `AsRef` trait.
2145 let skip = skippable.contains(&did)
2146 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2147 || 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);
2148 // Make sure the method is defined for the *actual* receiver: we don't
2149 // want to treat `Box<Self>` as a receiver if it only works because of
2150 // an autoderef to `&self`
2151 if pick.autoderefs == 0 && !skip {
2153 pick.item.ident(self.tcx).span,
2154 &format!("the method is available for `{}` here", new_rcvr_t),
2156 err.multipart_suggestion(
2157 "consider wrapping the receiver expression with the \
2160 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2161 (rcvr.span.shrink_to_hi(), ")".to_string()),
2163 Applicability::MaybeIncorrect,
2165 // We don't care about the other suggestions.
2166 alt_rcvr_sugg = true;
2172 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2176 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2178 let mut arbitrary_rcvr = vec![];
2179 // There are no traits implemented, so lets suggest some traits to
2180 // implement, by finding ones that have the item name, and are
2181 // legal to implement.
2182 let mut candidates = all_traits(self.tcx)
2184 // Don't issue suggestions for unstable traits since they're
2185 // unlikely to be implementable anyway
2186 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2187 Some(attr) => attr.level.is_stable(),
2191 // Static candidates are already implemented, and known not to work
2192 // Do not suggest them again
2193 static_candidates.iter().all(|sc| match *sc {
2194 CandidateSource::Trait(def_id) => def_id != info.def_id,
2195 CandidateSource::Impl(def_id) => {
2196 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2201 // We approximate the coherence rules to only suggest
2202 // traits that are legal to implement by requiring that
2203 // either the type or trait is local. Multi-dispatch means
2204 // this isn't perfect (that is, there are cases when
2205 // implementing a trait would be legal but is rejected
2207 unsatisfied_predicates.iter().all(|(p, _, _)| {
2208 match p.kind().skip_binder() {
2209 // Hide traits if they are present in predicates as they can be fixed without
2210 // having to implement them.
2211 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2212 ty::PredicateKind::Projection(p) => {
2213 p.projection_ty.item_def_id == info.def_id
2217 }) && (type_is_local || info.def_id.is_local())
2219 .associated_value(info.def_id, item_name)
2221 if let ty::AssocKind::Fn = item.kind {
2225 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2226 if let Some(hir::Node::TraitItem(hir::TraitItem {
2227 kind: hir::TraitItemKind::Fn(fn_sig, method),
2229 })) = id.map(|id| self.tcx.hir().get(id))
2231 let self_first_arg = match method {
2232 hir::TraitFn::Required([ident, ..]) => {
2233 ident.name == kw::SelfLower
2235 hir::TraitFn::Provided(body_id) => {
2236 self.tcx.hir().body(*body_id).params.first().map_or(
2241 hir::PatKind::Binding(_, _, ident, _)
2242 if ident.name == kw::SelfLower
2250 if !fn_sig.decl.implicit_self.has_implicit_self()
2253 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2254 arbitrary_rcvr.push(ty.span);
2260 // We only want to suggest public or local traits (#45781).
2261 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2265 .collect::<Vec<_>>();
2266 for span in &arbitrary_rcvr {
2269 "the method might not be found because of this arbitrary self type",
2276 if !candidates.is_empty() {
2277 // Sort from most relevant to least relevant.
2278 candidates.sort_by(|a, b| a.cmp(b).reverse());
2281 let param_type = match rcvr_ty.kind() {
2282 ty::Param(param) => Some(param),
2283 ty::Ref(_, ty, _) => match ty.kind() {
2284 ty::Param(param) => Some(param),
2289 err.help(if param_type.is_some() {
2290 "items from traits can only be used if the type parameter is bounded by the trait"
2292 "items from traits can only be used if the trait is implemented and in scope"
2294 let candidates_len = candidates.len();
2295 let message = |action| {
2297 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2300 if candidates_len == 1 { "trait defines" } else { "traits define" },
2302 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2306 // Obtain the span for `param` and use it for a structured suggestion.
2307 if let Some(param) = param_type {
2308 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2309 let type_param = generics.type_param(param, self.tcx);
2310 let hir = self.tcx.hir();
2311 if let Some(def_id) = type_param.def_id.as_local() {
2312 let id = hir.local_def_id_to_hir_id(def_id);
2313 // Get the `hir::Param` to verify whether it already has any bounds.
2314 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2315 // instead we suggest `T: Foo + Bar` in that case.
2317 Node::GenericParam(param) => {
2323 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2324 let (sp, mut introducer) = if let Some(span) =
2325 ast_generics.bounds_span_for_suggestions(def_id)
2327 (span, Introducer::Plus)
2328 } else if let Some(colon_span) = param.colon_span {
2329 (colon_span.shrink_to_hi(), Introducer::Nothing)
2331 (param.span.shrink_to_hi(), Introducer::Colon)
2335 hir::GenericParamKind::Type { synthetic: true, .. },
2337 introducer = Introducer::Plus
2339 let trait_def_ids: FxHashSet<DefId> = ast_generics
2340 .bounds_for_param(def_id)
2341 .flat_map(|bp| bp.bounds.iter())
2342 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2344 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2345 err.span_suggestions(
2348 "restrict type parameter `{}` with",
2351 candidates.iter().map(|t| {
2355 Introducer::Plus => " +",
2356 Introducer::Colon => ":",
2357 Introducer::Nothing => "",
2359 self.tcx.def_path_str(t.def_id),
2362 Applicability::MaybeIncorrect,
2367 Node::Item(hir::Item {
2368 kind: hir::ItemKind::Trait(.., bounds, _),
2372 let (sp, sep, article) = if bounds.is_empty() {
2373 (ident.span.shrink_to_hi(), ":", "a")
2375 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2377 err.span_suggestions(
2379 &message(format!("add {} supertrait for", article)),
2380 candidates.iter().map(|t| {
2381 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2383 Applicability::MaybeIncorrect,
2392 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2393 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2394 // cases where a positive bound implies a negative impl.
2395 (candidates, Vec::new())
2396 } else if let Some(simp_rcvr_ty) =
2397 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2399 let mut potential_candidates = Vec::new();
2400 let mut explicitly_negative = Vec::new();
2401 for candidate in candidates {
2402 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2405 .all_impls(candidate.def_id)
2407 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2410 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2412 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2413 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2416 explicitly_negative.push(candidate);
2418 potential_candidates.push(candidate);
2421 (potential_candidates, explicitly_negative)
2423 // We don't know enough about `recv_ty` to make proper suggestions.
2424 (candidates, Vec::new())
2427 let action = if let Some(param) = param_type {
2428 format!("restrict type parameter `{}` with", param)
2430 // FIXME: it might only need to be imported into scope, not implemented.
2431 "implement".to_string()
2433 match &potential_candidates[..] {
2435 [trait_info] if trait_info.def_id.is_local() => {
2437 self.tcx.def_span(trait_info.def_id),
2439 "`{}` defines an item `{}`, perhaps you need to {} it",
2440 self.tcx.def_path_str(trait_info.def_id),
2447 let mut msg = message(action);
2448 for (i, trait_info) in trait_infos.iter().enumerate() {
2449 msg.push_str(&format!(
2450 "\ncandidate #{}: `{}`",
2452 self.tcx.def_path_str(trait_info.def_id),
2458 match &explicitly_negative[..] {
2462 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2463 self.tcx.def_path_str(trait_info.def_id),
2469 let mut msg = format!(
2470 "the following traits define an item `{}`, but are explicitly unimplemented:",
2473 for trait_info in trait_infos {
2474 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2482 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2483 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2484 pub(crate) fn suggest_else_fn_with_closure(
2486 err: &mut Diagnostic,
2487 expr: &hir::Expr<'_>,
2491 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2492 else { return false; };
2494 if !self.can_coerce(output, expected) {
2498 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2499 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2500 let hir::ExprKind::MethodCall(
2501 hir::PathSegment { ident: method_name, .. },
2505 ) = call_expr.kind &&
2506 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2507 let new_name = Ident {
2508 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2509 span: method_name.span,
2511 let probe = self.lookup_probe(
2515 ProbeScope::TraitsInScope,
2518 // check the method arguments number
2519 if let Ok(pick) = probe &&
2520 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2521 let fn_args = fn_sig.skip_binder().inputs() &&
2522 fn_args.len() == args.len() + 1 {
2523 err.span_suggestion_verbose(
2524 method_name.span.shrink_to_hi(),
2525 &format!("try calling `{}` instead", new_name.name.as_str()),
2527 Applicability::MaybeIncorrect,
2535 /// Checks whether there is a local type somewhere in the chain of
2536 /// autoderefs of `rcvr_ty`.
2537 fn type_derefs_to_local(
2541 source: SelfSource<'tcx>,
2543 fn is_local(ty: Ty<'_>) -> bool {
2545 ty::Adt(def, _) => def.did().is_local(),
2546 ty::Foreign(did) => did.is_local(),
2547 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2548 ty::Param(_) => true,
2550 // Everything else (primitive types, etc.) is effectively
2551 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2552 // the noise from these sort of types is usually just really
2553 // annoying, rather than any sort of help).
2558 // This occurs for UFCS desugaring of `T::method`, where there is no
2559 // receiver expression for the method call, and thus no autoderef.
2560 if let SelfSource::QPath(_) = source {
2561 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2564 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2568 #[derive(Copy, Clone, Debug)]
2569 pub enum SelfSource<'a> {
2570 QPath(&'a hir::Ty<'a>),
2571 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2574 #[derive(Copy, Clone)]
2575 pub struct TraitInfo {
2579 impl PartialEq for TraitInfo {
2580 fn eq(&self, other: &TraitInfo) -> bool {
2581 self.cmp(other) == Ordering::Equal
2584 impl Eq for TraitInfo {}
2585 impl PartialOrd for TraitInfo {
2586 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2587 Some(self.cmp(other))
2590 impl Ord for TraitInfo {
2591 fn cmp(&self, other: &TraitInfo) -> Ordering {
2592 // Local crates are more important than remote ones (local:
2593 // `cnum == 0`), and otherwise we throw in the defid for totality.
2595 let lhs = (other.def_id.krate, other.def_id);
2596 let rhs = (self.def_id.krate, self.def_id);
2601 /// Retrieves all traits in this crate and any dependent crates,
2602 /// and wraps them into `TraitInfo` for custom sorting.
2603 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2604 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2607 fn print_disambiguation_help<'tcx>(
2609 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2610 err: &mut Diagnostic,
2613 kind: ty::AssocKind,
2616 candidate: Option<usize>,
2617 source_map: &source_map::SourceMap,
2618 fn_has_self_parameter: bool,
2620 let mut applicability = Applicability::MachineApplicable;
2621 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2624 if rcvr_ty.is_region_ptr() {
2625 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2629 std::iter::once(receiver)
2631 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2632 applicability = Applicability::HasPlaceholders;
2635 .collect::<Vec<_>>()
2638 let trait_name = if !fn_has_self_parameter {
2639 format!("<{} as {}>", rcvr_ty, trait_name)
2643 (span, format!("{}::{}{}", trait_name, item_name, args))
2645 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2647 err.span_suggestion_verbose(
2650 "disambiguate the {} for {}",
2651 kind.as_def_kind().descr(def_id),
2652 if let Some(candidate) = candidate {
2653 format!("candidate #{}", candidate)
2655 "the candidate".to_string()