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 trait_ref = tcx.mk_trait_ref(
75 self.next_ty_var(TypeVariableOrigin {
76 kind: TypeVariableOriginKind::MiscVariable,
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>,
117 sugg_span: Option<Span>| {
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(sugg_span) = sugg_span
179 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
180 let path = self.tcx.def_path_str(trait_ref.def_id);
182 let ty = match item.kind {
183 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
184 ty::AssocKind::Fn => self
190 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
194 print_disambiguation_help(
204 self.tcx.sess.source_map(),
205 item.fn_has_self_parameter,
209 CandidateSource::Trait(trait_did) => {
210 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
211 let item_span = self.tcx.def_span(item.def_id);
212 let idx = if sources.len() > 1 {
214 "candidate #{} is defined in the trait `{}`",
216 self.tcx.def_path_str(trait_did)
218 err.span_note(item_span, msg);
222 "the candidate is defined in the trait `{}`",
223 self.tcx.def_path_str(trait_did)
225 err.span_note(item_span, msg);
228 if let Some(sugg_span) = sugg_span {
229 let path = self.tcx.def_path_str(trait_did);
230 print_disambiguation_help(
240 self.tcx.sess.source_map(),
241 item.fn_has_self_parameter,
247 if sources.len() > limit {
248 err.note(&format!("and {} others", sources.len() - limit));
252 let sugg_span = if let SelfSource::MethodCall(expr) = source {
253 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
254 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
260 MethodError::NoMatch(NoMatchData {
261 mut static_candidates,
262 unsatisfied_predicates,
269 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
270 let ty_str = self.ty_to_string(rcvr_ty);
271 let is_method = mode == Mode::MethodCall;
272 let item_kind = if is_method {
274 } else if rcvr_ty.is_enum() {
275 "variant or associated item"
277 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
278 (Some(name), false) if name.is_lowercase() => "function or associated item",
279 (Some(_), false) => "associated item",
280 (Some(_), true) | (None, false) => "variant or associated item",
281 (None, true) => "variant",
285 if self.suggest_wrapping_range_with_parens(
286 tcx, rcvr_ty, source, span, item_name, &ty_str,
287 ) || self.suggest_constraining_numerical_ty(
288 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
292 span = item_name.span;
294 // Don't show generic arguments when the method can't be found in any implementation (#81576).
295 let mut ty_str_reported = ty_str.clone();
296 if let ty::Adt(_, generics) = rcvr_ty.kind() {
297 if generics.len() > 0 {
298 let mut autoderef = self.autoderef(span, rcvr_ty);
299 let candidate_found = autoderef.any(|(ty, _)| {
300 if let ty::Adt(adt_def, _) = ty.kind() {
302 .inherent_impls(adt_def.did())
304 .filter_map(|def_id| self.associated_value(*def_id, item_name))
311 let has_deref = autoderef.step_count() > 0;
312 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
313 if let Some((path_string, _)) = ty_str.split_once('<') {
314 ty_str_reported = path_string.to_string();
320 let mut err = struct_span_err!(
324 "no {} named `{}` found for {} `{}` in the current scope",
327 rcvr_ty.prefix_string(self.tcx),
330 if rcvr_ty.references_error() {
331 err.downgrade_to_delayed_bug();
334 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
335 self.suggest_await_before_method(
336 &mut err, item_name, rcvr_ty, cal, span,
339 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
342 "you are looking for the module in `std`, not the primitive type",
344 Applicability::MachineApplicable,
347 if let ty::RawPtr(_) = &rcvr_ty.kind() {
349 "try using `<*const T>::as_ref()` to get a reference to the \
350 type behind the pointer: https://doc.rust-lang.org/std/\
351 primitive.pointer.html#method.as_ref",
354 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
355 to invalid or uninitialized memory is undefined behavior",
359 let ty_span = match rcvr_ty.kind() {
360 ty::Param(param_type) => Some(
361 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
363 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
366 if let Some(span) = ty_span {
370 "{item_kind} `{item_name}` not found for this {}",
371 rcvr_ty.prefix_string(self.tcx)
376 if let SelfSource::MethodCall(rcvr_expr) = source {
377 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
381 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
382 let probe = self.lookup_probe(
386 ProbeScope::AllTraits,
392 let mut custom_span_label = false;
394 if !static_candidates.is_empty() {
396 "found the following associated functions; to be used as methods, \
397 functions must have a `self` parameter",
399 err.span_label(span, "this is an associated function, not a method");
400 custom_span_label = true;
402 if static_candidates.len() == 1 {
403 self.suggest_associated_call_syntax(
413 report_candidates(span, &mut err, &mut static_candidates, None);
414 } else if static_candidates.len() > 1 {
415 report_candidates(span, &mut err, &mut static_candidates, Some(sugg_span));
418 let mut bound_spans = vec![];
419 let mut restrict_type_params = false;
420 let mut unsatisfied_bounds = false;
421 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
422 let msg = "consider using `len` instead";
423 if let SelfSource::MethodCall(_expr) = source {
424 err.span_suggestion_short(
428 Applicability::MachineApplicable,
431 err.span_label(span, msg);
433 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
434 let iterator_trait = self.tcx.def_path_str(iterator_trait);
435 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
437 } else if !unsatisfied_predicates.is_empty() {
438 let mut type_params = FxHashMap::default();
440 // Pick out the list of unimplemented traits on the receiver.
441 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
442 let mut unimplemented_traits = FxHashMap::default();
443 let mut unimplemented_traits_only = true;
444 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
445 if let (ty::PredicateKind::Trait(p), Some(cause)) =
446 (predicate.kind().skip_binder(), cause.as_ref())
448 if p.trait_ref.self_ty() != rcvr_ty {
449 // This is necessary, not just to keep the errors clean, but also
450 // because our derived obligations can wind up with a trait ref that
451 // requires a different param_env to be correctly compared.
454 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
455 predicate.kind().rebind(p.trait_ref),
457 cause: cause.clone(),
458 param_env: self.param_env,
459 predicate: *predicate,
466 // Make sure that, if any traits other than the found ones were involved,
467 // we don't don't report an unimplemented trait.
468 // We don't want to say that `iter::Cloned` is not an iterator, just
469 // because of some non-Clone item being iterated over.
470 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
471 match predicate.kind().skip_binder() {
472 ty::PredicateKind::Trait(p)
473 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
475 unimplemented_traits_only = false;
481 let mut collect_type_param_suggestions =
482 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
483 // We don't care about regions here, so it's fine to skip the binder here.
484 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
485 (self_ty.kind(), parent_pred.kind().skip_binder())
487 let hir = self.tcx.hir();
488 let node = match p.trait_ref.self_ty().kind() {
490 // Account for `fn` items like in `issue-35677.rs` to
491 // suggest restricting its type params.
493 hir.body_owner(hir::BodyId { hir_id: self.body_id });
494 Some(hir.get(parent_body))
497 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
501 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
502 if let Some(g) = kind.generics() {
504 g.tail_span_for_predicate_suggestion(),
505 g.add_where_or_trailing_comma(),
509 .or_insert_with(FxHashSet::default)
510 .insert(obligation.to_owned());
515 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
517 "doesn't satisfy `{}`",
518 if obligation.len() > 50 { quiet } else { obligation }
520 match &self_ty.kind() {
521 // Point at the type that couldn't satisfy the bound.
523 bound_spans.push((self.tcx.def_span(def.did()), msg))
525 // Point at the trait object that couldn't satisfy the bound.
526 ty::Dynamic(preds, _, _) => {
527 for pred in preds.iter() {
528 match pred.skip_binder() {
529 ty::ExistentialPredicate::Trait(tr) => bound_spans
530 .push((self.tcx.def_span(tr.def_id), msg.clone())),
531 ty::ExistentialPredicate::Projection(_)
532 | ty::ExistentialPredicate::AutoTrait(_) => {}
536 // Point at the closure that couldn't satisfy the bound.
537 ty::Closure(def_id, _) => bound_spans.push((
538 tcx.def_span(*def_id),
539 format!("doesn't satisfy `{}`", quiet),
544 let mut format_pred = |pred: ty::Predicate<'tcx>| {
545 let bound_predicate = pred.kind();
546 match bound_predicate.skip_binder() {
547 ty::PredicateKind::Projection(pred) => {
548 let pred = bound_predicate.rebind(pred);
549 // `<Foo as Iterator>::Item = String`.
550 let projection_ty = pred.skip_binder().projection_ty;
552 let substs_with_infer_self = tcx.mk_substs(
553 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
554 .chain(projection_ty.substs.iter().skip(1)),
557 let quiet_projection_ty = ty::ProjectionTy {
558 substs: substs_with_infer_self,
559 item_def_id: projection_ty.item_def_id,
562 let term = pred.skip_binder().term;
564 let obligation = format!("{} = {}", projection_ty, term);
565 let quiet = format!("{} = {}", quiet_projection_ty, term);
567 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
568 Some((obligation, projection_ty.self_ty()))
570 ty::PredicateKind::Trait(poly_trait_ref) => {
571 let p = poly_trait_ref.trait_ref;
572 let self_ty = p.self_ty();
573 let path = p.print_only_trait_path();
574 let obligation = format!("{}: {}", self_ty, path);
575 let quiet = format!("_: {}", path);
576 bound_span_label(self_ty, &obligation, &quiet);
577 Some((obligation, self_ty))
583 // Find all the requirements that come from a local `impl` block.
584 let mut skip_list: FxHashSet<_> = Default::default();
585 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
586 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
588 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
589 .filter_map(|(p, parent, c)| match c.code() {
590 ObligationCauseCode::ImplDerivedObligation(data) => {
591 Some((&data.derived, p, parent, data.impl_def_id, data))
596 let parent_trait_ref = data.parent_trait_pred;
597 let path = parent_trait_ref.print_modifiers_and_trait_path();
598 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
599 let unsatisfied_msg = "unsatisfied trait bound introduced here";
601 "unsatisfied trait bound introduced in this `derive` macro";
602 match self.tcx.hir().get_if_local(impl_def_id) {
603 // Unmet obligation comes from a `derive` macro, point at it once to
604 // avoid multiple span labels pointing at the same place.
605 Some(Node::Item(hir::Item {
606 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
609 self_ty.span.ctxt().outer_expn_data().kind,
610 ExpnKind::Macro(MacroKind::Derive, _)
612 of_trait.as_ref().map(|t| t
618 Some(ExpnKind::Macro(MacroKind::Derive, _))
621 let span = self_ty.span.ctxt().outer_expn_data().call_site;
622 let mut spans: MultiSpan = span.into();
623 spans.push_span_label(span, derive_msg);
624 let entry = spanned_predicates.entry(spans);
625 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
628 // Unmet obligation coming from an `impl`.
629 Some(Node::Item(hir::Item {
631 hir::ItemKind::Impl(hir::Impl {
632 of_trait, self_ty, generics, ..
638 unsatisfied_predicates.iter().any(|(pred, _, _)| {
639 match pred.kind().skip_binder() {
640 ty::PredicateKind::Trait(pred) => {
642 == self.tcx.lang_items().sized_trait()
643 && pred.polarity == ty::ImplPolarity::Positive
648 for param in generics.params {
649 if param.span == cause.span && sized_pred {
650 let (sp, sugg) = match param.colon_span {
651 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
652 None => (param.span.shrink_to_hi(), ": ?Sized"),
654 err.span_suggestion_verbose(
656 "consider relaxing the type parameter's implicit \
659 Applicability::MachineApplicable,
663 if let Some(pred) = parent_p {
664 // Done to add the "doesn't satisfy" `span_label`.
665 let _ = format_pred(*pred);
668 let mut spans = if cause.span != *item_span {
669 let mut spans: MultiSpan = cause.span.into();
670 spans.push_span_label(cause.span, unsatisfied_msg);
673 let mut spans = Vec::with_capacity(2);
674 if let Some(trait_ref) = of_trait {
675 spans.push(trait_ref.path.span);
677 spans.push(self_ty.span);
680 if let Some(trait_ref) = of_trait {
681 spans.push_span_label(trait_ref.path.span, "");
683 spans.push_span_label(self_ty.span, "");
685 let entry = spanned_predicates.entry(spans);
686 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
688 Some(_) => unreachable!(),
692 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
693 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
694 for (span, (_path, _self_ty, preds)) in spanned_predicates {
695 let mut preds: Vec<_> = preds
697 .filter_map(|pred| format_pred(*pred))
698 .map(|(p, _)| format!("`{}`", p))
702 let msg = if let [pred] = &preds[..] {
703 format!("trait bound {} was not satisfied", pred)
706 "the following trait bounds were not satisfied:\n{}",
710 err.span_note(span, &msg);
711 unsatisfied_bounds = true;
714 // The requirements that didn't have an `impl` span to show.
715 let mut bound_list = unsatisfied_predicates
717 .filter_map(|(pred, parent_pred, _cause)| {
718 format_pred(*pred).map(|(p, self_ty)| {
719 collect_type_param_suggestions(self_ty, *pred, &p);
722 None => format!("`{}`", &p),
723 Some(parent_pred) => match format_pred(*parent_pred) {
724 None => format!("`{}`", &p),
725 Some((parent_p, _)) => {
726 collect_type_param_suggestions(
732 "`{}`\nwhich is required by `{}`",
742 .filter(|(_, pred)| !skip_list.contains(&pred))
745 .collect::<Vec<(usize, String)>>();
747 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
748 restrict_type_params = true;
749 // #74886: Sort here so that the output is always the same.
750 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
752 err.span_suggestion_verbose(
755 "consider restricting the type parameter{s} to satisfy the \
757 s = pluralize!(obligations.len())
759 format!("{} {}", add_where_or_comma, obligations.join(", ")),
760 Applicability::MaybeIncorrect,
764 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
765 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
766 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
768 if !bound_list.is_empty() || !skip_list.is_empty() {
769 let bound_list = bound_list
771 .map(|(_, path)| path)
774 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
775 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
776 let (primary_message, label) =
777 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
781 .map(|(_, (trait_ref, obligation))| {
782 if trait_ref.self_ty().references_error()
783 || rcvr_ty.references_error()
788 let OnUnimplementedNote { message, label, .. } = self
790 .on_unimplemented_note(trait_ref, &obligation);
797 let primary_message = primary_message.unwrap_or_else(|| format!(
798 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
800 err.set_primary_message(&primary_message);
801 if let Some(label) = label {
802 custom_span_label = true;
803 err.span_label(span, label);
805 if !bound_list.is_empty() {
807 "the following trait bounds were not satisfied:\n{bound_list}"
810 self.suggest_derive(&mut err, &unsatisfied_predicates);
812 unsatisfied_bounds = true;
816 let label_span_not_found = |err: &mut Diagnostic| {
817 if unsatisfied_predicates.is_empty() {
818 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
819 let is_string_or_ref_str = match rcvr_ty.kind() {
820 ty::Ref(_, ty, _) => {
824 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
827 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
830 if is_string_or_ref_str && item_name.name == sym::iter {
831 err.span_suggestion_verbose(
833 "because of the in-memory representation of `&str`, to obtain \
834 an `Iterator` over each of its codepoint use method `chars`",
836 Applicability::MachineApplicable,
839 if let ty::Adt(adt, _) = rcvr_ty.kind() {
840 let mut inherent_impls_candidate = self
842 .inherent_impls(adt.did())
846 if let Some(assoc) = self.associated_value(*def_id, item_name) {
847 // Check for both mode is the same so we avoid suggesting
848 // incorrect associated item.
849 match (mode, assoc.fn_has_self_parameter, source) {
850 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
851 // We check that the suggest type is actually
852 // different from the received one
853 // So we avoid suggestion method with Box<Self>
855 self.tcx.at(span).type_of(*def_id) != rcvr_ty
856 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
858 (Mode::Path, false, _) => true,
865 .collect::<Vec<_>>();
866 if !inherent_impls_candidate.is_empty() {
867 inherent_impls_candidate.sort();
868 inherent_impls_candidate.dedup();
870 // number of type to shows at most.
871 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
872 let type_candidates = inherent_impls_candidate
876 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
880 let additional_types = if inherent_impls_candidate.len() > limit {
882 "\nand {} more types",
883 inherent_impls_candidate.len() - limit
889 "the {item_kind} was found for\n{}{}",
890 type_candidates, additional_types
895 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
899 // If the method name is the name of a field with a function or closure type,
900 // give a helping note that it has to be called as `(x.f)(...)`.
901 if let SelfSource::MethodCall(expr) = source {
902 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
903 && lev_candidate.is_none()
904 && !custom_span_label
906 label_span_not_found(&mut err);
908 } else if !custom_span_label {
909 label_span_not_found(&mut err);
912 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
913 // can't be called due to `typeof(expr): Clone` not holding.
914 if unsatisfied_predicates.is_empty() {
915 self.suggest_calling_method_on_field(
916 &mut err, source, span, rcvr_ty, item_name,
920 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
924 for (span, msg) in bound_spans.into_iter() {
925 err.span_label(span, &msg);
928 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
930 self.suggest_traits_to_import(
935 args.map(|(_, args)| args.len() + 1),
938 &unsatisfied_predicates,
944 // Don't emit a suggestion if we found an actual method
945 // that had unsatisfied trait bounds
946 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
947 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
948 if let Some(suggestion) = lev_distance::find_best_match_for_name(
949 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
955 "there is a variant with a similar name",
957 Applicability::MaybeIncorrect,
962 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
963 let msg = "remove this method call";
964 let mut fallback_span = true;
965 if let SelfSource::MethodCall(expr) = source {
967 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
968 if let Some(span) = call_expr.span.trim_start(expr.span) {
969 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
970 fallback_span = false;
974 err.span_label(span, msg);
976 } else if let Some(lev_candidate) = lev_candidate {
977 // Don't emit a suggestion if we found an actual method
978 // that had unsatisfied trait bounds
979 if unsatisfied_predicates.is_empty() {
980 let def_kind = lev_candidate.kind.as_def_kind();
981 // Methods are defined within the context of a struct and their first parameter is always self,
982 // which represents the instance of the struct the method is being called on
983 // Associated functions don’t take self as a parameter and
984 // they are not methods because they don’t have an instance of the struct to work with.
985 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
988 &format!("there is a method with a similar name",),
990 Applicability::MaybeIncorrect,
996 "there is {} {} with a similar name",
998 def_kind.descr(lev_candidate.def_id),
1001 Applicability::MaybeIncorrect,
1007 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1012 MethodError::Ambiguity(mut sources) => {
1013 let mut err = struct_span_err!(
1017 "multiple applicable items in scope"
1019 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1021 report_candidates(span, &mut err, &mut sources, Some(sugg_span));
1025 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1026 let kind = kind.descr(def_id);
1027 let mut err = struct_span_err!(
1031 "{} `{}` is private",
1035 err.span_label(item_name.span, &format!("private {}", kind));
1039 .span_if_local(def_id)
1040 .unwrap_or_else(|| self.tcx.def_span(def_id));
1041 err.span_label(sp, &format!("private {} defined here", kind));
1042 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1046 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1047 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1048 let mut err = self.sess().struct_span_err(span, &msg);
1049 err.span_label(bound_span, "this has a `Sized` requirement");
1050 if !candidates.is_empty() {
1052 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1053 add a `use` for {one_of_them}:",
1054 an = if candidates.len() == 1 { "an" } else { "" },
1055 s = pluralize!(candidates.len()),
1056 were = pluralize!("was", candidates.len()),
1057 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1059 self.suggest_use_candidates(&mut err, help, candidates);
1061 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1063 let trait_type = self.tcx.mk_ref(
1065 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1067 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1073 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1078 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1079 /// doesn't take a `self` receiver.
1080 fn suggest_associated_call_syntax(
1082 err: &mut Diagnostic,
1083 static_candidates: &Vec<CandidateSource>,
1085 source: SelfSource<'tcx>,
1087 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1090 let mut has_unsuggestable_args = false;
1091 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1092 // When the "method" is resolved through dereferencing, we really want the
1093 // original type that has the associated function for accurate suggestions.
1095 let impl_ty = self.tcx.type_of(*impl_did);
1096 let target_ty = self
1097 .autoderef(sugg_span, rcvr_ty)
1098 .find(|(rcvr_ty, _)| {
1099 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1100 .types_may_unify(*rcvr_ty, impl_ty)
1102 .map_or(impl_ty, |(ty, _)| ty)
1104 if let ty::Adt(def, substs) = target_ty.kind() {
1105 // If there are any inferred arguments, (`{integer}`), we should replace
1106 // them with underscores to allow the compiler to infer them
1107 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1108 if !arg.is_suggestable(self.tcx, true) {
1109 has_unsuggestable_args = true;
1110 match arg.unpack() {
1111 GenericArgKind::Lifetime(_) => self
1112 .next_region_var(RegionVariableOrigin::MiscVariable(
1113 rustc_span::DUMMY_SP,
1116 GenericArgKind::Type(_) => self
1117 .next_ty_var(TypeVariableOrigin {
1118 span: rustc_span::DUMMY_SP,
1119 kind: TypeVariableOriginKind::MiscVariable,
1122 GenericArgKind::Const(arg) => self
1125 ConstVariableOrigin {
1126 span: rustc_span::DUMMY_SP,
1127 kind: ConstVariableOriginKind::MiscVariable,
1137 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1139 self.ty_to_value_string(target_ty)
1142 self.ty_to_value_string(rcvr_ty.peel_refs())
1144 if let SelfSource::MethodCall(_) = source {
1145 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1146 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1147 && assoc.kind == ty::AssocKind::Fn
1149 let sig = self.tcx.fn_sig(assoc.def_id);
1150 if let Some(first) = sig.inputs().skip_binder().get(0) {
1151 if first.peel_refs() == rcvr_ty.peel_refs() {
1154 Some(if first.is_region_ptr() {
1155 if first.is_mutable_ptr() { "&mut " } else { "&" }
1166 let mut applicability = Applicability::MachineApplicable;
1167 let args = if let Some((receiver, args)) = args {
1168 // The first arg is the same kind as the receiver
1169 let explicit_args = if first_arg.is_some() {
1170 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1172 // There is no `Self` kind to infer the arguments from
1173 if has_unsuggestable_args {
1174 applicability = Applicability::HasPlaceholders;
1176 args.iter().collect()
1180 first_arg.unwrap_or(""),
1187 .span_to_snippet(arg.span)
1188 .unwrap_or_else(|_| {
1189 applicability = Applicability::HasPlaceholders;
1192 .collect::<Vec<_>>()
1196 applicability = Applicability::HasPlaceholders;
1199 err.span_suggestion(
1201 "use associated function syntax instead",
1202 format!("{}::{}{}", ty_str, item_name, args),
1206 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1210 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1211 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1212 fn suggest_calling_field_as_fn(
1216 expr: &hir::Expr<'_>,
1218 err: &mut Diagnostic,
1221 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1222 ty::Adt(def, substs) if !def.is_enum() => {
1223 let variant = &def.non_enum_variant();
1224 tcx.find_field_index(item_name, variant).map(|index| {
1225 let field = &variant.fields[index];
1226 let field_ty = field.ty(tcx, substs);
1232 if let Some((field, field_ty)) = field_receiver {
1233 let scope = tcx.parent_module(self.body_id);
1234 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1237 if self.is_fn_ty(field_ty, span) {
1238 let expr_span = expr.span.to(item_name.span);
1239 err.multipart_suggestion(
1241 "to call the function stored in `{}`, \
1242 surround the field access with parentheses",
1246 (expr_span.shrink_to_lo(), '('.to_string()),
1247 (expr_span.shrink_to_hi(), ')'.to_string()),
1249 Applicability::MachineApplicable,
1252 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1254 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1255 err.span_suggestion(
1257 "remove the arguments",
1259 Applicability::MaybeIncorrect,
1265 let field_kind = if is_accessible { "field" } else { "private field" };
1266 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1272 /// Suggest possible range with adding parentheses, for example:
1273 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1274 fn suggest_wrapping_range_with_parens(
1278 source: SelfSource<'tcx>,
1283 if let SelfSource::MethodCall(expr) = source {
1284 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1285 if let Node::Expr(parent_expr) = parent {
1286 let lang_item = match parent_expr.kind {
1287 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1288 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1289 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1290 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1291 Some(LangItem::RangeToInclusive)
1295 ExprKind::Call(ref func, _) => match func.kind {
1296 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1297 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1298 Some(LangItem::RangeInclusiveStruct)
1305 if lang_item.is_none() {
1309 let span_included = match parent_expr.kind {
1310 hir::ExprKind::Struct(_, eps, _) => {
1311 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1313 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1314 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1322 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1324 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1326 let pick = self.probe_for_name(
1332 ProbeScope::AllTraits,
1335 let range_span = parent_expr.span.with_hi(expr.span.hi());
1336 tcx.sess.emit_err(errors::MissingParentheseInRange {
1338 ty_str: ty_str.to_string(),
1339 method_name: item_name.as_str().to_string(),
1340 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1341 func_name: item_name.name.as_str().to_string(),
1342 left: range_span.shrink_to_lo(),
1343 right: range_span.shrink_to_hi(),
1354 fn suggest_constraining_numerical_ty(
1358 source: SelfSource<'_>,
1364 let found_candidate = all_traits(self.tcx)
1366 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1367 let found_assoc = |ty: Ty<'tcx>| {
1368 simplify_type(tcx, ty, TreatParams::AsInfer)
1370 tcx.incoherent_impls(simp)
1372 .find_map(|&id| self.associated_value(id, item_name))
1376 let found_candidate = found_candidate
1377 || found_assoc(tcx.types.i8)
1378 || found_assoc(tcx.types.i16)
1379 || found_assoc(tcx.types.i32)
1380 || found_assoc(tcx.types.i64)
1381 || found_assoc(tcx.types.i128)
1382 || found_assoc(tcx.types.u8)
1383 || found_assoc(tcx.types.u16)
1384 || found_assoc(tcx.types.u32)
1385 || found_assoc(tcx.types.u64)
1386 || found_assoc(tcx.types.u128)
1387 || found_assoc(tcx.types.f32)
1388 || found_assoc(tcx.types.f32);
1390 && actual.is_numeric()
1391 && !actual.has_concrete_skeleton()
1392 && let SelfSource::MethodCall(expr) = source
1394 let mut err = struct_span_err!(
1398 "can't call {} `{}` on ambiguous numeric type `{}`",
1403 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1405 ExprKind::Lit(ref lit) => {
1410 .span_to_snippet(lit.span)
1411 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1413 // If this is a floating point literal that ends with '.',
1414 // get rid of it to stop this from becoming a member access.
1415 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1416 err.span_suggestion(
1419 "you must specify a concrete type for this numeric value, \
1423 format!("{snippet}_{concrete_type}"),
1424 Applicability::MaybeIncorrect,
1427 ExprKind::Path(QPath::Resolved(_, path)) => {
1429 if let hir::def::Res::Local(hir_id) = path.res {
1430 let span = tcx.hir().span(hir_id);
1431 let filename = tcx.sess.source_map().span_to_filename(span);
1434 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1436 "you must specify a type for this binding, like `{}`",
1440 match (filename, parent_node) {
1443 Node::Local(hir::Local {
1444 source: hir::LocalSource::Normal,
1449 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1450 err.span_suggestion(
1451 // account for `let x: _ = 42;`
1455 format!(": {concrete_type}"),
1456 Applicability::MaybeIncorrect,
1460 err.span_label(span, msg);
1473 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1474 fn suggest_calling_method_on_field(
1476 err: &mut Diagnostic,
1477 source: SelfSource<'tcx>,
1482 if let SelfSource::MethodCall(expr) = source
1483 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1484 && let Some((fields, substs)) =
1485 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1487 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1489 let lang_items = self.tcx.lang_items();
1490 let never_mention_traits = [
1491 lang_items.clone_trait(),
1492 lang_items.deref_trait(),
1493 lang_items.deref_mut_trait(),
1494 self.tcx.get_diagnostic_item(sym::AsRef),
1495 self.tcx.get_diagnostic_item(sym::AsMut),
1496 self.tcx.get_diagnostic_item(sym::Borrow),
1497 self.tcx.get_diagnostic_item(sym::BorrowMut),
1499 let candidate_fields: Vec<_> = fields
1500 .filter_map(|candidate_field| {
1501 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>,
1556 let SelfSource::MethodCall(expr) = source else { return; };
1557 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1559 let ty::Adt(kind, substs) = actual.kind() else { return; };
1560 match kind.adt_kind() {
1561 ty::AdtKind::Enum => {
1562 let matching_variants: Vec<_> = kind
1565 .flat_map(|variant| {
1566 let [field] = &variant.fields[..] else { return None; };
1567 let field_ty = field.ty(tcx, substs);
1569 // Skip `_`, since that'll just lead to ambiguity.
1570 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1574 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1576 .map(|pick| (variant, field, pick))
1580 let ret_ty_matches = |diagnostic_item| {
1581 if let Some(ret_ty) = self
1584 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1585 && let ty::Adt(kind, _) = ret_ty.kind()
1586 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1594 match &matching_variants[..] {
1595 [(_, field, pick)] => {
1596 let self_ty = field.ty(tcx, substs);
1598 tcx.def_span(pick.item.def_id),
1599 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1601 let (article, kind, variant, question) =
1602 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1603 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1604 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1605 ("an", "Option", "None", ret_ty_matches(sym::Option))
1610 err.span_suggestion_verbose(
1611 expr.span.shrink_to_hi(),
1613 "use the `?` operator to extract the `{self_ty}` value, propagating \
1614 {article} `{kind}::{variant}` value to the caller"
1617 Applicability::MachineApplicable,
1620 err.span_suggestion_verbose(
1621 expr.span.shrink_to_hi(),
1623 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1624 panicking if the value is {article} `{kind}::{variant}`"
1626 ".expect(\"REASON\")",
1627 Applicability::HasPlaceholders,
1631 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1635 // Target wrapper types - types that wrap or pretend to wrap another type,
1636 // perhaps this inner type is meant to be called?
1637 ty::AdtKind::Struct | ty::AdtKind::Union => {
1638 let [first] = ***substs else { return; };
1639 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1640 let Ok(pick) = self.lookup_probe(
1644 ProbeScope::TraitsInScope,
1647 let name = self.ty_to_value_string(actual);
1648 let inner_id = kind.did();
1649 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1650 pick.autoref_or_ptr_adjustment
1657 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1658 err.help("use `with` or `try_with` to access thread local storage");
1659 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1661 "if this `{name}` has been initialized, \
1662 use one of the `assume_init` methods to access the inner value"
1664 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1665 let (suggestion, borrow_kind, panic_if) = match mutable {
1666 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1667 Some(Mutability::Mut) => {
1668 (".borrow_mut()", "mutably borrow", "any borrows exist")
1672 err.span_suggestion_verbose(
1673 expr.span.shrink_to_hi(),
1675 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1676 panicking if {panic_if}"
1679 Applicability::MaybeIncorrect,
1681 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1682 err.span_suggestion_verbose(
1683 expr.span.shrink_to_hi(),
1685 "use `.lock().unwrap()` to borrow the `{ty}`, \
1686 blocking the current thread until it can be acquired"
1689 Applicability::MaybeIncorrect,
1691 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1692 let (suggestion, borrow_kind) = match mutable {
1693 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1694 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1697 err.span_suggestion_verbose(
1698 expr.span.shrink_to_hi(),
1700 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1701 blocking the current thread until it can be acquired"
1704 Applicability::MaybeIncorrect,
1711 tcx.def_span(pick.item.def_id),
1712 &format!("the method `{item_name}` exists on the type `{ty}`"),
1718 pub(crate) fn note_unmet_impls_on_type(
1720 err: &mut Diagnostic,
1721 errors: Vec<FulfillmentError<'tcx>>,
1723 let all_local_types_needing_impls =
1724 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1725 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1726 ty::Adt(def, _) => def.did().is_local(),
1731 let mut preds: Vec<_> = errors
1733 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1734 ty::PredicateKind::Trait(pred) => Some(pred),
1738 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1741 .filter_map(|pred| match pred.self_ty().kind() {
1742 ty::Adt(def, _) => Some(def.did()),
1745 .collect::<FxHashSet<_>>();
1746 let mut spans: MultiSpan = def_ids
1748 .filter_map(|def_id| {
1749 let span = self.tcx.def_span(*def_id);
1750 if span.is_dummy() { None } else { Some(span) }
1752 .collect::<Vec<_>>()
1755 for pred in &preds {
1756 match pred.self_ty().kind() {
1757 ty::Adt(def, _) if def.did().is_local() => {
1758 spans.push_span_label(
1759 self.tcx.def_span(def.did()),
1760 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1767 if all_local_types_needing_impls && spans.primary_span().is_some() {
1768 let msg = if preds.len() == 1 {
1770 "an implementation of `{}` might be missing for `{}`",
1771 preds[0].trait_ref.print_only_trait_path(),
1776 "the following type{} would have to `impl` {} required trait{} for this \
1777 operation to be valid",
1778 pluralize!(def_ids.len()),
1779 if def_ids.len() == 1 { "its" } else { "their" },
1780 pluralize!(preds.len()),
1783 err.span_note(spans, &msg);
1786 let preds: Vec<_> = errors
1788 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1790 self.suggest_derive(err, &preds);
1795 err: &mut Diagnostic,
1796 unsatisfied_predicates: &[(
1797 ty::Predicate<'tcx>,
1798 Option<ty::Predicate<'tcx>>,
1799 Option<ObligationCause<'tcx>>,
1802 let mut derives = Vec::<(String, Span, Symbol)>::new();
1803 let mut traits = Vec::<Span>::new();
1804 for (pred, _, _) in unsatisfied_predicates {
1805 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1806 let adt = match trait_pred.self_ty().ty_adt_def() {
1807 Some(adt) if adt.did().is_local() => adt,
1810 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1811 let can_derive = match diagnostic_name {
1812 sym::Default => !adt.is_enum(),
1820 | sym::Debug => true,
1824 let self_name = trait_pred.self_ty().to_string();
1825 let self_span = self.tcx.def_span(adt.did());
1826 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1827 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1829 if let Some(parent_diagnostic_name) =
1830 self.tcx.get_diagnostic_name(super_trait.def_id())
1835 parent_diagnostic_name,
1840 derives.push((self_name, self_span, diagnostic_name));
1842 traits.push(self.tcx.def_span(trait_pred.def_id()));
1845 traits.push(self.tcx.def_span(trait_pred.def_id()));
1854 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1855 for (self_name, self_span, trait_name) in derives.into_iter() {
1856 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1858 if last_self_name == &self_name {
1859 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1863 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1866 let len = traits.len();
1868 let span: MultiSpan = traits.into();
1871 &format!("the following trait{} must be implemented", pluralize!(len),),
1875 for (self_name, self_span, traits) in &derives_grouped {
1876 err.span_suggestion_verbose(
1877 self_span.shrink_to_lo(),
1878 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1879 format!("#[derive({})]\n", traits),
1880 Applicability::MaybeIncorrect,
1885 fn check_for_deref_method(
1887 err: &mut Diagnostic,
1888 self_source: SelfSource<'tcx>,
1892 let SelfSource::QPath(ty) = self_source else { return; };
1893 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1894 if let Ok(pick) = self.probe_for_name(
1900 ProbeScope::TraitsInScope,
1902 if deref_ty.is_suggestable(self.tcx, true)
1903 // If this method receives `&self`, then the provided
1904 // argument _should_ coerce, so it's valid to suggest
1905 // just changing the path.
1906 && pick.item.fn_has_self_parameter
1907 && let Some(self_ty) =
1908 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1911 let suggested_path = match deref_ty.kind() {
1920 | ty::Param(_) => format!("{deref_ty}"),
1921 // we need to test something like <&[_]>::len or <(&[u32])>::len
1922 // and Vec::function();
1923 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
1924 // but for Adt type like Vec::function()
1925 // we would suggest <[_]>::function();
1926 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
1927 _ => format!("<{deref_ty}>"),
1929 err.span_suggestion_verbose(
1931 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1933 Applicability::MaybeIncorrect,
1938 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1946 /// Print out the type for use in value namespace.
1947 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1949 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1950 _ => self.ty_to_string(ty),
1954 fn suggest_await_before_method(
1956 err: &mut Diagnostic,
1959 call: &hir::Expr<'_>,
1962 let output_ty = match self.get_impl_future_output_ty(ty) {
1963 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1966 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1967 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1969 err.span_suggestion_verbose(
1970 span.shrink_to_lo(),
1971 "consider `await`ing on the `Future` and calling the method on its `Output`",
1973 Applicability::MaybeIncorrect,
1978 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1979 let parent_map = self.tcx.visible_parent_map(());
1981 // Separate out candidates that must be imported with a glob, because they are named `_`
1982 // and cannot be referred with their identifier.
1983 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1984 if let Some(parent_did) = parent_map.get(trait_did) {
1985 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1986 if *parent_did != self.tcx.parent(*trait_did)
1989 .module_children(*parent_did)
1991 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1992 .all(|child| child.ident.name == kw::Underscore)
2001 let module_did = self.tcx.parent_module(self.body_id);
2002 let (module, _, _) = self.tcx.hir().get_module(module_did);
2003 let span = module.spans.inject_use_span;
2005 let path_strings = candidates.iter().map(|trait_did| {
2006 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2009 let glob_path_strings = globs.iter().map(|trait_did| {
2010 let parent_did = parent_map.get(trait_did).unwrap();
2012 "use {}::*; // trait {}\n",
2013 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2014 self.tcx.item_name(*trait_did),
2018 err.span_suggestions(
2021 path_strings.chain(glob_path_strings),
2022 Applicability::MaybeIncorrect,
2026 fn suggest_valid_traits(
2028 err: &mut Diagnostic,
2029 valid_out_of_scope_traits: Vec<DefId>,
2031 if !valid_out_of_scope_traits.is_empty() {
2032 let mut candidates = valid_out_of_scope_traits;
2036 // `TryFrom` and `FromIterator` have no methods
2037 let edition_fix = candidates
2039 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2042 err.help("items from traits can only be used if the trait is in scope");
2044 "the following {traits_are} implemented but not in scope; \
2045 perhaps add a `use` for {one_of_them}:",
2046 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2047 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2050 self.suggest_use_candidates(err, msg, candidates);
2051 if let Some(did) = edition_fix {
2053 "'{}' is included in the prelude starting in Edition 2021",
2054 with_crate_prefix!(self.tcx.def_path_str(did))
2064 fn suggest_traits_to_import(
2066 err: &mut Diagnostic,
2070 inputs_len: Option<usize>,
2071 source: SelfSource<'tcx>,
2072 valid_out_of_scope_traits: Vec<DefId>,
2073 unsatisfied_predicates: &[(
2074 ty::Predicate<'tcx>,
2075 Option<ty::Predicate<'tcx>>,
2076 Option<ObligationCause<'tcx>>,
2078 static_candidates: &[CandidateSource],
2079 unsatisfied_bounds: bool,
2081 let mut alt_rcvr_sugg = false;
2082 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2084 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2085 span, item_name, rcvr_ty, rcvr
2088 self.tcx.lang_items().clone_trait(),
2089 self.tcx.lang_items().deref_trait(),
2090 self.tcx.lang_items().deref_mut_trait(),
2091 self.tcx.lang_items().drop_trait(),
2092 self.tcx.get_diagnostic_item(sym::AsRef),
2094 // Try alternative arbitrary self types that could fulfill this call.
2095 // FIXME: probe for all types that *could* be arbitrary self-types, not
2097 for (rcvr_ty, post) in &[
2099 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2100 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2102 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2104 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2105 // We point at the method, but we just skip the rest of the check for arbitrary
2106 // self types and rely on the suggestion to `use` the trait from
2107 // `suggest_valid_traits`.
2108 let did = Some(pick.item.container_id(self.tcx));
2109 let skip = skippable.contains(&did);
2110 if pick.autoderefs == 0 && !skip {
2112 pick.item.ident(self.tcx).span,
2113 &format!("the method is available for `{}` here", rcvr_ty),
2118 Err(MethodError::Ambiguity(_)) => {
2119 // If the method is defined (but ambiguous) for the receiver we have, it is also
2120 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2121 // the receiver, then it might disambiguate this method, but I think these
2122 // suggestions are generally misleading (see #94218).
2128 for (rcvr_ty, pre) in &[
2129 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2130 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2131 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2132 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2134 if let Some(new_rcvr_t) = *rcvr_ty
2135 && let Ok(pick) = self.lookup_probe(
2139 ProbeScope::AllTraits,
2142 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2143 let did = Some(pick.item.container_id(self.tcx));
2144 // We don't want to suggest a container type when the missing
2145 // method is `.clone()` or `.deref()` otherwise we'd suggest
2146 // `Arc::new(foo).clone()`, which is far from what the user wants.
2147 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2148 // implement the `AsRef` trait.
2149 let skip = skippable.contains(&did)
2150 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2151 || 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);
2152 // Make sure the method is defined for the *actual* receiver: we don't
2153 // want to treat `Box<Self>` as a receiver if it only works because of
2154 // an autoderef to `&self`
2155 if pick.autoderefs == 0 && !skip {
2157 pick.item.ident(self.tcx).span,
2158 &format!("the method is available for `{}` here", new_rcvr_t),
2160 err.multipart_suggestion(
2161 "consider wrapping the receiver expression with the \
2164 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2165 (rcvr.span.shrink_to_hi(), ")".to_string()),
2167 Applicability::MaybeIncorrect,
2169 // We don't care about the other suggestions.
2170 alt_rcvr_sugg = true;
2176 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2180 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2182 let mut arbitrary_rcvr = vec![];
2183 // There are no traits implemented, so lets suggest some traits to
2184 // implement, by finding ones that have the item name, and are
2185 // legal to implement.
2186 let mut candidates = all_traits(self.tcx)
2188 // Don't issue suggestions for unstable traits since they're
2189 // unlikely to be implementable anyway
2190 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2191 Some(attr) => attr.level.is_stable(),
2195 // Static candidates are already implemented, and known not to work
2196 // Do not suggest them again
2197 static_candidates.iter().all(|sc| match *sc {
2198 CandidateSource::Trait(def_id) => def_id != info.def_id,
2199 CandidateSource::Impl(def_id) => {
2200 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2205 // We approximate the coherence rules to only suggest
2206 // traits that are legal to implement by requiring that
2207 // either the type or trait is local. Multi-dispatch means
2208 // this isn't perfect (that is, there are cases when
2209 // implementing a trait would be legal but is rejected
2211 unsatisfied_predicates.iter().all(|(p, _, _)| {
2212 match p.kind().skip_binder() {
2213 // Hide traits if they are present in predicates as they can be fixed without
2214 // having to implement them.
2215 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2216 ty::PredicateKind::Projection(p) => {
2217 p.projection_ty.item_def_id == info.def_id
2221 }) && (type_is_local || info.def_id.is_local())
2223 .associated_value(info.def_id, item_name)
2225 if let ty::AssocKind::Fn = item.kind {
2229 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2230 if let Some(hir::Node::TraitItem(hir::TraitItem {
2231 kind: hir::TraitItemKind::Fn(fn_sig, method),
2233 })) = id.map(|id| self.tcx.hir().get(id))
2235 let self_first_arg = match method {
2236 hir::TraitFn::Required([ident, ..]) => {
2237 ident.name == kw::SelfLower
2239 hir::TraitFn::Provided(body_id) => {
2240 self.tcx.hir().body(*body_id).params.first().map_or(
2245 hir::PatKind::Binding(_, _, ident, _)
2246 if ident.name == kw::SelfLower
2254 if !fn_sig.decl.implicit_self.has_implicit_self()
2257 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2258 arbitrary_rcvr.push(ty.span);
2264 // We only want to suggest public or local traits (#45781).
2265 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2269 .collect::<Vec<_>>();
2270 for span in &arbitrary_rcvr {
2273 "the method might not be found because of this arbitrary self type",
2280 if !candidates.is_empty() {
2281 // Sort from most relevant to least relevant.
2282 candidates.sort_by(|a, b| a.cmp(b).reverse());
2285 let param_type = match rcvr_ty.kind() {
2286 ty::Param(param) => Some(param),
2287 ty::Ref(_, ty, _) => match ty.kind() {
2288 ty::Param(param) => Some(param),
2293 err.help(if param_type.is_some() {
2294 "items from traits can only be used if the type parameter is bounded by the trait"
2296 "items from traits can only be used if the trait is implemented and in scope"
2298 let candidates_len = candidates.len();
2299 let message = |action| {
2301 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2304 if candidates_len == 1 { "trait defines" } else { "traits define" },
2306 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2310 // Obtain the span for `param` and use it for a structured suggestion.
2311 if let Some(param) = param_type {
2312 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2313 let type_param = generics.type_param(param, self.tcx);
2314 let hir = self.tcx.hir();
2315 if let Some(def_id) = type_param.def_id.as_local() {
2316 let id = hir.local_def_id_to_hir_id(def_id);
2317 // Get the `hir::Param` to verify whether it already has any bounds.
2318 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2319 // instead we suggest `T: Foo + Bar` in that case.
2321 Node::GenericParam(param) => {
2327 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2328 let (sp, mut introducer) = if let Some(span) =
2329 ast_generics.bounds_span_for_suggestions(def_id)
2331 (span, Introducer::Plus)
2332 } else if let Some(colon_span) = param.colon_span {
2333 (colon_span.shrink_to_hi(), Introducer::Nothing)
2335 (param.span.shrink_to_hi(), Introducer::Colon)
2339 hir::GenericParamKind::Type { synthetic: true, .. },
2341 introducer = Introducer::Plus
2343 let trait_def_ids: FxHashSet<DefId> = ast_generics
2344 .bounds_for_param(def_id)
2345 .flat_map(|bp| bp.bounds.iter())
2346 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2348 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2349 err.span_suggestions(
2352 "restrict type parameter `{}` with",
2355 candidates.iter().map(|t| {
2359 Introducer::Plus => " +",
2360 Introducer::Colon => ":",
2361 Introducer::Nothing => "",
2363 self.tcx.def_path_str(t.def_id),
2366 Applicability::MaybeIncorrect,
2371 Node::Item(hir::Item {
2372 kind: hir::ItemKind::Trait(.., bounds, _),
2376 let (sp, sep, article) = if bounds.is_empty() {
2377 (ident.span.shrink_to_hi(), ":", "a")
2379 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2381 err.span_suggestions(
2383 &message(format!("add {} supertrait for", article)),
2384 candidates.iter().map(|t| {
2385 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2387 Applicability::MaybeIncorrect,
2396 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2397 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2398 // cases where a positive bound implies a negative impl.
2399 (candidates, Vec::new())
2400 } else if let Some(simp_rcvr_ty) =
2401 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2403 let mut potential_candidates = Vec::new();
2404 let mut explicitly_negative = Vec::new();
2405 for candidate in candidates {
2406 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2409 .all_impls(candidate.def_id)
2411 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2414 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2416 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2417 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2420 explicitly_negative.push(candidate);
2422 potential_candidates.push(candidate);
2425 (potential_candidates, explicitly_negative)
2427 // We don't know enough about `recv_ty` to make proper suggestions.
2428 (candidates, Vec::new())
2431 let action = if let Some(param) = param_type {
2432 format!("restrict type parameter `{}` with", param)
2434 // FIXME: it might only need to be imported into scope, not implemented.
2435 "implement".to_string()
2437 match &potential_candidates[..] {
2439 [trait_info] if trait_info.def_id.is_local() => {
2441 self.tcx.def_span(trait_info.def_id),
2443 "`{}` defines an item `{}`, perhaps you need to {} it",
2444 self.tcx.def_path_str(trait_info.def_id),
2451 let mut msg = message(action);
2452 for (i, trait_info) in trait_infos.iter().enumerate() {
2453 msg.push_str(&format!(
2454 "\ncandidate #{}: `{}`",
2456 self.tcx.def_path_str(trait_info.def_id),
2462 match &explicitly_negative[..] {
2466 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2467 self.tcx.def_path_str(trait_info.def_id),
2473 let mut msg = format!(
2474 "the following traits define an item `{}`, but are explicitly unimplemented:",
2477 for trait_info in trait_infos {
2478 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2486 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2487 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2488 pub(crate) fn suggest_else_fn_with_closure(
2490 err: &mut Diagnostic,
2491 expr: &hir::Expr<'_>,
2495 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2496 else { return false; };
2498 if !self.can_coerce(output, expected) {
2502 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2503 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2504 let hir::ExprKind::MethodCall(
2505 hir::PathSegment { ident: method_name, .. },
2509 ) = call_expr.kind &&
2510 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2511 let new_name = Ident {
2512 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2513 span: method_name.span,
2515 let probe = self.lookup_probe(
2519 ProbeScope::TraitsInScope,
2522 // check the method arguments number
2523 if let Ok(pick) = probe &&
2524 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2525 let fn_args = fn_sig.skip_binder().inputs() &&
2526 fn_args.len() == args.len() + 1 {
2527 err.span_suggestion_verbose(
2528 method_name.span.shrink_to_hi(),
2529 &format!("try calling `{}` instead", new_name.name.as_str()),
2531 Applicability::MaybeIncorrect,
2539 /// Checks whether there is a local type somewhere in the chain of
2540 /// autoderefs of `rcvr_ty`.
2541 fn type_derefs_to_local(
2545 source: SelfSource<'tcx>,
2547 fn is_local(ty: Ty<'_>) -> bool {
2549 ty::Adt(def, _) => def.did().is_local(),
2550 ty::Foreign(did) => did.is_local(),
2551 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2552 ty::Param(_) => true,
2554 // Everything else (primitive types, etc.) is effectively
2555 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2556 // the noise from these sort of types is usually just really
2557 // annoying, rather than any sort of help).
2562 // This occurs for UFCS desugaring of `T::method`, where there is no
2563 // receiver expression for the method call, and thus no autoderef.
2564 if let SelfSource::QPath(_) = source {
2565 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2568 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2572 #[derive(Copy, Clone, Debug)]
2573 pub enum SelfSource<'a> {
2574 QPath(&'a hir::Ty<'a>),
2575 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2578 #[derive(Copy, Clone)]
2579 pub struct TraitInfo {
2583 impl PartialEq for TraitInfo {
2584 fn eq(&self, other: &TraitInfo) -> bool {
2585 self.cmp(other) == Ordering::Equal
2588 impl Eq for TraitInfo {}
2589 impl PartialOrd for TraitInfo {
2590 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2591 Some(self.cmp(other))
2594 impl Ord for TraitInfo {
2595 fn cmp(&self, other: &TraitInfo) -> Ordering {
2596 // Local crates are more important than remote ones (local:
2597 // `cnum == 0`), and otherwise we throw in the defid for totality.
2599 let lhs = (other.def_id.krate, other.def_id);
2600 let rhs = (self.def_id.krate, self.def_id);
2605 /// Retrieves all traits in this crate and any dependent crates,
2606 /// and wraps them into `TraitInfo` for custom sorting.
2607 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2608 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2611 fn print_disambiguation_help<'tcx>(
2613 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2614 err: &mut Diagnostic,
2617 kind: ty::AssocKind,
2620 candidate: Option<usize>,
2621 source_map: &source_map::SourceMap,
2622 fn_has_self_parameter: bool,
2624 let mut applicability = Applicability::MachineApplicable;
2625 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2628 if rcvr_ty.is_region_ptr() {
2629 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2633 std::iter::once(receiver)
2635 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2636 applicability = Applicability::HasPlaceholders;
2639 .collect::<Vec<_>>()
2642 let trait_name = if !fn_has_self_parameter {
2643 format!("<{} as {}>", rcvr_ty, trait_name)
2647 (span, format!("{}::{}{}", trait_name, item_name, args))
2649 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2651 err.span_suggestion_verbose(
2654 "disambiguate the {} for {}",
2655 kind.as_def_kind().descr(def_id),
2656 if let Some(candidate) = candidate {
2657 format!("candidate #{}", candidate)
2659 "the candidate".to_string()