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, 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(
87 poly_trait_ref.without_const(),
89 self.predicate_may_hold(&obligation)
96 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
97 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
100 pub fn report_method_error(
105 source: SelfSource<'tcx>,
106 error: MethodError<'tcx>,
107 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
108 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
109 // Avoid suggestions when we don't know what's going on.
110 if rcvr_ty.references_error() {
114 let report_candidates = |span: Span,
115 err: &mut Diagnostic,
116 sources: &mut Vec<CandidateSource>,
120 // Dynamic limit to avoid hiding just one candidate, which is silly.
121 let limit = if sources.len() == 5 { 5 } else { 4 };
123 for (idx, source) in sources.iter().take(limit).enumerate() {
125 CandidateSource::Impl(impl_did) => {
126 // Provide the best span we can. Use the item, if local to crate, else
127 // the impl, if local to crate (item may be defaulted), else nothing.
128 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
129 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
130 self.associated_value(impl_trait_ref.def_id, item_name)
135 let note_span = if item.def_id.is_local() {
136 Some(self.tcx.def_span(item.def_id))
137 } else if impl_did.is_local() {
138 Some(self.tcx.def_span(impl_did))
143 let impl_ty = self.tcx.at(span).type_of(impl_did);
145 let insertion = match self.tcx.impl_trait_ref(impl_did) {
146 None => String::new(),
147 Some(trait_ref) => format!(
148 " of the trait `{}`",
149 self.tcx.def_path_str(trait_ref.def_id)
153 let (note_str, idx) = if sources.len() > 1 {
156 "candidate #{} is defined in an impl{} for the type `{}`",
166 "the candidate is defined in an impl{} for the type `{}`",
172 if let Some(note_span) = note_span {
173 // We have a span pointing to the method. Show note with snippet.
174 err.span_note(note_span, ¬e_str);
178 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
179 let path = self.tcx.def_path_str(trait_ref.def_id);
181 let ty = match item.kind {
182 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
183 ty::AssocKind::Fn => self
189 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
193 print_disambiguation_help(
203 self.tcx.sess.source_map(),
204 item.fn_has_self_parameter,
208 CandidateSource::Trait(trait_did) => {
209 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
210 let item_span = self.tcx.def_span(item.def_id);
211 let idx = if sources.len() > 1 {
213 "candidate #{} is defined in the trait `{}`",
215 self.tcx.def_path_str(trait_did)
217 err.span_note(item_span, msg);
221 "the candidate is defined in the trait `{}`",
222 self.tcx.def_path_str(trait_did)
224 err.span_note(item_span, msg);
227 let path = self.tcx.def_path_str(trait_did);
228 print_disambiguation_help(
238 self.tcx.sess.source_map(),
239 item.fn_has_self_parameter,
244 if sources.len() > limit {
245 err.note(&format!("and {} others", sources.len() - limit));
249 let sugg_span = if let SelfSource::MethodCall(expr) = source {
250 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
251 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
257 MethodError::NoMatch(NoMatchData {
258 mut static_candidates,
259 unsatisfied_predicates,
266 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
267 let ty_str = self.ty_to_string(rcvr_ty);
268 let is_method = mode == Mode::MethodCall;
269 let item_kind = if is_method {
271 } else if rcvr_ty.is_enum() {
272 "variant or associated item"
274 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
275 (Some(name), false) if name.is_lowercase() => "function or associated item",
276 (Some(_), false) => "associated item",
277 (Some(_), true) | (None, false) => "variant or associated item",
278 (None, true) => "variant",
282 if self.suggest_wrapping_range_with_parens(
283 tcx, rcvr_ty, source, span, item_name, &ty_str,
284 ) || self.suggest_constraining_numerical_ty(
285 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
289 span = item_name.span;
291 // Don't show generic arguments when the method can't be found in any implementation (#81576).
292 let mut ty_str_reported = ty_str.clone();
293 if let ty::Adt(_, generics) = rcvr_ty.kind() {
294 if generics.len() > 0 {
295 let mut autoderef = self.autoderef(span, rcvr_ty);
296 let candidate_found = autoderef.any(|(ty, _)| {
297 if let ty::Adt(adt_def, _) = ty.kind() {
299 .inherent_impls(adt_def.did())
301 .filter_map(|def_id| self.associated_value(*def_id, item_name))
308 let has_deref = autoderef.step_count() > 0;
309 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
310 if let Some((path_string, _)) = ty_str.split_once('<') {
311 ty_str_reported = path_string.to_string();
317 let mut err = struct_span_err!(
321 "no {} named `{}` found for {} `{}` in the current scope",
324 rcvr_ty.prefix_string(self.tcx),
327 if rcvr_ty.references_error() {
328 err.downgrade_to_delayed_bug();
331 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
332 self.suggest_await_before_method(
333 &mut err, item_name, rcvr_ty, cal, span,
336 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
339 "you are looking for the module in `std`, not the primitive type",
341 Applicability::MachineApplicable,
344 if let ty::RawPtr(_) = &rcvr_ty.kind() {
346 "try using `<*const T>::as_ref()` to get a reference to the \
347 type behind the pointer: https://doc.rust-lang.org/std/\
348 primitive.pointer.html#method.as_ref",
351 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
352 to invalid or uninitialized memory is undefined behavior",
356 let ty_span = match rcvr_ty.kind() {
357 ty::Param(param_type) => Some(
358 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
360 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
363 if let Some(span) = ty_span {
367 "{item_kind} `{item_name}` not found for this {}",
368 rcvr_ty.prefix_string(self.tcx)
373 if let SelfSource::MethodCall(rcvr_expr) = source {
374 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
378 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
379 let probe = self.lookup_probe(
384 ProbeScope::AllTraits,
390 let mut custom_span_label = false;
392 if !static_candidates.is_empty() {
394 "found the following associated functions; to be used as methods, \
395 functions must have a `self` parameter",
397 err.span_label(span, "this is an associated function, not a method");
398 custom_span_label = true;
400 if static_candidates.len() == 1 {
401 self.suggest_associated_call_syntax(
411 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
412 } else if static_candidates.len() > 1 {
413 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
416 let mut bound_spans = vec![];
417 let mut restrict_type_params = false;
418 let mut unsatisfied_bounds = false;
419 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
420 let msg = "consider using `len` instead";
421 if let SelfSource::MethodCall(_expr) = source {
422 err.span_suggestion_short(
426 Applicability::MachineApplicable,
429 err.span_label(span, msg);
431 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
432 let iterator_trait = self.tcx.def_path_str(iterator_trait);
433 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
435 } else if !unsatisfied_predicates.is_empty() {
436 let mut type_params = FxHashMap::default();
438 // Pick out the list of unimplemented traits on the receiver.
439 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
440 let mut unimplemented_traits = FxHashMap::default();
441 let mut unimplemented_traits_only = true;
442 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
443 if let (ty::PredicateKind::Trait(p), Some(cause)) =
444 (predicate.kind().skip_binder(), cause.as_ref())
446 if p.trait_ref.self_ty() != rcvr_ty {
447 // This is necessary, not just to keep the errors clean, but also
448 // because our derived obligations can wind up with a trait ref that
449 // requires a different param_env to be correctly compared.
452 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
453 predicate.kind().rebind(p.trait_ref),
455 cause: cause.clone(),
456 param_env: self.param_env,
457 predicate: *predicate,
464 // Make sure that, if any traits other than the found ones were involved,
465 // we don't don't report an unimplemented trait.
466 // We don't want to say that `iter::Cloned` is not an iterator, just
467 // because of some non-Clone item being iterated over.
468 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
469 match predicate.kind().skip_binder() {
470 ty::PredicateKind::Trait(p)
471 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
473 unimplemented_traits_only = false;
479 let mut collect_type_param_suggestions =
480 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
481 // We don't care about regions here, so it's fine to skip the binder here.
482 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
483 (self_ty.kind(), parent_pred.kind().skip_binder())
485 let hir = self.tcx.hir();
486 let node = match p.trait_ref.self_ty().kind() {
488 // Account for `fn` items like in `issue-35677.rs` to
489 // suggest restricting its type params.
491 hir.body_owner(hir::BodyId { hir_id: self.body_id });
492 Some(hir.get(parent_body))
495 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
499 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
500 if let Some(g) = kind.generics() {
502 g.tail_span_for_predicate_suggestion(),
503 g.add_where_or_trailing_comma(),
507 .or_insert_with(FxHashSet::default)
508 .insert(obligation.to_owned());
513 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
515 "doesn't satisfy `{}`",
516 if obligation.len() > 50 { quiet } else { obligation }
518 match &self_ty.kind() {
519 // Point at the type that couldn't satisfy the bound.
521 bound_spans.push((self.tcx.def_span(def.did()), msg))
523 // Point at the trait object that couldn't satisfy the bound.
524 ty::Dynamic(preds, _, _) => {
525 for pred in preds.iter() {
526 match pred.skip_binder() {
527 ty::ExistentialPredicate::Trait(tr) => bound_spans
528 .push((self.tcx.def_span(tr.def_id), msg.clone())),
529 ty::ExistentialPredicate::Projection(_)
530 | ty::ExistentialPredicate::AutoTrait(_) => {}
534 // Point at the closure that couldn't satisfy the bound.
535 ty::Closure(def_id, _) => bound_spans.push((
536 tcx.def_span(*def_id),
537 format!("doesn't satisfy `{}`", quiet),
542 let mut format_pred = |pred: ty::Predicate<'tcx>| {
543 let bound_predicate = pred.kind();
544 match bound_predicate.skip_binder() {
545 ty::PredicateKind::Projection(pred) => {
546 let pred = bound_predicate.rebind(pred);
547 // `<Foo as Iterator>::Item = String`.
548 let projection_ty = pred.skip_binder().projection_ty;
550 let substs_with_infer_self = tcx.mk_substs(
551 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
552 .chain(projection_ty.substs.iter().skip(1)),
555 let quiet_projection_ty = ty::ProjectionTy {
556 substs: substs_with_infer_self,
557 item_def_id: projection_ty.item_def_id,
560 let term = pred.skip_binder().term;
562 let obligation = format!("{} = {}", projection_ty, term);
563 let quiet = format!("{} = {}", quiet_projection_ty, term);
565 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
566 Some((obligation, projection_ty.self_ty()))
568 ty::PredicateKind::Trait(poly_trait_ref) => {
569 let p = poly_trait_ref.trait_ref;
570 let self_ty = p.self_ty();
571 let path = p.print_only_trait_path();
572 let obligation = format!("{}: {}", self_ty, path);
573 let quiet = format!("_: {}", path);
574 bound_span_label(self_ty, &obligation, &quiet);
575 Some((obligation, self_ty))
581 // Find all the requirements that come from a local `impl` block.
582 let mut skip_list: FxHashSet<_> = Default::default();
583 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
584 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
586 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
587 .filter_map(|(p, parent, c)| match c.code() {
588 ObligationCauseCode::ImplDerivedObligation(data) => {
589 Some((&data.derived, p, parent, data.impl_def_id, data))
594 let parent_trait_ref = data.parent_trait_pred;
595 let path = parent_trait_ref.print_modifiers_and_trait_path();
596 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
597 let unsatisfied_msg = "unsatisfied trait bound introduced here";
599 "unsatisfied trait bound introduced in this `derive` macro";
600 match self.tcx.hir().get_if_local(impl_def_id) {
601 // Unmet obligation comes from a `derive` macro, point at it once to
602 // avoid multiple span labels pointing at the same place.
603 Some(Node::Item(hir::Item {
604 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
607 self_ty.span.ctxt().outer_expn_data().kind,
608 ExpnKind::Macro(MacroKind::Derive, _)
610 of_trait.as_ref().map(|t| t
616 Some(ExpnKind::Macro(MacroKind::Derive, _))
619 let span = self_ty.span.ctxt().outer_expn_data().call_site;
620 let mut spans: MultiSpan = span.into();
621 spans.push_span_label(span, derive_msg);
622 let entry = spanned_predicates.entry(spans);
623 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
626 // Unmet obligation coming from an `impl`.
627 Some(Node::Item(hir::Item {
629 hir::ItemKind::Impl(hir::Impl {
630 of_trait, self_ty, generics, ..
636 unsatisfied_predicates.iter().any(|(pred, _, _)| {
637 match pred.kind().skip_binder() {
638 ty::PredicateKind::Trait(pred) => {
640 == self.tcx.lang_items().sized_trait()
641 && pred.polarity == ty::ImplPolarity::Positive
646 for param in generics.params {
647 if param.span == cause.span && sized_pred {
648 let (sp, sugg) = match param.colon_span {
649 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
650 None => (param.span.shrink_to_hi(), ": ?Sized"),
652 err.span_suggestion_verbose(
654 "consider relaxing the type parameter's implicit \
657 Applicability::MachineApplicable,
661 if let Some(pred) = parent_p {
662 // Done to add the "doesn't satisfy" `span_label`.
663 let _ = format_pred(*pred);
666 let mut spans = if cause.span != *item_span {
667 let mut spans: MultiSpan = cause.span.into();
668 spans.push_span_label(cause.span, unsatisfied_msg);
671 let mut spans = Vec::with_capacity(2);
672 if let Some(trait_ref) = of_trait {
673 spans.push(trait_ref.path.span);
675 spans.push(self_ty.span);
678 if let Some(trait_ref) = of_trait {
679 spans.push_span_label(trait_ref.path.span, "");
681 spans.push_span_label(self_ty.span, "");
683 let entry = spanned_predicates.entry(spans);
684 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
686 Some(_) => unreachable!(),
690 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
691 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
692 for (span, (_path, _self_ty, preds)) in spanned_predicates {
693 let mut preds: Vec<_> = preds
695 .filter_map(|pred| format_pred(*pred))
696 .map(|(p, _)| format!("`{}`", p))
700 let msg = if let [pred] = &preds[..] {
701 format!("trait bound {} was not satisfied", pred)
704 "the following trait bounds were not satisfied:\n{}",
708 err.span_note(span, &msg);
709 unsatisfied_bounds = true;
712 // The requirements that didn't have an `impl` span to show.
713 let mut bound_list = unsatisfied_predicates
715 .filter_map(|(pred, parent_pred, _cause)| {
716 format_pred(*pred).map(|(p, self_ty)| {
717 collect_type_param_suggestions(self_ty, *pred, &p);
720 None => format!("`{}`", &p),
721 Some(parent_pred) => match format_pred(*parent_pred) {
722 None => format!("`{}`", &p),
723 Some((parent_p, _)) => {
724 collect_type_param_suggestions(
730 "`{}`\nwhich is required by `{}`",
740 .filter(|(_, pred)| !skip_list.contains(&pred))
743 .collect::<Vec<(usize, String)>>();
745 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
746 restrict_type_params = true;
747 // #74886: Sort here so that the output is always the same.
748 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
750 err.span_suggestion_verbose(
753 "consider restricting the type parameter{s} to satisfy the \
755 s = pluralize!(obligations.len())
757 format!("{} {}", add_where_or_comma, obligations.join(", ")),
758 Applicability::MaybeIncorrect,
762 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
763 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
764 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
766 if !bound_list.is_empty() || !skip_list.is_empty() {
767 let bound_list = bound_list
769 .map(|(_, path)| path)
772 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
773 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
774 let (primary_message, label) =
775 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
779 .map(|(_, (trait_ref, obligation))| {
780 if trait_ref.self_ty().references_error()
781 || rcvr_ty.references_error()
786 let OnUnimplementedNote { message, label, .. } = self
788 .on_unimplemented_note(trait_ref, &obligation);
795 let primary_message = primary_message.unwrap_or_else(|| format!(
796 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
798 err.set_primary_message(&primary_message);
799 if let Some(label) = label {
800 custom_span_label = true;
801 err.span_label(span, label);
803 if !bound_list.is_empty() {
805 "the following trait bounds were not satisfied:\n{bound_list}"
808 self.suggest_derive(&mut err, &unsatisfied_predicates);
810 unsatisfied_bounds = true;
814 let label_span_not_found = |err: &mut Diagnostic| {
815 if unsatisfied_predicates.is_empty() {
816 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
817 let is_string_or_ref_str = match rcvr_ty.kind() {
818 ty::Ref(_, ty, _) => {
822 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
825 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
828 if is_string_or_ref_str && item_name.name == sym::iter {
829 err.span_suggestion_verbose(
831 "because of the in-memory representation of `&str`, to obtain \
832 an `Iterator` over each of its codepoint use method `chars`",
834 Applicability::MachineApplicable,
837 if let ty::Adt(adt, _) = rcvr_ty.kind() {
838 let mut inherent_impls_candidate = self
840 .inherent_impls(adt.did())
844 if let Some(assoc) = self.associated_value(*def_id, item_name) {
845 // Check for both mode is the same so we avoid suggesting
846 // incorrect associated item.
847 match (mode, assoc.fn_has_self_parameter, source) {
848 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
849 // We check that the suggest type is actually
850 // different from the received one
851 // So we avoid suggestion method with Box<Self>
853 self.tcx.at(span).type_of(*def_id) != rcvr_ty
854 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
856 (Mode::Path, false, _) => true,
863 .collect::<Vec<_>>();
864 if !inherent_impls_candidate.is_empty() {
865 inherent_impls_candidate.sort();
866 inherent_impls_candidate.dedup();
868 // number of type to shows at most.
869 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
870 let type_candidates = inherent_impls_candidate
874 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
878 let additional_types = if inherent_impls_candidate.len() > limit {
880 "\nand {} more types",
881 inherent_impls_candidate.len() - limit
887 "the {item_kind} was found for\n{}{}",
888 type_candidates, additional_types
893 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
897 // If the method name is the name of a field with a function or closure type,
898 // give a helping note that it has to be called as `(x.f)(...)`.
899 if let SelfSource::MethodCall(expr) = source {
900 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
901 && lev_candidate.is_none()
902 && !custom_span_label
904 label_span_not_found(&mut err);
906 } else if !custom_span_label {
907 label_span_not_found(&mut err);
910 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
911 // can't be called due to `typeof(expr): Clone` not holding.
912 if unsatisfied_predicates.is_empty() {
913 self.suggest_calling_method_on_field(
914 &mut err, source, span, rcvr_ty, item_name,
918 self.check_for_inner_self(&mut err, source, span, rcvr_ty, item_name);
922 for (span, msg) in bound_spans.into_iter() {
923 err.span_label(span, &msg);
926 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
928 self.suggest_traits_to_import(
933 args.map(|(_, args)| args.len() + 1),
936 &unsatisfied_predicates,
942 // Don't emit a suggestion if we found an actual method
943 // that had unsatisfied trait bounds
944 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
945 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
946 if let Some(suggestion) = lev_distance::find_best_match_for_name(
947 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
953 "there is a variant with a similar name",
955 Applicability::MaybeIncorrect,
960 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
961 let msg = "remove this method call";
962 let mut fallback_span = true;
963 if let SelfSource::MethodCall(expr) = source {
965 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
966 if let Some(span) = call_expr.span.trim_start(expr.span) {
967 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
968 fallback_span = false;
972 err.span_label(span, msg);
974 } else if let Some(lev_candidate) = lev_candidate {
975 // Don't emit a suggestion if we found an actual method
976 // that had unsatisfied trait bounds
977 if unsatisfied_predicates.is_empty() {
978 let def_kind = lev_candidate.kind.as_def_kind();
979 // Methods are defined within the context of a struct and their first parameter is always self,
980 // which represents the instance of the struct the method is being called on
981 // Associated functions don’t take self as a parameter and
982 // they are not methods because they don’t have an instance of the struct to work with.
983 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
986 &format!("there is a method with a similar name",),
988 Applicability::MaybeIncorrect,
994 "there is {} {} with a similar name",
996 def_kind.descr(lev_candidate.def_id),
999 Applicability::MaybeIncorrect,
1005 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1010 MethodError::Ambiguity(mut sources) => {
1011 let mut err = struct_span_err!(
1015 "multiple applicable items in scope"
1017 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1019 report_candidates(span, &mut err, &mut sources, sugg_span);
1023 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1024 let kind = kind.descr(def_id);
1025 let mut err = struct_span_err!(
1029 "{} `{}` is private",
1033 err.span_label(item_name.span, &format!("private {}", kind));
1037 .span_if_local(def_id)
1038 .unwrap_or_else(|| self.tcx.def_span(def_id));
1039 err.span_label(sp, &format!("private {} defined here", kind));
1040 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1044 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1045 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1046 let mut err = self.sess().struct_span_err(span, &msg);
1047 err.span_label(bound_span, "this has a `Sized` requirement");
1048 if !candidates.is_empty() {
1050 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1051 add a `use` for {one_of_them}:",
1052 an = if candidates.len() == 1 { "an" } else { "" },
1053 s = pluralize!(candidates.len()),
1054 were = pluralize!("was", candidates.len()),
1055 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1057 self.suggest_use_candidates(&mut err, help, candidates);
1059 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1061 let trait_type = self.tcx.mk_ref(
1063 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1065 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1071 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1076 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1077 /// doesn't take a `self` receiver.
1078 fn suggest_associated_call_syntax(
1080 err: &mut Diagnostic,
1081 static_candidates: &Vec<CandidateSource>,
1083 source: SelfSource<'tcx>,
1085 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1088 let mut has_unsuggestable_args = false;
1089 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1090 // When the "method" is resolved through dereferencing, we really want the
1091 // original type that has the associated function for accurate suggestions.
1093 let impl_ty = self.tcx.type_of(*impl_did);
1094 let target_ty = self
1095 .autoderef(sugg_span, rcvr_ty)
1096 .find(|(rcvr_ty, _)| {
1097 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1098 .types_may_unify(*rcvr_ty, impl_ty)
1100 .map_or(impl_ty, |(ty, _)| ty)
1102 if let ty::Adt(def, substs) = target_ty.kind() {
1103 // If there are any inferred arguments, (`{integer}`), we should replace
1104 // them with underscores to allow the compiler to infer them
1105 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1106 if !arg.is_suggestable(self.tcx, true) {
1107 has_unsuggestable_args = true;
1108 match arg.unpack() {
1109 GenericArgKind::Lifetime(_) => self
1110 .next_region_var(RegionVariableOrigin::MiscVariable(
1111 rustc_span::DUMMY_SP,
1114 GenericArgKind::Type(_) => self
1115 .next_ty_var(TypeVariableOrigin {
1116 span: rustc_span::DUMMY_SP,
1117 kind: TypeVariableOriginKind::MiscVariable,
1120 GenericArgKind::Const(arg) => self
1123 ConstVariableOrigin {
1124 span: rustc_span::DUMMY_SP,
1125 kind: ConstVariableOriginKind::MiscVariable,
1135 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1137 self.ty_to_value_string(target_ty)
1140 self.ty_to_value_string(rcvr_ty.peel_refs())
1142 if let SelfSource::MethodCall(_) = source {
1143 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1144 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1145 && assoc.kind == ty::AssocKind::Fn
1147 let sig = self.tcx.fn_sig(assoc.def_id);
1148 if let Some(first) = sig.inputs().skip_binder().get(0) {
1149 if first.peel_refs() == rcvr_ty.peel_refs() {
1152 Some(if first.is_region_ptr() {
1153 if first.is_mutable_ptr() { "&mut " } else { "&" }
1164 let mut applicability = Applicability::MachineApplicable;
1165 let args = if let Some((receiver, args)) = args {
1166 // The first arg is the same kind as the receiver
1167 let explicit_args = if first_arg.is_some() {
1168 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1170 // There is no `Self` kind to infer the arguments from
1171 if has_unsuggestable_args {
1172 applicability = Applicability::HasPlaceholders;
1174 args.iter().collect()
1178 first_arg.unwrap_or(""),
1185 .span_to_snippet(arg.span)
1186 .unwrap_or_else(|_| {
1187 applicability = Applicability::HasPlaceholders;
1190 .collect::<Vec<_>>()
1194 applicability = Applicability::HasPlaceholders;
1197 err.span_suggestion(
1199 "use associated function syntax instead",
1200 format!("{}::{}{}", ty_str, item_name, args),
1204 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1208 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1209 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1210 fn suggest_calling_field_as_fn(
1214 expr: &hir::Expr<'_>,
1216 err: &mut Diagnostic,
1219 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1220 ty::Adt(def, substs) if !def.is_enum() => {
1221 let variant = &def.non_enum_variant();
1222 tcx.find_field_index(item_name, variant).map(|index| {
1223 let field = &variant.fields[index];
1224 let field_ty = field.ty(tcx, substs);
1230 if let Some((field, field_ty)) = field_receiver {
1231 let scope = tcx.parent_module(self.body_id);
1232 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1235 if self.is_fn_ty(field_ty, span) {
1236 let expr_span = expr.span.to(item_name.span);
1237 err.multipart_suggestion(
1239 "to call the function stored in `{}`, \
1240 surround the field access with parentheses",
1244 (expr_span.shrink_to_lo(), '('.to_string()),
1245 (expr_span.shrink_to_hi(), ')'.to_string()),
1247 Applicability::MachineApplicable,
1250 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1252 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1253 err.span_suggestion(
1255 "remove the arguments",
1257 Applicability::MaybeIncorrect,
1263 let field_kind = if is_accessible { "field" } else { "private field" };
1264 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1270 /// Suggest possible range with adding parentheses, for example:
1271 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1272 fn suggest_wrapping_range_with_parens(
1276 source: SelfSource<'tcx>,
1281 if let SelfSource::MethodCall(expr) = source {
1282 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1283 if let Node::Expr(parent_expr) = parent {
1284 let lang_item = match parent_expr.kind {
1285 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1286 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1287 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1288 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1289 Some(LangItem::RangeToInclusive)
1293 ExprKind::Call(ref func, _) => match func.kind {
1294 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1295 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1296 Some(LangItem::RangeInclusiveStruct)
1303 if lang_item.is_none() {
1307 let span_included = match parent_expr.kind {
1308 hir::ExprKind::Struct(_, eps, _) => {
1309 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1311 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1312 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1320 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1322 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1324 let pick = self.probe_for_name(
1331 ProbeScope::AllTraits,
1334 let range_span = parent_expr.span.with_hi(expr.span.hi());
1335 tcx.sess.emit_err(errors::MissingParentheseInRange {
1337 ty_str: ty_str.to_string(),
1338 method_name: item_name.as_str().to_string(),
1339 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1340 func_name: item_name.name.as_str().to_string(),
1341 left: range_span.shrink_to_lo(),
1342 right: range_span.shrink_to_hi(),
1353 fn suggest_constraining_numerical_ty(
1357 source: SelfSource<'_>,
1363 let found_candidate = all_traits(self.tcx)
1365 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1366 let found_assoc = |ty: Ty<'tcx>| {
1367 simplify_type(tcx, ty, TreatParams::AsInfer)
1369 tcx.incoherent_impls(simp)
1371 .find_map(|&id| self.associated_value(id, item_name))
1375 let found_candidate = found_candidate
1376 || found_assoc(tcx.types.i8)
1377 || found_assoc(tcx.types.i16)
1378 || found_assoc(tcx.types.i32)
1379 || found_assoc(tcx.types.i64)
1380 || found_assoc(tcx.types.i128)
1381 || found_assoc(tcx.types.u8)
1382 || found_assoc(tcx.types.u16)
1383 || found_assoc(tcx.types.u32)
1384 || found_assoc(tcx.types.u64)
1385 || found_assoc(tcx.types.u128)
1386 || found_assoc(tcx.types.f32)
1387 || found_assoc(tcx.types.f32);
1389 && actual.is_numeric()
1390 && !actual.has_concrete_skeleton()
1391 && let SelfSource::MethodCall(expr) = source
1393 let mut err = struct_span_err!(
1397 "can't call {} `{}` on ambiguous numeric type `{}`",
1402 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1404 ExprKind::Lit(ref lit) => {
1409 .span_to_snippet(lit.span)
1410 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1412 // If this is a floating point literal that ends with '.',
1413 // get rid of it to stop this from becoming a member access.
1414 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1415 err.span_suggestion(
1418 "you must specify a concrete type for this numeric value, \
1422 format!("{snippet}_{concrete_type}"),
1423 Applicability::MaybeIncorrect,
1426 ExprKind::Path(QPath::Resolved(_, path)) => {
1428 if let hir::def::Res::Local(hir_id) = path.res {
1429 let span = tcx.hir().span(hir_id);
1430 let filename = tcx.sess.source_map().span_to_filename(span);
1433 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1435 "you must specify a type for this binding, like `{}`",
1439 match (filename, parent_node) {
1442 Node::Local(hir::Local {
1443 source: hir::LocalSource::Normal,
1448 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1449 err.span_suggestion(
1450 // account for `let x: _ = 42;`
1454 format!(": {concrete_type}"),
1455 Applicability::MaybeIncorrect,
1459 err.span_label(span, msg);
1472 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1473 fn suggest_calling_method_on_field(
1475 err: &mut Diagnostic,
1476 source: SelfSource<'tcx>,
1481 if let SelfSource::MethodCall(expr) = source
1482 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1483 && let Some((fields, substs)) =
1484 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1486 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1488 let lang_items = self.tcx.lang_items();
1489 let never_mention_traits = [
1490 lang_items.clone_trait(),
1491 lang_items.deref_trait(),
1492 lang_items.deref_mut_trait(),
1493 self.tcx.get_diagnostic_item(sym::AsRef),
1494 self.tcx.get_diagnostic_item(sym::AsMut),
1495 self.tcx.get_diagnostic_item(sym::Borrow),
1496 self.tcx.get_diagnostic_item(sym::BorrowMut),
1498 let candidate_fields: Vec<_> = fields
1499 .filter_map(|candidate_field| {
1500 self.check_for_nested_field_satisfying(
1508 ProbeScope::TraitsInScope,
1510 .map_or(false, |pick| {
1511 !never_mention_traits
1514 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1526 .map(|id| id.name.to_ident_string())
1527 .collect::<Vec<String>>()
1532 let len = candidate_fields.len();
1534 err.span_suggestions(
1535 item_name.span.shrink_to_lo(),
1537 "{} of the expressions' fields {} a method of the same name",
1538 if len > 1 { "some" } else { "one" },
1539 if len > 1 { "have" } else { "has" },
1541 candidate_fields.iter().map(|path| format!("{path}.")),
1542 Applicability::MaybeIncorrect,
1548 fn check_for_inner_self(
1550 err: &mut Diagnostic,
1551 source: SelfSource<'tcx>,
1557 let SelfSource::MethodCall(expr) = source else { return; };
1558 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1560 let ty::Adt(kind, substs) = actual.kind() else { return; };
1561 match kind.adt_kind() {
1562 ty::AdtKind::Enum => {
1563 let matching_variants: Vec<_> = kind
1566 .flat_map(|variant| {
1567 let [field] = &variant.fields[..] else { return None; };
1568 let field_ty = field.ty(tcx, substs);
1570 // Skip `_`, since that'll just lead to ambiguity.
1571 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1580 ProbeScope::TraitsInScope,
1583 .map(|pick| (variant, field, pick))
1587 let ret_ty_matches = |diagnostic_item| {
1588 if let Some(ret_ty) = self
1591 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1592 && let ty::Adt(kind, _) = ret_ty.kind()
1593 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1601 match &matching_variants[..] {
1602 [(_, field, pick)] => {
1603 let self_ty = field.ty(tcx, substs);
1605 tcx.def_span(pick.item.def_id),
1606 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1608 let (article, kind, variant, question) =
1609 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1610 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1611 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1612 ("an", "Option", "None", ret_ty_matches(sym::Option))
1617 err.span_suggestion_verbose(
1618 expr.span.shrink_to_hi(),
1620 "use the `?` operator to extract the `{self_ty}` value, propagating \
1621 {article} `{kind}::{variant}` value to the caller"
1624 Applicability::MachineApplicable,
1627 err.span_suggestion_verbose(
1628 expr.span.shrink_to_hi(),
1630 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1631 panicking if the value is {article} `{kind}::{variant}`"
1633 ".expect(\"REASON\")",
1634 Applicability::HasPlaceholders,
1638 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1642 // Target wrapper types - types that wrap or pretend to wrap another type,
1643 // perhaps this inner type is meant to be called?
1644 ty::AdtKind::Struct | ty::AdtKind::Union => {
1645 let [first] = ***substs else { return; };
1646 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1647 let Ok(pick) = self.lookup_probe(
1652 ProbeScope::TraitsInScope,
1655 let name = self.ty_to_value_string(actual);
1656 let inner_id = kind.did();
1657 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1658 pick.autoref_or_ptr_adjustment
1665 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1666 err.help("use `with` or `try_with` to access thread local storage");
1667 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1669 "if this `{name}` has been initialized, \
1670 use one of the `assume_init` methods to access the inner value"
1672 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1673 let (suggestion, borrow_kind, panic_if) = match mutable {
1674 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1675 Some(Mutability::Mut) => {
1676 (".borrow_mut()", "mutably borrow", "any borrows exist")
1680 err.span_suggestion_verbose(
1681 expr.span.shrink_to_hi(),
1683 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1684 panicking if {panic_if}"
1687 Applicability::MaybeIncorrect,
1689 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1690 err.span_suggestion_verbose(
1691 expr.span.shrink_to_hi(),
1693 "use `.lock().unwrap()` to borrow the `{ty}`, \
1694 blocking the current thread until it can be acquired"
1697 Applicability::MaybeIncorrect,
1699 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1700 let (suggestion, borrow_kind) = match mutable {
1701 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1702 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1705 err.span_suggestion_verbose(
1706 expr.span.shrink_to_hi(),
1708 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1709 blocking the current thread until it can be acquired"
1712 Applicability::MaybeIncorrect,
1719 tcx.def_span(pick.item.def_id),
1720 &format!("the method `{item_name}` exists on the type `{ty}`"),
1726 pub(crate) fn note_unmet_impls_on_type(
1728 err: &mut Diagnostic,
1729 errors: Vec<FulfillmentError<'tcx>>,
1731 let all_local_types_needing_impls =
1732 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1733 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1734 ty::Adt(def, _) => def.did().is_local(),
1739 let mut preds: Vec<_> = errors
1741 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1742 ty::PredicateKind::Trait(pred) => Some(pred),
1746 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1749 .filter_map(|pred| match pred.self_ty().kind() {
1750 ty::Adt(def, _) => Some(def.did()),
1753 .collect::<FxHashSet<_>>();
1754 let mut spans: MultiSpan = def_ids
1756 .filter_map(|def_id| {
1757 let span = self.tcx.def_span(*def_id);
1758 if span.is_dummy() { None } else { Some(span) }
1760 .collect::<Vec<_>>()
1763 for pred in &preds {
1764 match pred.self_ty().kind() {
1765 ty::Adt(def, _) if def.did().is_local() => {
1766 spans.push_span_label(
1767 self.tcx.def_span(def.did()),
1768 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1775 if all_local_types_needing_impls && spans.primary_span().is_some() {
1776 let msg = if preds.len() == 1 {
1778 "an implementation of `{}` might be missing for `{}`",
1779 preds[0].trait_ref.print_only_trait_path(),
1784 "the following type{} would have to `impl` {} required trait{} for this \
1785 operation to be valid",
1786 pluralize!(def_ids.len()),
1787 if def_ids.len() == 1 { "its" } else { "their" },
1788 pluralize!(preds.len()),
1791 err.span_note(spans, &msg);
1794 let preds: Vec<_> = errors
1796 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1798 self.suggest_derive(err, &preds);
1803 err: &mut Diagnostic,
1804 unsatisfied_predicates: &[(
1805 ty::Predicate<'tcx>,
1806 Option<ty::Predicate<'tcx>>,
1807 Option<ObligationCause<'tcx>>,
1810 let mut derives = Vec::<(String, Span, Symbol)>::new();
1811 let mut traits = Vec::<Span>::new();
1812 for (pred, _, _) in unsatisfied_predicates {
1813 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1814 let adt = match trait_pred.self_ty().ty_adt_def() {
1815 Some(adt) if adt.did().is_local() => adt,
1818 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1819 let can_derive = match diagnostic_name {
1820 sym::Default => !adt.is_enum(),
1828 | sym::Debug => true,
1832 let self_name = trait_pred.self_ty().to_string();
1833 let self_span = self.tcx.def_span(adt.did());
1834 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1835 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1837 if let Some(parent_diagnostic_name) =
1838 self.tcx.get_diagnostic_name(super_trait.def_id())
1843 parent_diagnostic_name,
1848 derives.push((self_name, self_span, diagnostic_name));
1850 traits.push(self.tcx.def_span(trait_pred.def_id()));
1853 traits.push(self.tcx.def_span(trait_pred.def_id()));
1862 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1863 for (self_name, self_span, trait_name) in derives.into_iter() {
1864 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1866 if last_self_name == &self_name {
1867 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1871 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1874 let len = traits.len();
1876 let span: MultiSpan = traits.into();
1879 &format!("the following trait{} must be implemented", pluralize!(len),),
1883 for (self_name, self_span, traits) in &derives_grouped {
1884 err.span_suggestion_verbose(
1885 self_span.shrink_to_lo(),
1886 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1887 format!("#[derive({})]\n", traits),
1888 Applicability::MaybeIncorrect,
1893 fn check_for_deref_method(
1895 err: &mut Diagnostic,
1896 self_source: SelfSource<'tcx>,
1900 let SelfSource::QPath(ty) = self_source else { return; };
1901 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1902 if let Ok(pick) = self.probe_for_name(
1909 ProbeScope::TraitsInScope,
1911 if deref_ty.is_suggestable(self.tcx, true)
1912 // If this method receives `&self`, then the provided
1913 // argument _should_ coerce, so it's valid to suggest
1914 // just changing the path.
1915 && pick.item.fn_has_self_parameter
1916 && let Some(self_ty) =
1917 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1920 let suggested_path = match deref_ty.kind() {
1929 | ty::Param(_) => format!("{deref_ty}"),
1930 // we need to test something like <&[_]>::len
1931 // and Vec::function();
1932 // <&[_]>::len doesn't need an extra "<>" between
1933 // but for Adt type like Vec::function()
1934 // we would suggest <[_]>::function();
1935 _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
1936 _ => format!("<{deref_ty}>"),
1938 err.span_suggestion_verbose(
1940 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1942 Applicability::MaybeIncorrect,
1947 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1955 /// Print out the type for use in value namespace.
1956 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1958 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1959 _ => self.ty_to_string(ty),
1963 fn suggest_await_before_method(
1965 err: &mut Diagnostic,
1968 call: &hir::Expr<'_>,
1971 let output_ty = match self.get_impl_future_output_ty(ty) {
1972 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1975 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1976 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1978 err.span_suggestion_verbose(
1979 span.shrink_to_lo(),
1980 "consider `await`ing on the `Future` and calling the method on its `Output`",
1982 Applicability::MaybeIncorrect,
1987 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1988 let parent_map = self.tcx.visible_parent_map(());
1990 // Separate out candidates that must be imported with a glob, because they are named `_`
1991 // and cannot be referred with their identifier.
1992 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1993 if let Some(parent_did) = parent_map.get(trait_did) {
1994 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1995 if *parent_did != self.tcx.parent(*trait_did)
1998 .module_children(*parent_did)
2000 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2001 .all(|child| child.ident.name == kw::Underscore)
2010 let module_did = self.tcx.parent_module(self.body_id);
2011 let (module, _, _) = self.tcx.hir().get_module(module_did);
2012 let span = module.spans.inject_use_span;
2014 let path_strings = candidates.iter().map(|trait_did| {
2015 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2018 let glob_path_strings = globs.iter().map(|trait_did| {
2019 let parent_did = parent_map.get(trait_did).unwrap();
2021 "use {}::*; // trait {}\n",
2022 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2023 self.tcx.item_name(*trait_did),
2027 err.span_suggestions(
2030 path_strings.chain(glob_path_strings),
2031 Applicability::MaybeIncorrect,
2035 fn suggest_valid_traits(
2037 err: &mut Diagnostic,
2038 valid_out_of_scope_traits: Vec<DefId>,
2040 if !valid_out_of_scope_traits.is_empty() {
2041 let mut candidates = valid_out_of_scope_traits;
2045 // `TryFrom` and `FromIterator` have no methods
2046 let edition_fix = candidates
2048 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2051 err.help("items from traits can only be used if the trait is in scope");
2053 "the following {traits_are} implemented but not in scope; \
2054 perhaps add a `use` for {one_of_them}:",
2055 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2056 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2059 self.suggest_use_candidates(err, msg, candidates);
2060 if let Some(did) = edition_fix {
2062 "'{}' is included in the prelude starting in Edition 2021",
2063 with_crate_prefix!(self.tcx.def_path_str(did))
2073 fn suggest_traits_to_import(
2075 err: &mut Diagnostic,
2079 inputs_len: Option<usize>,
2080 source: SelfSource<'tcx>,
2081 valid_out_of_scope_traits: Vec<DefId>,
2082 unsatisfied_predicates: &[(
2083 ty::Predicate<'tcx>,
2084 Option<ty::Predicate<'tcx>>,
2085 Option<ObligationCause<'tcx>>,
2087 static_candidates: &[CandidateSource],
2088 unsatisfied_bounds: bool,
2090 let mut alt_rcvr_sugg = false;
2091 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2093 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2094 span, item_name, rcvr_ty, rcvr
2097 self.tcx.lang_items().clone_trait(),
2098 self.tcx.lang_items().deref_trait(),
2099 self.tcx.lang_items().deref_mut_trait(),
2100 self.tcx.lang_items().drop_trait(),
2101 self.tcx.get_diagnostic_item(sym::AsRef),
2103 // Try alternative arbitrary self types that could fulfill this call.
2104 // FIXME: probe for all types that *could* be arbitrary self-types, not
2106 for (rcvr_ty, post) in &[
2108 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2109 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2111 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2113 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2114 // We point at the method, but we just skip the rest of the check for arbitrary
2115 // self types and rely on the suggestion to `use` the trait from
2116 // `suggest_valid_traits`.
2117 let did = Some(pick.item.container_id(self.tcx));
2118 let skip = skippable.contains(&did);
2119 if pick.autoderefs == 0 && !skip {
2121 pick.item.ident(self.tcx).span,
2122 &format!("the method is available for `{}` here", rcvr_ty),
2127 Err(MethodError::Ambiguity(_)) => {
2128 // If the method is defined (but ambiguous) for the receiver we have, it is also
2129 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2130 // the receiver, then it might disambiguate this method, but I think these
2131 // suggestions are generally misleading (see #94218).
2137 for (rcvr_ty, pre) in &[
2138 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2139 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2140 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2141 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2143 if let Some(new_rcvr_t) = *rcvr_ty
2144 && let Ok(pick) = self.lookup_probe(
2149 ProbeScope::AllTraits,
2152 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2153 let did = Some(pick.item.container_id(self.tcx));
2154 // We don't want to suggest a container type when the missing
2155 // method is `.clone()` or `.deref()` otherwise we'd suggest
2156 // `Arc::new(foo).clone()`, which is far from what the user wants.
2157 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2158 // implement the `AsRef` trait.
2159 let skip = skippable.contains(&did)
2160 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2161 || 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);
2162 // Make sure the method is defined for the *actual* receiver: we don't
2163 // want to treat `Box<Self>` as a receiver if it only works because of
2164 // an autoderef to `&self`
2165 if pick.autoderefs == 0 && !skip {
2167 pick.item.ident(self.tcx).span,
2168 &format!("the method is available for `{}` here", new_rcvr_t),
2170 err.multipart_suggestion(
2171 "consider wrapping the receiver expression with the \
2174 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2175 (rcvr.span.shrink_to_hi(), ")".to_string()),
2177 Applicability::MaybeIncorrect,
2179 // We don't care about the other suggestions.
2180 alt_rcvr_sugg = true;
2186 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2190 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2192 let mut arbitrary_rcvr = vec![];
2193 // There are no traits implemented, so lets suggest some traits to
2194 // implement, by finding ones that have the item name, and are
2195 // legal to implement.
2196 let mut candidates = all_traits(self.tcx)
2198 // Don't issue suggestions for unstable traits since they're
2199 // unlikely to be implementable anyway
2200 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2201 Some(attr) => attr.level.is_stable(),
2205 // Static candidates are already implemented, and known not to work
2206 // Do not suggest them again
2207 static_candidates.iter().all(|sc| match *sc {
2208 CandidateSource::Trait(def_id) => def_id != info.def_id,
2209 CandidateSource::Impl(def_id) => {
2210 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2215 // We approximate the coherence rules to only suggest
2216 // traits that are legal to implement by requiring that
2217 // either the type or trait is local. Multi-dispatch means
2218 // this isn't perfect (that is, there are cases when
2219 // implementing a trait would be legal but is rejected
2221 unsatisfied_predicates.iter().all(|(p, _, _)| {
2222 match p.kind().skip_binder() {
2223 // Hide traits if they are present in predicates as they can be fixed without
2224 // having to implement them.
2225 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2226 ty::PredicateKind::Projection(p) => {
2227 p.projection_ty.item_def_id == info.def_id
2231 }) && (type_is_local || info.def_id.is_local())
2233 .associated_value(info.def_id, item_name)
2235 if let ty::AssocKind::Fn = item.kind {
2239 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2240 if let Some(hir::Node::TraitItem(hir::TraitItem {
2241 kind: hir::TraitItemKind::Fn(fn_sig, method),
2243 })) = id.map(|id| self.tcx.hir().get(id))
2245 let self_first_arg = match method {
2246 hir::TraitFn::Required([ident, ..]) => {
2247 ident.name == kw::SelfLower
2249 hir::TraitFn::Provided(body_id) => {
2250 self.tcx.hir().body(*body_id).params.first().map_or(
2255 hir::PatKind::Binding(_, _, ident, _)
2256 if ident.name == kw::SelfLower
2264 if !fn_sig.decl.implicit_self.has_implicit_self()
2267 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2268 arbitrary_rcvr.push(ty.span);
2274 // We only want to suggest public or local traits (#45781).
2275 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2279 .collect::<Vec<_>>();
2280 for span in &arbitrary_rcvr {
2283 "the method might not be found because of this arbitrary self type",
2290 if !candidates.is_empty() {
2291 // Sort from most relevant to least relevant.
2292 candidates.sort_by(|a, b| a.cmp(b).reverse());
2295 let param_type = match rcvr_ty.kind() {
2296 ty::Param(param) => Some(param),
2297 ty::Ref(_, ty, _) => match ty.kind() {
2298 ty::Param(param) => Some(param),
2303 err.help(if param_type.is_some() {
2304 "items from traits can only be used if the type parameter is bounded by the trait"
2306 "items from traits can only be used if the trait is implemented and in scope"
2308 let candidates_len = candidates.len();
2309 let message = |action| {
2311 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2314 if candidates_len == 1 { "trait defines" } else { "traits define" },
2316 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2320 // Obtain the span for `param` and use it for a structured suggestion.
2321 if let Some(param) = param_type {
2322 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2323 let type_param = generics.type_param(param, self.tcx);
2324 let hir = self.tcx.hir();
2325 if let Some(def_id) = type_param.def_id.as_local() {
2326 let id = hir.local_def_id_to_hir_id(def_id);
2327 // Get the `hir::Param` to verify whether it already has any bounds.
2328 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2329 // instead we suggest `T: Foo + Bar` in that case.
2331 Node::GenericParam(param) => {
2337 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2338 let (sp, mut introducer) = if let Some(span) =
2339 ast_generics.bounds_span_for_suggestions(def_id)
2341 (span, Introducer::Plus)
2342 } else if let Some(colon_span) = param.colon_span {
2343 (colon_span.shrink_to_hi(), Introducer::Nothing)
2345 (param.span.shrink_to_hi(), Introducer::Colon)
2349 hir::GenericParamKind::Type { synthetic: true, .. },
2351 introducer = Introducer::Plus
2353 let trait_def_ids: FxHashSet<DefId> = ast_generics
2354 .bounds_for_param(def_id)
2355 .flat_map(|bp| bp.bounds.iter())
2356 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2358 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2359 err.span_suggestions(
2362 "restrict type parameter `{}` with",
2365 candidates.iter().map(|t| {
2369 Introducer::Plus => " +",
2370 Introducer::Colon => ":",
2371 Introducer::Nothing => "",
2373 self.tcx.def_path_str(t.def_id),
2376 Applicability::MaybeIncorrect,
2381 Node::Item(hir::Item {
2382 kind: hir::ItemKind::Trait(.., bounds, _),
2386 let (sp, sep, article) = if bounds.is_empty() {
2387 (ident.span.shrink_to_hi(), ":", "a")
2389 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2391 err.span_suggestions(
2393 &message(format!("add {} supertrait for", article)),
2394 candidates.iter().map(|t| {
2395 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2397 Applicability::MaybeIncorrect,
2406 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2407 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2408 // cases where a positive bound implies a negative impl.
2409 (candidates, Vec::new())
2410 } else if let Some(simp_rcvr_ty) =
2411 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2413 let mut potential_candidates = Vec::new();
2414 let mut explicitly_negative = Vec::new();
2415 for candidate in candidates {
2416 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2419 .all_impls(candidate.def_id)
2421 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2424 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2426 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2427 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2430 explicitly_negative.push(candidate);
2432 potential_candidates.push(candidate);
2435 (potential_candidates, explicitly_negative)
2437 // We don't know enough about `recv_ty` to make proper suggestions.
2438 (candidates, Vec::new())
2441 let action = if let Some(param) = param_type {
2442 format!("restrict type parameter `{}` with", param)
2444 // FIXME: it might only need to be imported into scope, not implemented.
2445 "implement".to_string()
2447 match &potential_candidates[..] {
2449 [trait_info] if trait_info.def_id.is_local() => {
2451 self.tcx.def_span(trait_info.def_id),
2453 "`{}` defines an item `{}`, perhaps you need to {} it",
2454 self.tcx.def_path_str(trait_info.def_id),
2461 let mut msg = message(action);
2462 for (i, trait_info) in trait_infos.iter().enumerate() {
2463 msg.push_str(&format!(
2464 "\ncandidate #{}: `{}`",
2466 self.tcx.def_path_str(trait_info.def_id),
2472 match &explicitly_negative[..] {
2476 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2477 self.tcx.def_path_str(trait_info.def_id),
2483 let mut msg = format!(
2484 "the following traits define an item `{}`, but are explicitly unimplemented:",
2487 for trait_info in trait_infos {
2488 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2496 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2497 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2498 pub(crate) fn suggest_else_fn_with_closure(
2500 err: &mut Diagnostic,
2501 expr: &hir::Expr<'_>,
2505 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2506 else { return false; };
2508 if !self.can_coerce(output, expected) {
2512 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2513 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2514 let hir::ExprKind::MethodCall(
2515 hir::PathSegment { ident: method_name, .. },
2519 ) = call_expr.kind &&
2520 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2521 let new_name = Ident {
2522 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2523 span: method_name.span,
2525 let probe = self.lookup_probe(
2530 ProbeScope::TraitsInScope,
2533 // check the method arguments number
2534 if let Ok(pick) = probe &&
2535 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2536 let fn_args = fn_sig.skip_binder().inputs() &&
2537 fn_args.len() == args.len() + 1 {
2538 err.span_suggestion_verbose(
2539 method_name.span.shrink_to_hi(),
2540 &format!("try calling `{}` instead", new_name.name.as_str()),
2542 Applicability::MaybeIncorrect,
2550 /// Checks whether there is a local type somewhere in the chain of
2551 /// autoderefs of `rcvr_ty`.
2552 fn type_derefs_to_local(
2556 source: SelfSource<'tcx>,
2558 fn is_local(ty: Ty<'_>) -> bool {
2560 ty::Adt(def, _) => def.did().is_local(),
2561 ty::Foreign(did) => did.is_local(),
2562 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2563 ty::Param(_) => true,
2565 // Everything else (primitive types, etc.) is effectively
2566 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2567 // the noise from these sort of types is usually just really
2568 // annoying, rather than any sort of help).
2573 // This occurs for UFCS desugaring of `T::method`, where there is no
2574 // receiver expression for the method call, and thus no autoderef.
2575 if let SelfSource::QPath(_) = source {
2576 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2579 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2583 #[derive(Copy, Clone, Debug)]
2584 pub enum SelfSource<'a> {
2585 QPath(&'a hir::Ty<'a>),
2586 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2589 #[derive(Copy, Clone)]
2590 pub struct TraitInfo {
2594 impl PartialEq for TraitInfo {
2595 fn eq(&self, other: &TraitInfo) -> bool {
2596 self.cmp(other) == Ordering::Equal
2599 impl Eq for TraitInfo {}
2600 impl PartialOrd for TraitInfo {
2601 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2602 Some(self.cmp(other))
2605 impl Ord for TraitInfo {
2606 fn cmp(&self, other: &TraitInfo) -> Ordering {
2607 // Local crates are more important than remote ones (local:
2608 // `cnum == 0`), and otherwise we throw in the defid for totality.
2610 let lhs = (other.def_id.krate, other.def_id);
2611 let rhs = (self.def_id.krate, self.def_id);
2616 /// Retrieves all traits in this crate and any dependent crates,
2617 /// and wraps them into `TraitInfo` for custom sorting.
2618 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2619 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2622 fn print_disambiguation_help<'tcx>(
2624 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2625 err: &mut Diagnostic,
2628 kind: ty::AssocKind,
2631 candidate: Option<usize>,
2632 source_map: &source_map::SourceMap,
2633 fn_has_self_parameter: bool,
2635 let mut applicability = Applicability::MachineApplicable;
2636 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2639 if rcvr_ty.is_region_ptr() {
2640 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2644 std::iter::once(receiver)
2646 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2647 applicability = Applicability::HasPlaceholders;
2650 .collect::<Vec<_>>()
2653 let trait_name = if !fn_has_self_parameter {
2654 format!("<{} as {}>", rcvr_ty, trait_name)
2658 (span, format!("{}::{}{}", trait_name, item_name, args))
2660 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2662 err.span_suggestion_verbose(
2665 "disambiguate the {} for {}",
2666 kind.as_def_kind().descr(def_id),
2667 if let Some(candidate) = candidate {
2668 format!("candidate #{}", candidate)
2670 "the candidate".to_string()