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::Clause(ty::Clause::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::Clause(ty::Clause::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::Clause(ty::Clause::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::Clause(ty::Clause::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::Clause(ty::Clause::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::Clause(ty::Clause::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 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1153 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1158 let mut applicability = Applicability::MachineApplicable;
1159 let args = if let Some((receiver, args)) = args {
1160 // The first arg is the same kind as the receiver
1161 let explicit_args = if first_arg.is_some() {
1162 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1164 // There is no `Self` kind to infer the arguments from
1165 if has_unsuggestable_args {
1166 applicability = Applicability::HasPlaceholders;
1168 args.iter().collect()
1172 first_arg.unwrap_or(""),
1179 .span_to_snippet(arg.span)
1180 .unwrap_or_else(|_| {
1181 applicability = Applicability::HasPlaceholders;
1184 .collect::<Vec<_>>()
1188 applicability = Applicability::HasPlaceholders;
1191 err.span_suggestion(
1193 "use associated function syntax instead",
1194 format!("{}::{}{}", ty_str, item_name, args),
1198 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1202 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1203 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1204 fn suggest_calling_field_as_fn(
1208 expr: &hir::Expr<'_>,
1210 err: &mut Diagnostic,
1213 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1214 ty::Adt(def, substs) if !def.is_enum() => {
1215 let variant = &def.non_enum_variant();
1216 tcx.find_field_index(item_name, variant).map(|index| {
1217 let field = &variant.fields[index];
1218 let field_ty = field.ty(tcx, substs);
1224 if let Some((field, field_ty)) = field_receiver {
1225 let scope = tcx.parent_module(self.body_id);
1226 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1229 if self.is_fn_ty(field_ty, span) {
1230 let expr_span = expr.span.to(item_name.span);
1231 err.multipart_suggestion(
1233 "to call the function stored in `{}`, \
1234 surround the field access with parentheses",
1238 (expr_span.shrink_to_lo(), '('.to_string()),
1239 (expr_span.shrink_to_hi(), ')'.to_string()),
1241 Applicability::MachineApplicable,
1244 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1246 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1247 err.span_suggestion(
1249 "remove the arguments",
1251 Applicability::MaybeIncorrect,
1257 let field_kind = if is_accessible { "field" } else { "private field" };
1258 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1264 /// Suggest possible range with adding parentheses, for example:
1265 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1266 fn suggest_wrapping_range_with_parens(
1270 source: SelfSource<'tcx>,
1275 if let SelfSource::MethodCall(expr) = source {
1276 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1277 if let Node::Expr(parent_expr) = parent {
1278 let lang_item = match parent_expr.kind {
1279 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1280 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1281 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1282 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1283 Some(LangItem::RangeToInclusive)
1287 ExprKind::Call(ref func, _) => match func.kind {
1288 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1289 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1290 Some(LangItem::RangeInclusiveStruct)
1297 if lang_item.is_none() {
1301 let span_included = match parent_expr.kind {
1302 hir::ExprKind::Struct(_, eps, _) => {
1303 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1305 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1306 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1314 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1316 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1318 let pick = self.probe_for_name(
1324 ProbeScope::AllTraits,
1327 let range_span = parent_expr.span.with_hi(expr.span.hi());
1328 tcx.sess.emit_err(errors::MissingParentheseInRange {
1330 ty_str: ty_str.to_string(),
1331 method_name: item_name.as_str().to_string(),
1332 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1333 func_name: item_name.name.as_str().to_string(),
1334 left: range_span.shrink_to_lo(),
1335 right: range_span.shrink_to_hi(),
1346 fn suggest_constraining_numerical_ty(
1350 source: SelfSource<'_>,
1356 let found_candidate = all_traits(self.tcx)
1358 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1359 let found_assoc = |ty: Ty<'tcx>| {
1360 simplify_type(tcx, ty, TreatParams::AsInfer)
1362 tcx.incoherent_impls(simp)
1364 .find_map(|&id| self.associated_value(id, item_name))
1368 let found_candidate = found_candidate
1369 || found_assoc(tcx.types.i8)
1370 || found_assoc(tcx.types.i16)
1371 || found_assoc(tcx.types.i32)
1372 || found_assoc(tcx.types.i64)
1373 || found_assoc(tcx.types.i128)
1374 || found_assoc(tcx.types.u8)
1375 || found_assoc(tcx.types.u16)
1376 || found_assoc(tcx.types.u32)
1377 || found_assoc(tcx.types.u64)
1378 || found_assoc(tcx.types.u128)
1379 || found_assoc(tcx.types.f32)
1380 || found_assoc(tcx.types.f32);
1382 && actual.is_numeric()
1383 && !actual.has_concrete_skeleton()
1384 && let SelfSource::MethodCall(expr) = source
1386 let mut err = struct_span_err!(
1390 "can't call {} `{}` on ambiguous numeric type `{}`",
1395 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1397 ExprKind::Lit(ref lit) => {
1402 .span_to_snippet(lit.span)
1403 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1405 // If this is a floating point literal that ends with '.',
1406 // get rid of it to stop this from becoming a member access.
1407 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1408 err.span_suggestion(
1411 "you must specify a concrete type for this numeric value, \
1415 format!("{snippet}_{concrete_type}"),
1416 Applicability::MaybeIncorrect,
1419 ExprKind::Path(QPath::Resolved(_, path)) => {
1421 if let hir::def::Res::Local(hir_id) = path.res {
1422 let span = tcx.hir().span(hir_id);
1423 let filename = tcx.sess.source_map().span_to_filename(span);
1426 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1428 "you must specify a type for this binding, like `{}`",
1432 match (filename, parent_node) {
1435 Node::Local(hir::Local {
1436 source: hir::LocalSource::Normal,
1441 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1442 err.span_suggestion(
1443 // account for `let x: _ = 42;`
1447 format!(": {concrete_type}"),
1448 Applicability::MaybeIncorrect,
1452 err.span_label(span, msg);
1465 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1466 fn suggest_calling_method_on_field(
1468 err: &mut Diagnostic,
1469 source: SelfSource<'tcx>,
1474 if let SelfSource::MethodCall(expr) = source
1475 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1476 && let Some((fields, substs)) =
1477 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1479 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1481 let lang_items = self.tcx.lang_items();
1482 let never_mention_traits = [
1483 lang_items.clone_trait(),
1484 lang_items.deref_trait(),
1485 lang_items.deref_mut_trait(),
1486 self.tcx.get_diagnostic_item(sym::AsRef),
1487 self.tcx.get_diagnostic_item(sym::AsMut),
1488 self.tcx.get_diagnostic_item(sym::Borrow),
1489 self.tcx.get_diagnostic_item(sym::BorrowMut),
1491 let candidate_fields: Vec<_> = fields
1492 .filter_map(|candidate_field| {
1493 self.check_for_nested_field_satisfying(
1500 ProbeScope::TraitsInScope,
1502 .map_or(false, |pick| {
1503 !never_mention_traits
1506 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1518 .map(|id| id.name.to_ident_string())
1519 .collect::<Vec<String>>()
1524 let len = candidate_fields.len();
1526 err.span_suggestions(
1527 item_name.span.shrink_to_lo(),
1529 "{} of the expressions' fields {} a method of the same name",
1530 if len > 1 { "some" } else { "one" },
1531 if len > 1 { "have" } else { "has" },
1533 candidate_fields.iter().map(|path| format!("{path}.")),
1534 Applicability::MaybeIncorrect,
1540 fn check_for_inner_self(
1542 err: &mut Diagnostic,
1543 source: SelfSource<'tcx>,
1548 let SelfSource::MethodCall(expr) = source else { return; };
1549 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1551 let ty::Adt(kind, substs) = actual.kind() else { return; };
1552 match kind.adt_kind() {
1553 ty::AdtKind::Enum => {
1554 let matching_variants: Vec<_> = kind
1557 .flat_map(|variant| {
1558 let [field] = &variant.fields[..] else { return None; };
1559 let field_ty = field.ty(tcx, substs);
1561 // Skip `_`, since that'll just lead to ambiguity.
1562 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1566 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1568 .map(|pick| (variant, field, pick))
1572 let ret_ty_matches = |diagnostic_item| {
1573 if let Some(ret_ty) = self
1576 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1577 && let ty::Adt(kind, _) = ret_ty.kind()
1578 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1586 match &matching_variants[..] {
1587 [(_, field, pick)] => {
1588 let self_ty = field.ty(tcx, substs);
1590 tcx.def_span(pick.item.def_id),
1591 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1593 let (article, kind, variant, question) =
1594 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1595 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1596 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1597 ("an", "Option", "None", ret_ty_matches(sym::Option))
1602 err.span_suggestion_verbose(
1603 expr.span.shrink_to_hi(),
1605 "use the `?` operator to extract the `{self_ty}` value, propagating \
1606 {article} `{kind}::{variant}` value to the caller"
1609 Applicability::MachineApplicable,
1612 err.span_suggestion_verbose(
1613 expr.span.shrink_to_hi(),
1615 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1616 panicking if the value is {article} `{kind}::{variant}`"
1618 ".expect(\"REASON\")",
1619 Applicability::HasPlaceholders,
1623 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1627 // Target wrapper types - types that wrap or pretend to wrap another type,
1628 // perhaps this inner type is meant to be called?
1629 ty::AdtKind::Struct | ty::AdtKind::Union => {
1630 let [first] = ***substs else { return; };
1631 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1632 let Ok(pick) = self.lookup_probe(
1636 ProbeScope::TraitsInScope,
1639 let name = self.ty_to_value_string(actual);
1640 let inner_id = kind.did();
1641 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1642 pick.autoref_or_ptr_adjustment
1649 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1650 err.help("use `with` or `try_with` to access thread local storage");
1651 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1653 "if this `{name}` has been initialized, \
1654 use one of the `assume_init` methods to access the inner value"
1656 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1657 let (suggestion, borrow_kind, panic_if) = match mutable {
1658 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1659 Some(Mutability::Mut) => {
1660 (".borrow_mut()", "mutably borrow", "any borrows exist")
1664 err.span_suggestion_verbose(
1665 expr.span.shrink_to_hi(),
1667 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1668 panicking if {panic_if}"
1671 Applicability::MaybeIncorrect,
1673 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1674 err.span_suggestion_verbose(
1675 expr.span.shrink_to_hi(),
1677 "use `.lock().unwrap()` to borrow the `{ty}`, \
1678 blocking the current thread until it can be acquired"
1681 Applicability::MaybeIncorrect,
1683 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1684 let (suggestion, borrow_kind) = match mutable {
1685 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1686 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1689 err.span_suggestion_verbose(
1690 expr.span.shrink_to_hi(),
1692 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1693 blocking the current thread until it can be acquired"
1696 Applicability::MaybeIncorrect,
1703 tcx.def_span(pick.item.def_id),
1704 &format!("the method `{item_name}` exists on the type `{ty}`"),
1710 pub(crate) fn note_unmet_impls_on_type(
1712 err: &mut Diagnostic,
1713 errors: Vec<FulfillmentError<'tcx>>,
1715 let all_local_types_needing_impls =
1716 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1717 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1718 ty::Adt(def, _) => def.did().is_local(),
1723 let mut preds: Vec<_> = errors
1725 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1726 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1730 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1733 .filter_map(|pred| match pred.self_ty().kind() {
1734 ty::Adt(def, _) => Some(def.did()),
1737 .collect::<FxHashSet<_>>();
1738 let mut spans: MultiSpan = def_ids
1740 .filter_map(|def_id| {
1741 let span = self.tcx.def_span(*def_id);
1742 if span.is_dummy() { None } else { Some(span) }
1744 .collect::<Vec<_>>()
1747 for pred in &preds {
1748 match pred.self_ty().kind() {
1749 ty::Adt(def, _) if def.did().is_local() => {
1750 spans.push_span_label(
1751 self.tcx.def_span(def.did()),
1752 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1759 if all_local_types_needing_impls && spans.primary_span().is_some() {
1760 let msg = if preds.len() == 1 {
1762 "an implementation of `{}` might be missing for `{}`",
1763 preds[0].trait_ref.print_only_trait_path(),
1768 "the following type{} would have to `impl` {} required trait{} for this \
1769 operation to be valid",
1770 pluralize!(def_ids.len()),
1771 if def_ids.len() == 1 { "its" } else { "their" },
1772 pluralize!(preds.len()),
1775 err.span_note(spans, &msg);
1778 let preds: Vec<_> = errors
1780 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1782 self.suggest_derive(err, &preds);
1787 err: &mut Diagnostic,
1788 unsatisfied_predicates: &[(
1789 ty::Predicate<'tcx>,
1790 Option<ty::Predicate<'tcx>>,
1791 Option<ObligationCause<'tcx>>,
1794 let mut derives = Vec::<(String, Span, Symbol)>::new();
1795 let mut traits = Vec::<Span>::new();
1796 for (pred, _, _) in unsatisfied_predicates {
1797 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1798 let adt = match trait_pred.self_ty().ty_adt_def() {
1799 Some(adt) if adt.did().is_local() => adt,
1802 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1803 let can_derive = match diagnostic_name {
1804 sym::Default => !adt.is_enum(),
1812 | sym::Debug => true,
1816 let self_name = trait_pred.self_ty().to_string();
1817 let self_span = self.tcx.def_span(adt.did());
1818 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1819 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1821 if let Some(parent_diagnostic_name) =
1822 self.tcx.get_diagnostic_name(super_trait.def_id())
1827 parent_diagnostic_name,
1832 derives.push((self_name, self_span, diagnostic_name));
1834 traits.push(self.tcx.def_span(trait_pred.def_id()));
1837 traits.push(self.tcx.def_span(trait_pred.def_id()));
1846 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1847 for (self_name, self_span, trait_name) in derives.into_iter() {
1848 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1850 if last_self_name == &self_name {
1851 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1855 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1858 let len = traits.len();
1860 let span: MultiSpan = traits.into();
1863 &format!("the following trait{} must be implemented", pluralize!(len),),
1867 for (self_name, self_span, traits) in &derives_grouped {
1868 err.span_suggestion_verbose(
1869 self_span.shrink_to_lo(),
1870 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1871 format!("#[derive({})]\n", traits),
1872 Applicability::MaybeIncorrect,
1877 fn check_for_deref_method(
1879 err: &mut Diagnostic,
1880 self_source: SelfSource<'tcx>,
1884 let SelfSource::QPath(ty) = self_source else { return; };
1885 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1886 if let Ok(pick) = self.probe_for_name(
1892 ProbeScope::TraitsInScope,
1894 if deref_ty.is_suggestable(self.tcx, true)
1895 // If this method receives `&self`, then the provided
1896 // argument _should_ coerce, so it's valid to suggest
1897 // just changing the path.
1898 && pick.item.fn_has_self_parameter
1899 && let Some(self_ty) =
1900 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1903 let suggested_path = match deref_ty.kind() {
1912 | ty::Param(_) => format!("{deref_ty}"),
1913 // we need to test something like <&[_]>::len or <(&[u32])>::len
1914 // and Vec::function();
1915 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
1916 // but for Adt type like Vec::function()
1917 // we would suggest <[_]>::function();
1918 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
1919 _ => format!("<{deref_ty}>"),
1921 err.span_suggestion_verbose(
1923 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1925 Applicability::MaybeIncorrect,
1930 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1938 /// Print out the type for use in value namespace.
1939 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1941 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1942 _ => self.ty_to_string(ty),
1946 fn suggest_await_before_method(
1948 err: &mut Diagnostic,
1951 call: &hir::Expr<'_>,
1954 let output_ty = match self.get_impl_future_output_ty(ty) {
1955 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
1958 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1959 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1961 err.span_suggestion_verbose(
1962 span.shrink_to_lo(),
1963 "consider `await`ing on the `Future` and calling the method on its `Output`",
1965 Applicability::MaybeIncorrect,
1970 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1971 let parent_map = self.tcx.visible_parent_map(());
1973 // Separate out candidates that must be imported with a glob, because they are named `_`
1974 // and cannot be referred with their identifier.
1975 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1976 if let Some(parent_did) = parent_map.get(trait_did) {
1977 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1978 if *parent_did != self.tcx.parent(*trait_did)
1981 .module_children(*parent_did)
1983 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1984 .all(|child| child.ident.name == kw::Underscore)
1993 let module_did = self.tcx.parent_module(self.body_id);
1994 let (module, _, _) = self.tcx.hir().get_module(module_did);
1995 let span = module.spans.inject_use_span;
1997 let path_strings = candidates.iter().map(|trait_did| {
1998 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2001 let glob_path_strings = globs.iter().map(|trait_did| {
2002 let parent_did = parent_map.get(trait_did).unwrap();
2004 "use {}::*; // trait {}\n",
2005 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2006 self.tcx.item_name(*trait_did),
2010 err.span_suggestions(
2013 path_strings.chain(glob_path_strings),
2014 Applicability::MaybeIncorrect,
2018 fn suggest_valid_traits(
2020 err: &mut Diagnostic,
2021 valid_out_of_scope_traits: Vec<DefId>,
2023 if !valid_out_of_scope_traits.is_empty() {
2024 let mut candidates = valid_out_of_scope_traits;
2028 // `TryFrom` and `FromIterator` have no methods
2029 let edition_fix = candidates
2031 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2034 err.help("items from traits can only be used if the trait is in scope");
2036 "the following {traits_are} implemented but not in scope; \
2037 perhaps add a `use` for {one_of_them}:",
2038 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2039 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2042 self.suggest_use_candidates(err, msg, candidates);
2043 if let Some(did) = edition_fix {
2045 "'{}' is included in the prelude starting in Edition 2021",
2046 with_crate_prefix!(self.tcx.def_path_str(did))
2056 fn suggest_traits_to_import(
2058 err: &mut Diagnostic,
2062 inputs_len: Option<usize>,
2063 source: SelfSource<'tcx>,
2064 valid_out_of_scope_traits: Vec<DefId>,
2065 unsatisfied_predicates: &[(
2066 ty::Predicate<'tcx>,
2067 Option<ty::Predicate<'tcx>>,
2068 Option<ObligationCause<'tcx>>,
2070 static_candidates: &[CandidateSource],
2071 unsatisfied_bounds: bool,
2073 let mut alt_rcvr_sugg = false;
2074 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2076 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2077 span, item_name, rcvr_ty, rcvr
2080 self.tcx.lang_items().clone_trait(),
2081 self.tcx.lang_items().deref_trait(),
2082 self.tcx.lang_items().deref_mut_trait(),
2083 self.tcx.lang_items().drop_trait(),
2084 self.tcx.get_diagnostic_item(sym::AsRef),
2086 // Try alternative arbitrary self types that could fulfill this call.
2087 // FIXME: probe for all types that *could* be arbitrary self-types, not
2089 for (rcvr_ty, post) in &[
2091 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2092 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2094 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2096 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2097 // We point at the method, but we just skip the rest of the check for arbitrary
2098 // self types and rely on the suggestion to `use` the trait from
2099 // `suggest_valid_traits`.
2100 let did = Some(pick.item.container_id(self.tcx));
2101 let skip = skippable.contains(&did);
2102 if pick.autoderefs == 0 && !skip {
2104 pick.item.ident(self.tcx).span,
2105 &format!("the method is available for `{}` here", rcvr_ty),
2110 Err(MethodError::Ambiguity(_)) => {
2111 // If the method is defined (but ambiguous) for the receiver we have, it is also
2112 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2113 // the receiver, then it might disambiguate this method, but I think these
2114 // suggestions are generally misleading (see #94218).
2120 for (rcvr_ty, pre) in &[
2121 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2122 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2123 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2124 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2126 if let Some(new_rcvr_t) = *rcvr_ty
2127 && let Ok(pick) = self.lookup_probe(
2131 ProbeScope::AllTraits,
2134 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2135 let did = Some(pick.item.container_id(self.tcx));
2136 // We don't want to suggest a container type when the missing
2137 // method is `.clone()` or `.deref()` otherwise we'd suggest
2138 // `Arc::new(foo).clone()`, which is far from what the user wants.
2139 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2140 // implement the `AsRef` trait.
2141 let skip = skippable.contains(&did)
2142 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2143 || 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);
2144 // Make sure the method is defined for the *actual* receiver: we don't
2145 // want to treat `Box<Self>` as a receiver if it only works because of
2146 // an autoderef to `&self`
2147 if pick.autoderefs == 0 && !skip {
2149 pick.item.ident(self.tcx).span,
2150 &format!("the method is available for `{}` here", new_rcvr_t),
2152 err.multipart_suggestion(
2153 "consider wrapping the receiver expression with the \
2156 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2157 (rcvr.span.shrink_to_hi(), ")".to_string()),
2159 Applicability::MaybeIncorrect,
2161 // We don't care about the other suggestions.
2162 alt_rcvr_sugg = true;
2168 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2172 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2174 let mut arbitrary_rcvr = vec![];
2175 // There are no traits implemented, so lets suggest some traits to
2176 // implement, by finding ones that have the item name, and are
2177 // legal to implement.
2178 let mut candidates = all_traits(self.tcx)
2180 // Don't issue suggestions for unstable traits since they're
2181 // unlikely to be implementable anyway
2182 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2183 Some(attr) => attr.level.is_stable(),
2187 // Static candidates are already implemented, and known not to work
2188 // Do not suggest them again
2189 static_candidates.iter().all(|sc| match *sc {
2190 CandidateSource::Trait(def_id) => def_id != info.def_id,
2191 CandidateSource::Impl(def_id) => {
2192 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2197 // We approximate the coherence rules to only suggest
2198 // traits that are legal to implement by requiring that
2199 // either the type or trait is local. Multi-dispatch means
2200 // this isn't perfect (that is, there are cases when
2201 // implementing a trait would be legal but is rejected
2203 unsatisfied_predicates.iter().all(|(p, _, _)| {
2204 match p.kind().skip_binder() {
2205 // Hide traits if they are present in predicates as they can be fixed without
2206 // having to implement them.
2207 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2208 t.def_id() == info.def_id
2210 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2211 p.projection_ty.item_def_id == info.def_id
2215 }) && (type_is_local || info.def_id.is_local())
2217 .associated_value(info.def_id, item_name)
2219 if let ty::AssocKind::Fn = item.kind {
2223 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2224 if let Some(hir::Node::TraitItem(hir::TraitItem {
2225 kind: hir::TraitItemKind::Fn(fn_sig, method),
2227 })) = id.map(|id| self.tcx.hir().get(id))
2229 let self_first_arg = match method {
2230 hir::TraitFn::Required([ident, ..]) => {
2231 ident.name == kw::SelfLower
2233 hir::TraitFn::Provided(body_id) => {
2234 self.tcx.hir().body(*body_id).params.first().map_or(
2239 hir::PatKind::Binding(_, _, ident, _)
2240 if ident.name == kw::SelfLower
2248 if !fn_sig.decl.implicit_self.has_implicit_self()
2251 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2252 arbitrary_rcvr.push(ty.span);
2258 // We only want to suggest public or local traits (#45781).
2259 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2263 .collect::<Vec<_>>();
2264 for span in &arbitrary_rcvr {
2267 "the method might not be found because of this arbitrary self type",
2274 if !candidates.is_empty() {
2275 // Sort from most relevant to least relevant.
2276 candidates.sort_by(|a, b| a.cmp(b).reverse());
2279 let param_type = match rcvr_ty.kind() {
2280 ty::Param(param) => Some(param),
2281 ty::Ref(_, ty, _) => match ty.kind() {
2282 ty::Param(param) => Some(param),
2287 err.help(if param_type.is_some() {
2288 "items from traits can only be used if the type parameter is bounded by the trait"
2290 "items from traits can only be used if the trait is implemented and in scope"
2292 let candidates_len = candidates.len();
2293 let message = |action| {
2295 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2298 if candidates_len == 1 { "trait defines" } else { "traits define" },
2300 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2304 // Obtain the span for `param` and use it for a structured suggestion.
2305 if let Some(param) = param_type {
2306 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2307 let type_param = generics.type_param(param, self.tcx);
2308 let hir = self.tcx.hir();
2309 if let Some(def_id) = type_param.def_id.as_local() {
2310 let id = hir.local_def_id_to_hir_id(def_id);
2311 // Get the `hir::Param` to verify whether it already has any bounds.
2312 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2313 // instead we suggest `T: Foo + Bar` in that case.
2315 Node::GenericParam(param) => {
2321 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2322 let (sp, mut introducer) = if let Some(span) =
2323 ast_generics.bounds_span_for_suggestions(def_id)
2325 (span, Introducer::Plus)
2326 } else if let Some(colon_span) = param.colon_span {
2327 (colon_span.shrink_to_hi(), Introducer::Nothing)
2329 (param.span.shrink_to_hi(), Introducer::Colon)
2333 hir::GenericParamKind::Type { synthetic: true, .. },
2335 introducer = Introducer::Plus
2337 let trait_def_ids: FxHashSet<DefId> = ast_generics
2338 .bounds_for_param(def_id)
2339 .flat_map(|bp| bp.bounds.iter())
2340 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2342 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2343 err.span_suggestions(
2346 "restrict type parameter `{}` with",
2349 candidates.iter().map(|t| {
2353 Introducer::Plus => " +",
2354 Introducer::Colon => ":",
2355 Introducer::Nothing => "",
2357 self.tcx.def_path_str(t.def_id),
2360 Applicability::MaybeIncorrect,
2365 Node::Item(hir::Item {
2366 kind: hir::ItemKind::Trait(.., bounds, _),
2370 let (sp, sep, article) = if bounds.is_empty() {
2371 (ident.span.shrink_to_hi(), ":", "a")
2373 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2375 err.span_suggestions(
2377 &message(format!("add {} supertrait for", article)),
2378 candidates.iter().map(|t| {
2379 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2381 Applicability::MaybeIncorrect,
2390 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2391 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2392 // cases where a positive bound implies a negative impl.
2393 (candidates, Vec::new())
2394 } else if let Some(simp_rcvr_ty) =
2395 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2397 let mut potential_candidates = Vec::new();
2398 let mut explicitly_negative = Vec::new();
2399 for candidate in candidates {
2400 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2403 .all_impls(candidate.def_id)
2405 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2408 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2410 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2411 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2414 explicitly_negative.push(candidate);
2416 potential_candidates.push(candidate);
2419 (potential_candidates, explicitly_negative)
2421 // We don't know enough about `recv_ty` to make proper suggestions.
2422 (candidates, Vec::new())
2425 let action = if let Some(param) = param_type {
2426 format!("restrict type parameter `{}` with", param)
2428 // FIXME: it might only need to be imported into scope, not implemented.
2429 "implement".to_string()
2431 match &potential_candidates[..] {
2433 [trait_info] if trait_info.def_id.is_local() => {
2435 self.tcx.def_span(trait_info.def_id),
2437 "`{}` defines an item `{}`, perhaps you need to {} it",
2438 self.tcx.def_path_str(trait_info.def_id),
2445 let mut msg = message(action);
2446 for (i, trait_info) in trait_infos.iter().enumerate() {
2447 msg.push_str(&format!(
2448 "\ncandidate #{}: `{}`",
2450 self.tcx.def_path_str(trait_info.def_id),
2456 match &explicitly_negative[..] {
2460 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2461 self.tcx.def_path_str(trait_info.def_id),
2467 let mut msg = format!(
2468 "the following traits define an item `{}`, but are explicitly unimplemented:",
2471 for trait_info in trait_infos {
2472 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2480 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2481 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2482 pub(crate) fn suggest_else_fn_with_closure(
2484 err: &mut Diagnostic,
2485 expr: &hir::Expr<'_>,
2489 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2490 else { return false; };
2492 if !self.can_coerce(output, expected) {
2496 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2497 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2498 let hir::ExprKind::MethodCall(
2499 hir::PathSegment { ident: method_name, .. },
2503 ) = call_expr.kind &&
2504 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2505 let new_name = Ident {
2506 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2507 span: method_name.span,
2509 let probe = self.lookup_probe(
2513 ProbeScope::TraitsInScope,
2516 // check the method arguments number
2517 if let Ok(pick) = probe &&
2518 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2519 let fn_args = fn_sig.skip_binder().inputs() &&
2520 fn_args.len() == args.len() + 1 {
2521 err.span_suggestion_verbose(
2522 method_name.span.shrink_to_hi(),
2523 &format!("try calling `{}` instead", new_name.name.as_str()),
2525 Applicability::MaybeIncorrect,
2533 /// Checks whether there is a local type somewhere in the chain of
2534 /// autoderefs of `rcvr_ty`.
2535 fn type_derefs_to_local(
2539 source: SelfSource<'tcx>,
2541 fn is_local(ty: Ty<'_>) -> bool {
2543 ty::Adt(def, _) => def.did().is_local(),
2544 ty::Foreign(did) => did.is_local(),
2545 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2546 ty::Param(_) => true,
2548 // Everything else (primitive types, etc.) is effectively
2549 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2550 // the noise from these sort of types is usually just really
2551 // annoying, rather than any sort of help).
2556 // This occurs for UFCS desugaring of `T::method`, where there is no
2557 // receiver expression for the method call, and thus no autoderef.
2558 if let SelfSource::QPath(_) = source {
2559 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2562 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2566 #[derive(Copy, Clone, Debug)]
2567 pub enum SelfSource<'a> {
2568 QPath(&'a hir::Ty<'a>),
2569 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2572 #[derive(Copy, Clone)]
2573 pub struct TraitInfo {
2577 impl PartialEq for TraitInfo {
2578 fn eq(&self, other: &TraitInfo) -> bool {
2579 self.cmp(other) == Ordering::Equal
2582 impl Eq for TraitInfo {}
2583 impl PartialOrd for TraitInfo {
2584 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2585 Some(self.cmp(other))
2588 impl Ord for TraitInfo {
2589 fn cmp(&self, other: &TraitInfo) -> Ordering {
2590 // Local crates are more important than remote ones (local:
2591 // `cnum == 0`), and otherwise we throw in the defid for totality.
2593 let lhs = (other.def_id.krate, other.def_id);
2594 let rhs = (self.def_id.krate, self.def_id);
2599 /// Retrieves all traits in this crate and any dependent crates,
2600 /// and wraps them into `TraitInfo` for custom sorting.
2601 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2602 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2605 fn print_disambiguation_help<'tcx>(
2607 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2608 err: &mut Diagnostic,
2611 kind: ty::AssocKind,
2614 candidate: Option<usize>,
2615 source_map: &source_map::SourceMap,
2616 fn_has_self_parameter: bool,
2618 let mut applicability = Applicability::MachineApplicable;
2619 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2622 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2623 std::iter::once(receiver)
2625 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2626 applicability = Applicability::HasPlaceholders;
2629 .collect::<Vec<_>>()
2632 let trait_name = if !fn_has_self_parameter {
2633 format!("<{} as {}>", rcvr_ty, trait_name)
2637 (span, format!("{}::{}{}", trait_name, item_name, args))
2639 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2641 err.span_suggestion_verbose(
2644 "disambiguate the {} for {}",
2645 kind.as_def_kind().descr(def_id),
2646 if let Some(candidate) = candidate {
2647 format!("candidate #{}", candidate)
2649 "the candidate".to_string()