1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
13 use rustc_hir::def::DefKind;
14 use rustc_hir::def_id::DefId;
15 use rustc_hir::lang_items::LangItem;
16 use rustc_hir::{ExprKind, Node, QPath};
17 use rustc_infer::infer::{
18 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
21 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
22 use rustc_middle::traits::util::supertraits;
23 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
24 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
25 use rustc_middle::ty::print::with_crate_prefix;
26 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable};
27 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
28 use rustc_span::symbol::{kw, sym, Ident};
29 use rustc_span::Symbol;
30 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
31 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
32 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
33 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
34 use rustc_trait_selection::traits::{
35 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
38 use std::cmp::Ordering;
41 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
42 use super::{CandidateSource, MethodError, NoMatchData};
44 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
45 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
48 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
49 // so we look for these beforehand.
50 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
51 // If it's not a simple function, look for things which implement `FnOnce`.
53 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
57 // This conditional prevents us from asking to call errors and unresolved types.
58 // It might seem that we can use `predicate_must_hold_modulo_regions`,
59 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
60 // type resolution always gives a "maybe" here.
61 if self.autoderef(span, ty).any(|(ty, _)| {
62 info!("check deref {:?} error", ty);
63 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
68 self.autoderef(span, ty).any(|(ty, _)| {
69 info!("check deref {:?} impl FnOnce", ty);
71 let fn_once_substs = tcx.mk_substs_trait(
74 .next_ty_var(TypeVariableOrigin {
75 kind: TypeVariableOriginKind::MiscVariable,
80 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
81 let poly_trait_ref = ty::Binder::dummy(trait_ref);
82 let obligation = Obligation::misc(
86 poly_trait_ref.without_const().to_predicate(tcx),
88 self.predicate_may_hold(&obligation)
95 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
96 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
99 pub fn report_method_error(
104 source: SelfSource<'tcx>,
105 error: MethodError<'tcx>,
106 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
107 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
108 // Avoid suggestions when we don't know what's going on.
109 if rcvr_ty.references_error() {
113 let report_candidates = |span: Span,
114 err: &mut Diagnostic,
115 sources: &mut Vec<CandidateSource>,
119 // Dynamic limit to avoid hiding just one candidate, which is silly.
120 let limit = if sources.len() == 5 { 5 } else { 4 };
122 for (idx, source) in sources.iter().take(limit).enumerate() {
124 CandidateSource::Impl(impl_did) => {
125 // Provide the best span we can. Use the item, if local to crate, else
126 // the impl, if local to crate (item may be defaulted), else nothing.
127 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
128 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
129 self.associated_value(impl_trait_ref.def_id, item_name)
134 let note_span = if item.def_id.is_local() {
135 Some(self.tcx.def_span(item.def_id))
136 } else if impl_did.is_local() {
137 Some(self.tcx.def_span(impl_did))
142 let impl_ty = self.tcx.at(span).type_of(impl_did);
144 let insertion = match self.tcx.impl_trait_ref(impl_did) {
145 None => String::new(),
146 Some(trait_ref) => format!(
147 " of the trait `{}`",
148 self.tcx.def_path_str(trait_ref.def_id)
152 let (note_str, idx) = if sources.len() > 1 {
155 "candidate #{} is defined in an impl{} for the type `{}`",
165 "the candidate is defined in an impl{} for the type `{}`",
171 if let Some(note_span) = note_span {
172 // We have a span pointing to the method. Show note with snippet.
173 err.span_note(note_span, ¬e_str);
177 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
178 let path = self.tcx.def_path_str(trait_ref.def_id);
180 let ty = match item.kind {
181 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
182 ty::AssocKind::Fn => self
188 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
192 print_disambiguation_help(
202 self.tcx.sess.source_map(),
203 item.fn_has_self_parameter,
207 CandidateSource::Trait(trait_did) => {
208 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
209 let item_span = self.tcx.def_span(item.def_id);
210 let idx = if sources.len() > 1 {
212 "candidate #{} is defined in the trait `{}`",
214 self.tcx.def_path_str(trait_did)
216 err.span_note(item_span, msg);
220 "the candidate is defined in the trait `{}`",
221 self.tcx.def_path_str(trait_did)
223 err.span_note(item_span, msg);
226 let path = self.tcx.def_path_str(trait_did);
227 print_disambiguation_help(
237 self.tcx.sess.source_map(),
238 item.fn_has_self_parameter,
243 if sources.len() > limit {
244 err.note(&format!("and {} others", sources.len() - limit));
248 let sugg_span = if let SelfSource::MethodCall(expr) = source {
249 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
250 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
256 MethodError::NoMatch(NoMatchData {
257 mut static_candidates,
258 unsatisfied_predicates,
265 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
266 let ty_str = self.ty_to_string(rcvr_ty);
267 let is_method = mode == Mode::MethodCall;
268 let item_kind = if is_method {
270 } else if rcvr_ty.is_enum() {
271 "variant or associated item"
273 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
274 (Some(name), false) if name.is_lowercase() => "function or associated item",
275 (Some(_), false) => "associated item",
276 (Some(_), true) | (None, false) => "variant or associated item",
277 (None, true) => "variant",
281 if self.suggest_wrapping_range_with_parens(
282 tcx, rcvr_ty, source, span, item_name, &ty_str,
283 ) || self.suggest_constraining_numerical_ty(
284 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
288 span = item_name.span;
290 // Don't show generic arguments when the method can't be found in any implementation (#81576).
291 let mut ty_str_reported = ty_str.clone();
292 if let ty::Adt(_, generics) = rcvr_ty.kind() {
293 if generics.len() > 0 {
294 let mut autoderef = self.autoderef(span, rcvr_ty);
295 let candidate_found = autoderef.any(|(ty, _)| {
296 if let ty::Adt(adt_def, _) = ty.kind() {
298 .inherent_impls(adt_def.did())
300 .filter_map(|def_id| self.associated_value(*def_id, item_name))
307 let has_deref = autoderef.step_count() > 0;
308 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
309 if let Some((path_string, _)) = ty_str.split_once('<') {
310 ty_str_reported = path_string.to_string();
316 let mut err = struct_span_err!(
320 "no {} named `{}` found for {} `{}` in the current scope",
323 rcvr_ty.prefix_string(self.tcx),
326 if rcvr_ty.references_error() {
327 err.downgrade_to_delayed_bug();
330 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
331 self.suggest_await_before_method(
332 &mut err, item_name, rcvr_ty, cal, span,
335 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
338 "you are looking for the module in `std`, not the primitive type",
340 Applicability::MachineApplicable,
343 if let ty::RawPtr(_) = &rcvr_ty.kind() {
345 "try using `<*const T>::as_ref()` to get a reference to the \
346 type behind the pointer: https://doc.rust-lang.org/std/\
347 primitive.pointer.html#method.as_ref",
350 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
351 to invalid or uninitialized memory is undefined behavior",
355 let ty_span = match rcvr_ty.kind() {
356 ty::Param(param_type) => Some(
357 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
359 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
362 if let Some(span) = ty_span {
366 "{item_kind} `{item_name}` not found for this {}",
367 rcvr_ty.prefix_string(self.tcx)
372 if let SelfSource::MethodCall(rcvr_expr) = source {
373 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
377 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
378 let probe = self.lookup_probe(
383 ProbeScope::AllTraits,
389 let mut custom_span_label = false;
391 if !static_candidates.is_empty() {
393 "found the following associated functions; to be used as methods, \
394 functions must have a `self` parameter",
396 err.span_label(span, "this is an associated function, not a method");
397 custom_span_label = true;
399 if static_candidates.len() == 1 {
400 self.suggest_associated_call_syntax(
410 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
411 } else if static_candidates.len() > 1 {
412 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
415 let mut bound_spans = vec![];
416 let mut restrict_type_params = false;
417 let mut unsatisfied_bounds = false;
418 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
419 let msg = "consider using `len` instead";
420 if let SelfSource::MethodCall(_expr) = source {
421 err.span_suggestion_short(
425 Applicability::MachineApplicable,
428 err.span_label(span, msg);
430 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
431 let iterator_trait = self.tcx.def_path_str(iterator_trait);
432 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
434 } else if !unsatisfied_predicates.is_empty() {
435 let mut type_params = FxHashMap::default();
437 // Pick out the list of unimplemented traits on the receiver.
438 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
439 let mut unimplemented_traits = FxHashMap::default();
440 let mut unimplemented_traits_only = true;
441 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
442 if let (ty::PredicateKind::Trait(p), Some(cause)) =
443 (predicate.kind().skip_binder(), cause.as_ref())
445 if p.trait_ref.self_ty() != rcvr_ty {
446 // This is necessary, not just to keep the errors clean, but also
447 // because our derived obligations can wind up with a trait ref that
448 // requires a different param_env to be correctly compared.
451 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
452 predicate.kind().rebind(p.trait_ref),
454 cause: cause.clone(),
455 param_env: self.param_env,
456 predicate: *predicate,
463 // Make sure that, if any traits other than the found ones were involved,
464 // we don't don't report an unimplemented trait.
465 // We don't want to say that `iter::Cloned` is not an iterator, just
466 // because of some non-Clone item being iterated over.
467 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
468 match predicate.kind().skip_binder() {
469 ty::PredicateKind::Trait(p)
470 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
472 unimplemented_traits_only = false;
478 let mut collect_type_param_suggestions =
479 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
480 // We don't care about regions here, so it's fine to skip the binder here.
481 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
482 (self_ty.kind(), parent_pred.kind().skip_binder())
484 let hir = self.tcx.hir();
485 let node = match p.trait_ref.self_ty().kind() {
487 // Account for `fn` items like in `issue-35677.rs` to
488 // suggest restricting its type params.
490 hir.body_owner(hir::BodyId { hir_id: self.body_id });
491 Some(hir.get(parent_body))
494 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
498 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
499 if let Some(g) = kind.generics() {
501 g.tail_span_for_predicate_suggestion(),
502 g.add_where_or_trailing_comma(),
506 .or_insert_with(FxHashSet::default)
507 .insert(obligation.to_owned());
512 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
514 "doesn't satisfy `{}`",
515 if obligation.len() > 50 { quiet } else { obligation }
517 match &self_ty.kind() {
518 // Point at the type that couldn't satisfy the bound.
520 bound_spans.push((self.tcx.def_span(def.did()), msg))
522 // Point at the trait object that couldn't satisfy the bound.
523 ty::Dynamic(preds, _, _) => {
524 for pred in preds.iter() {
525 match pred.skip_binder() {
526 ty::ExistentialPredicate::Trait(tr) => bound_spans
527 .push((self.tcx.def_span(tr.def_id), msg.clone())),
528 ty::ExistentialPredicate::Projection(_)
529 | ty::ExistentialPredicate::AutoTrait(_) => {}
533 // Point at the closure that couldn't satisfy the bound.
534 ty::Closure(def_id, _) => bound_spans.push((
535 tcx.def_span(*def_id),
536 format!("doesn't satisfy `{}`", quiet),
541 let mut format_pred = |pred: ty::Predicate<'tcx>| {
542 let bound_predicate = pred.kind();
543 match bound_predicate.skip_binder() {
544 ty::PredicateKind::Projection(pred) => {
545 let pred = bound_predicate.rebind(pred);
546 // `<Foo as Iterator>::Item = String`.
547 let projection_ty = pred.skip_binder().projection_ty;
549 let substs_with_infer_self = tcx.mk_substs(
550 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
551 .chain(projection_ty.substs.iter().skip(1)),
554 let quiet_projection_ty = ty::ProjectionTy {
555 substs: substs_with_infer_self,
556 item_def_id: projection_ty.item_def_id,
559 let term = pred.skip_binder().term;
561 let obligation = format!("{} = {}", projection_ty, term);
562 let quiet = format!("{} = {}", quiet_projection_ty, term);
564 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
565 Some((obligation, projection_ty.self_ty()))
567 ty::PredicateKind::Trait(poly_trait_ref) => {
568 let p = poly_trait_ref.trait_ref;
569 let self_ty = p.self_ty();
570 let path = p.print_only_trait_path();
571 let obligation = format!("{}: {}", self_ty, path);
572 let quiet = format!("_: {}", path);
573 bound_span_label(self_ty, &obligation, &quiet);
574 Some((obligation, self_ty))
580 // Find all the requirements that come from a local `impl` block.
581 let mut skip_list: FxHashSet<_> = Default::default();
582 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
583 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
585 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
586 .filter_map(|(p, parent, c)| match c.code() {
587 ObligationCauseCode::ImplDerivedObligation(data) => {
588 Some((&data.derived, p, parent, data.impl_def_id, data))
593 let parent_trait_ref = data.parent_trait_pred;
594 let path = parent_trait_ref.print_modifiers_and_trait_path();
595 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
596 let unsatisfied_msg = "unsatisfied trait bound introduced here";
598 "unsatisfied trait bound introduced in this `derive` macro";
599 match self.tcx.hir().get_if_local(impl_def_id) {
600 // Unmet obligation comes from a `derive` macro, point at it once to
601 // avoid multiple span labels pointing at the same place.
602 Some(Node::Item(hir::Item {
603 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
606 self_ty.span.ctxt().outer_expn_data().kind,
607 ExpnKind::Macro(MacroKind::Derive, _)
609 of_trait.as_ref().map(|t| t
615 Some(ExpnKind::Macro(MacroKind::Derive, _))
618 let span = self_ty.span.ctxt().outer_expn_data().call_site;
619 let mut spans: MultiSpan = span.into();
620 spans.push_span_label(span, derive_msg);
621 let entry = spanned_predicates.entry(spans);
622 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
625 // Unmet obligation coming from an `impl`.
626 Some(Node::Item(hir::Item {
628 hir::ItemKind::Impl(hir::Impl {
629 of_trait, self_ty, generics, ..
635 unsatisfied_predicates.iter().any(|(pred, _, _)| {
636 match pred.kind().skip_binder() {
637 ty::PredicateKind::Trait(pred) => {
639 == self.tcx.lang_items().sized_trait()
640 && pred.polarity == ty::ImplPolarity::Positive
645 for param in generics.params {
646 if param.span == cause.span && sized_pred {
647 let (sp, sugg) = match param.colon_span {
648 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
649 None => (param.span.shrink_to_hi(), ": ?Sized"),
651 err.span_suggestion_verbose(
653 "consider relaxing the type parameter's implicit \
656 Applicability::MachineApplicable,
660 if let Some(pred) = parent_p {
661 // Done to add the "doesn't satisfy" `span_label`.
662 let _ = format_pred(*pred);
665 let mut spans = if cause.span != *item_span {
666 let mut spans: MultiSpan = cause.span.into();
667 spans.push_span_label(cause.span, unsatisfied_msg);
670 let mut spans = Vec::with_capacity(2);
671 if let Some(trait_ref) = of_trait {
672 spans.push(trait_ref.path.span);
674 spans.push(self_ty.span);
677 if let Some(trait_ref) = of_trait {
678 spans.push_span_label(trait_ref.path.span, "");
680 spans.push_span_label(self_ty.span, "");
682 let entry = spanned_predicates.entry(spans);
683 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
685 Some(_) => unreachable!(),
689 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
690 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
691 for (span, (_path, _self_ty, preds)) in spanned_predicates {
692 let mut preds: Vec<_> = preds
694 .filter_map(|pred| format_pred(*pred))
695 .map(|(p, _)| format!("`{}`", p))
699 let msg = if let [pred] = &preds[..] {
700 format!("trait bound {} was not satisfied", pred)
703 "the following trait bounds were not satisfied:\n{}",
707 err.span_note(span, &msg);
708 unsatisfied_bounds = true;
711 // The requirements that didn't have an `impl` span to show.
712 let mut bound_list = unsatisfied_predicates
714 .filter_map(|(pred, parent_pred, _cause)| {
715 format_pred(*pred).map(|(p, self_ty)| {
716 collect_type_param_suggestions(self_ty, *pred, &p);
719 None => format!("`{}`", &p),
720 Some(parent_pred) => match format_pred(*parent_pred) {
721 None => format!("`{}`", &p),
722 Some((parent_p, _)) => {
723 collect_type_param_suggestions(
729 "`{}`\nwhich is required by `{}`",
739 .filter(|(_, pred)| !skip_list.contains(&pred))
742 .collect::<Vec<(usize, String)>>();
744 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
745 restrict_type_params = true;
746 // #74886: Sort here so that the output is always the same.
747 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
749 err.span_suggestion_verbose(
752 "consider restricting the type parameter{s} to satisfy the \
754 s = pluralize!(obligations.len())
756 format!("{} {}", add_where_or_comma, obligations.join(", ")),
757 Applicability::MaybeIncorrect,
761 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
762 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
763 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
765 if !bound_list.is_empty() || !skip_list.is_empty() {
766 let bound_list = bound_list
768 .map(|(_, path)| path)
771 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
772 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
773 let (primary_message, label) =
774 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
778 .map(|(_, (trait_ref, obligation))| {
779 if trait_ref.self_ty().references_error()
780 || rcvr_ty.references_error()
785 let OnUnimplementedNote { message, label, .. } = self
787 .on_unimplemented_note(trait_ref, &obligation);
794 let primary_message = primary_message.unwrap_or_else(|| format!(
795 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
797 err.set_primary_message(&primary_message);
798 if let Some(label) = label {
799 custom_span_label = true;
800 err.span_label(span, label);
802 if !bound_list.is_empty() {
804 "the following trait bounds were not satisfied:\n{bound_list}"
807 self.suggest_derive(&mut err, &unsatisfied_predicates);
809 unsatisfied_bounds = true;
813 let label_span_not_found = |err: &mut Diagnostic| {
814 if unsatisfied_predicates.is_empty() {
815 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
816 let is_string_or_ref_str = match rcvr_ty.kind() {
817 ty::Ref(_, ty, _) => {
821 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
824 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
827 if is_string_or_ref_str && item_name.name == sym::iter {
828 err.span_suggestion_verbose(
830 "because of the in-memory representation of `&str`, to obtain \
831 an `Iterator` over each of its codepoint use method `chars`",
833 Applicability::MachineApplicable,
836 if let ty::Adt(adt, _) = rcvr_ty.kind() {
837 let mut inherent_impls_candidate = self
839 .inherent_impls(adt.did())
843 if let Some(assoc) = self.associated_value(*def_id, item_name) {
844 // Check for both mode is the same so we avoid suggesting
845 // incorrect associated item.
846 match (mode, assoc.fn_has_self_parameter, source) {
847 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
848 // We check that the suggest type is actually
849 // different from the received one
850 // So we avoid suggestion method with Box<Self>
852 self.tcx.at(span).type_of(*def_id) != rcvr_ty
853 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
855 (Mode::Path, false, _) => true,
862 .collect::<Vec<_>>();
863 if !inherent_impls_candidate.is_empty() {
864 inherent_impls_candidate.sort();
865 inherent_impls_candidate.dedup();
867 // number of type to shows at most.
868 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
869 let type_candidates = inherent_impls_candidate
873 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
877 let additional_types = if inherent_impls_candidate.len() > limit {
879 "\nand {} more types",
880 inherent_impls_candidate.len() - limit
886 "the {item_kind} was found for\n{}{}",
887 type_candidates, additional_types
892 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
896 // If the method name is the name of a field with a function or closure type,
897 // give a helping note that it has to be called as `(x.f)(...)`.
898 if let SelfSource::MethodCall(expr) = source {
899 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
900 && lev_candidate.is_none()
901 && !custom_span_label
903 label_span_not_found(&mut err);
905 } else if !custom_span_label {
906 label_span_not_found(&mut err);
909 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
910 // can't be called due to `typeof(expr): Clone` not holding.
911 if unsatisfied_predicates.is_empty() {
912 self.suggest_calling_method_on_field(
913 &mut err, source, span, rcvr_ty, item_name,
917 self.check_for_inner_self(&mut err, source, span, rcvr_ty, item_name);
921 for (span, msg) in bound_spans.into_iter() {
922 err.span_label(span, &msg);
925 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
927 self.suggest_traits_to_import(
932 args.map(|(_, args)| args.len() + 1),
935 &unsatisfied_predicates,
941 // Don't emit a suggestion if we found an actual method
942 // that had unsatisfied trait bounds
943 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
944 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
945 if let Some(suggestion) = lev_distance::find_best_match_for_name(
946 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
952 "there is a variant with a similar name",
954 Applicability::MaybeIncorrect,
959 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
960 let msg = "remove this method call";
961 let mut fallback_span = true;
962 if let SelfSource::MethodCall(expr) = source {
964 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
965 if let Some(span) = call_expr.span.trim_start(expr.span) {
966 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
967 fallback_span = false;
971 err.span_label(span, msg);
973 } else if let Some(lev_candidate) = lev_candidate {
974 // Don't emit a suggestion if we found an actual method
975 // that had unsatisfied trait bounds
976 if unsatisfied_predicates.is_empty() {
977 let def_kind = lev_candidate.kind.as_def_kind();
978 // Methods are defined within the context of a struct and their first parameter is always self,
979 // which represents the instance of the struct the method is being called on
980 // Associated functions don’t take self as a parameter and
981 // they are not methods because they don’t have an instance of the struct to work with.
982 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
985 &format!("there is a method with a similar name",),
987 Applicability::MaybeIncorrect,
993 "there is {} {} with a similar name",
995 def_kind.descr(lev_candidate.def_id),
998 Applicability::MaybeIncorrect,
1004 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1009 MethodError::Ambiguity(mut sources) => {
1010 let mut err = struct_span_err!(
1014 "multiple applicable items in scope"
1016 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1018 report_candidates(span, &mut err, &mut sources, sugg_span);
1022 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1023 let kind = kind.descr(def_id);
1024 let mut err = struct_span_err!(
1028 "{} `{}` is private",
1032 err.span_label(item_name.span, &format!("private {}", kind));
1036 .span_if_local(def_id)
1037 .unwrap_or_else(|| self.tcx.def_span(def_id));
1038 err.span_label(sp, &format!("private {} defined here", kind));
1039 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1043 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1044 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1045 let mut err = self.sess().struct_span_err(span, &msg);
1046 err.span_label(bound_span, "this has a `Sized` requirement");
1047 if !candidates.is_empty() {
1049 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1050 add a `use` for {one_of_them}:",
1051 an = if candidates.len() == 1 { "an" } else { "" },
1052 s = pluralize!(candidates.len()),
1053 were = pluralize!("was", candidates.len()),
1054 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1056 self.suggest_use_candidates(&mut err, help, candidates);
1058 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1060 let trait_type = self.tcx.mk_ref(
1062 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1064 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1070 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1075 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1076 /// doesn't take a `self` receiver.
1077 fn suggest_associated_call_syntax(
1079 err: &mut Diagnostic,
1080 static_candidates: &Vec<CandidateSource>,
1082 source: SelfSource<'tcx>,
1084 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1087 let mut has_unsuggestable_args = false;
1088 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1089 // When the "method" is resolved through dereferencing, we really want the
1090 // original type that has the associated function for accurate suggestions.
1092 let impl_ty = self.tcx.type_of(*impl_did);
1093 let target_ty = self
1094 .autoderef(sugg_span, rcvr_ty)
1095 .find(|(rcvr_ty, _)| {
1096 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1097 .types_may_unify(*rcvr_ty, impl_ty)
1099 .map_or(impl_ty, |(ty, _)| ty)
1101 if let ty::Adt(def, substs) = target_ty.kind() {
1102 // If there are any inferred arguments, (`{integer}`), we should replace
1103 // them with underscores to allow the compiler to infer them
1104 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1105 if !arg.is_suggestable(self.tcx, true) {
1106 has_unsuggestable_args = true;
1107 match arg.unpack() {
1108 GenericArgKind::Lifetime(_) => self
1109 .next_region_var(RegionVariableOrigin::MiscVariable(
1110 rustc_span::DUMMY_SP,
1113 GenericArgKind::Type(_) => self
1114 .next_ty_var(TypeVariableOrigin {
1115 span: rustc_span::DUMMY_SP,
1116 kind: TypeVariableOriginKind::MiscVariable,
1119 GenericArgKind::Const(arg) => self
1122 ConstVariableOrigin {
1123 span: rustc_span::DUMMY_SP,
1124 kind: ConstVariableOriginKind::MiscVariable,
1134 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1136 self.ty_to_value_string(target_ty)
1139 self.ty_to_value_string(rcvr_ty.peel_refs())
1141 if let SelfSource::MethodCall(_) = source {
1142 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1143 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1144 && assoc.kind == ty::AssocKind::Fn
1146 let sig = self.tcx.fn_sig(assoc.def_id);
1147 if let Some(first) = sig.inputs().skip_binder().get(0) {
1148 if first.peel_refs() == rcvr_ty.peel_refs() {
1151 Some(if first.is_region_ptr() {
1152 if first.is_mutable_ptr() { "&mut " } else { "&" }
1163 let mut applicability = Applicability::MachineApplicable;
1164 let args = if let Some((receiver, args)) = args {
1165 // The first arg is the same kind as the receiver
1166 let explicit_args = if first_arg.is_some() {
1167 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1169 // There is no `Self` kind to infer the arguments from
1170 if has_unsuggestable_args {
1171 applicability = Applicability::HasPlaceholders;
1173 args.iter().collect()
1177 first_arg.unwrap_or(""),
1184 .span_to_snippet(arg.span)
1185 .unwrap_or_else(|_| {
1186 applicability = Applicability::HasPlaceholders;
1189 .collect::<Vec<_>>()
1193 applicability = Applicability::HasPlaceholders;
1196 err.span_suggestion(
1198 "use associated function syntax instead",
1199 format!("{}::{}{}", ty_str, item_name, args),
1203 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1207 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1208 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1209 fn suggest_calling_field_as_fn(
1213 expr: &hir::Expr<'_>,
1215 err: &mut Diagnostic,
1218 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1219 ty::Adt(def, substs) if !def.is_enum() => {
1220 let variant = &def.non_enum_variant();
1221 tcx.find_field_index(item_name, variant).map(|index| {
1222 let field = &variant.fields[index];
1223 let field_ty = field.ty(tcx, substs);
1229 if let Some((field, field_ty)) = field_receiver {
1230 let scope = tcx.parent_module(self.body_id);
1231 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1234 if self.is_fn_ty(field_ty, span) {
1235 let expr_span = expr.span.to(item_name.span);
1236 err.multipart_suggestion(
1238 "to call the function stored in `{}`, \
1239 surround the field access with parentheses",
1243 (expr_span.shrink_to_lo(), '('.to_string()),
1244 (expr_span.shrink_to_hi(), ')'.to_string()),
1246 Applicability::MachineApplicable,
1249 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1251 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1252 err.span_suggestion(
1254 "remove the arguments",
1256 Applicability::MaybeIncorrect,
1262 let field_kind = if is_accessible { "field" } else { "private field" };
1263 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1269 /// Suggest possible range with adding parentheses, for example:
1270 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1271 fn suggest_wrapping_range_with_parens(
1275 source: SelfSource<'tcx>,
1280 if let SelfSource::MethodCall(expr) = source {
1281 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1282 if let Node::Expr(parent_expr) = parent {
1283 let lang_item = match parent_expr.kind {
1284 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1285 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1286 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1287 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1288 Some(LangItem::RangeToInclusive)
1292 ExprKind::Call(ref func, _) => match func.kind {
1293 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1294 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1295 Some(LangItem::RangeInclusiveStruct)
1302 if lang_item.is_none() {
1306 let span_included = match parent_expr.kind {
1307 hir::ExprKind::Struct(_, eps, _) => {
1308 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1310 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1311 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1319 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1321 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1323 let pick = self.probe_for_name(
1330 ProbeScope::AllTraits,
1333 let range_span = parent_expr.span.with_hi(expr.span.hi());
1334 tcx.sess.emit_err(errors::MissingParentheseInRange {
1336 ty_str: ty_str.to_string(),
1337 method_name: item_name.as_str().to_string(),
1338 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1339 func_name: item_name.name.as_str().to_string(),
1340 left: range_span.shrink_to_lo(),
1341 right: range_span.shrink_to_hi(),
1352 fn suggest_constraining_numerical_ty(
1356 source: SelfSource<'_>,
1362 let found_candidate = all_traits(self.tcx)
1364 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1365 let found_assoc = |ty: Ty<'tcx>| {
1366 simplify_type(tcx, ty, TreatParams::AsInfer)
1368 tcx.incoherent_impls(simp)
1370 .find_map(|&id| self.associated_value(id, item_name))
1374 let found_candidate = found_candidate
1375 || found_assoc(tcx.types.i8)
1376 || found_assoc(tcx.types.i16)
1377 || found_assoc(tcx.types.i32)
1378 || found_assoc(tcx.types.i64)
1379 || found_assoc(tcx.types.i128)
1380 || found_assoc(tcx.types.u8)
1381 || found_assoc(tcx.types.u16)
1382 || found_assoc(tcx.types.u32)
1383 || found_assoc(tcx.types.u64)
1384 || found_assoc(tcx.types.u128)
1385 || found_assoc(tcx.types.f32)
1386 || found_assoc(tcx.types.f32);
1388 && actual.is_numeric()
1389 && !actual.has_concrete_skeleton()
1390 && let SelfSource::MethodCall(expr) = source
1392 let mut err = struct_span_err!(
1396 "can't call {} `{}` on ambiguous numeric type `{}`",
1401 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1403 ExprKind::Lit(ref lit) => {
1408 .span_to_snippet(lit.span)
1409 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1411 // If this is a floating point literal that ends with '.',
1412 // get rid of it to stop this from becoming a member access.
1413 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1414 err.span_suggestion(
1417 "you must specify a concrete type for this numeric value, \
1421 format!("{snippet}_{concrete_type}"),
1422 Applicability::MaybeIncorrect,
1425 ExprKind::Path(QPath::Resolved(_, path)) => {
1427 if let hir::def::Res::Local(hir_id) = path.res {
1428 let span = tcx.hir().span(hir_id);
1429 let filename = tcx.sess.source_map().span_to_filename(span);
1432 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1434 "you must specify a type for this binding, like `{}`",
1438 match (filename, parent_node) {
1441 Node::Local(hir::Local {
1442 source: hir::LocalSource::Normal,
1447 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1448 err.span_suggestion(
1449 // account for `let x: _ = 42;`
1453 format!(": {concrete_type}"),
1454 Applicability::MaybeIncorrect,
1458 err.span_label(span, msg);
1471 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1472 fn suggest_calling_method_on_field(
1474 err: &mut Diagnostic,
1475 source: SelfSource<'tcx>,
1480 if let SelfSource::MethodCall(expr) = source
1481 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1482 && let Some((fields, substs)) =
1483 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1485 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1487 let lang_items = self.tcx.lang_items();
1488 let never_mention_traits = [
1489 lang_items.clone_trait(),
1490 lang_items.deref_trait(),
1491 lang_items.deref_mut_trait(),
1492 self.tcx.get_diagnostic_item(sym::AsRef),
1493 self.tcx.get_diagnostic_item(sym::AsMut),
1494 self.tcx.get_diagnostic_item(sym::Borrow),
1495 self.tcx.get_diagnostic_item(sym::BorrowMut),
1497 let candidate_fields: Vec<_> = fields
1498 .filter_map(|candidate_field| {
1499 self.check_for_nested_field_satisfying(
1507 ProbeScope::TraitsInScope,
1509 .map_or(false, |pick| {
1510 !never_mention_traits
1513 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1525 .map(|id| id.name.to_ident_string())
1526 .collect::<Vec<String>>()
1531 let len = candidate_fields.len();
1533 err.span_suggestions(
1534 item_name.span.shrink_to_lo(),
1536 "{} of the expressions' fields {} a method of the same name",
1537 if len > 1 { "some" } else { "one" },
1538 if len > 1 { "have" } else { "has" },
1540 candidate_fields.iter().map(|path| format!("{path}.")),
1541 Applicability::MaybeIncorrect,
1547 fn check_for_inner_self(
1549 err: &mut Diagnostic,
1550 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() {
1579 ProbeScope::TraitsInScope,
1582 .map(|pick| (variant, field, pick))
1586 let ret_ty_matches = |diagnostic_item| {
1587 if let Some(ret_ty) = self
1590 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1591 && let ty::Adt(kind, _) = ret_ty.kind()
1592 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1600 match &matching_variants[..] {
1601 [(_, field, pick)] => {
1602 let self_ty = field.ty(tcx, substs);
1604 tcx.def_span(pick.item.def_id),
1605 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1607 let (article, kind, variant, question) =
1608 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1609 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1610 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1611 ("an", "Option", "None", ret_ty_matches(sym::Option))
1616 err.span_suggestion_verbose(
1617 expr.span.shrink_to_hi(),
1619 "use the `?` operator to extract the `{self_ty}` value, propagating \
1620 {article} `{kind}::{variant}` value to the caller"
1623 Applicability::MachineApplicable,
1626 err.span_suggestion_verbose(
1627 expr.span.shrink_to_hi(),
1629 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1630 panicking if the value is {article} `{kind}::{variant}`"
1632 ".expect(\"REASON\")",
1633 Applicability::HasPlaceholders,
1637 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1641 // Target wrapper types - types that wrap or pretend to wrap another type,
1642 // perhaps this inner type is meant to be called?
1643 ty::AdtKind::Struct | ty::AdtKind::Union => {
1644 let [first] = ***substs else { return; };
1645 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1646 let Ok(pick) = self.lookup_probe(
1651 ProbeScope::TraitsInScope,
1654 let name = self.ty_to_value_string(actual);
1655 let inner_id = kind.did();
1656 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1657 pick.autoref_or_ptr_adjustment
1664 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1665 err.help("use `with` or `try_with` to access thread local storage");
1666 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1668 "if this `{name}` has been initialized, \
1669 use one of the `assume_init` methods to access the inner value"
1671 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1672 let (suggestion, borrow_kind, panic_if) = match mutable {
1673 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1674 Some(Mutability::Mut) => {
1675 (".borrow_mut()", "mutably borrow", "any borrows exist")
1679 err.span_suggestion_verbose(
1680 expr.span.shrink_to_hi(),
1682 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1683 panicking if {panic_if}"
1686 Applicability::MaybeIncorrect,
1688 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1689 err.span_suggestion_verbose(
1690 expr.span.shrink_to_hi(),
1692 "use `.lock().unwrap()` to borrow the `{ty}`, \
1693 blocking the current thread until it can be acquired"
1696 Applicability::MaybeIncorrect,
1698 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1699 let (suggestion, borrow_kind) = match mutable {
1700 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1701 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1704 err.span_suggestion_verbose(
1705 expr.span.shrink_to_hi(),
1707 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1708 blocking the current thread until it can be acquired"
1711 Applicability::MaybeIncorrect,
1718 tcx.def_span(pick.item.def_id),
1719 &format!("the method `{item_name}` exists on the type `{ty}`"),
1725 pub(crate) fn note_unmet_impls_on_type(
1727 err: &mut Diagnostic,
1728 errors: Vec<FulfillmentError<'tcx>>,
1730 let all_local_types_needing_impls =
1731 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1732 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1733 ty::Adt(def, _) => def.did().is_local(),
1738 let mut preds: Vec<_> = errors
1740 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1741 ty::PredicateKind::Trait(pred) => Some(pred),
1745 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1748 .filter_map(|pred| match pred.self_ty().kind() {
1749 ty::Adt(def, _) => Some(def.did()),
1752 .collect::<FxHashSet<_>>();
1753 let mut spans: MultiSpan = def_ids
1755 .filter_map(|def_id| {
1756 let span = self.tcx.def_span(*def_id);
1757 if span.is_dummy() { None } else { Some(span) }
1759 .collect::<Vec<_>>()
1762 for pred in &preds {
1763 match pred.self_ty().kind() {
1764 ty::Adt(def, _) if def.did().is_local() => {
1765 spans.push_span_label(
1766 self.tcx.def_span(def.did()),
1767 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1774 if all_local_types_needing_impls && spans.primary_span().is_some() {
1775 let msg = if preds.len() == 1 {
1777 "an implementation of `{}` might be missing for `{}`",
1778 preds[0].trait_ref.print_only_trait_path(),
1783 "the following type{} would have to `impl` {} required trait{} for this \
1784 operation to be valid",
1785 pluralize!(def_ids.len()),
1786 if def_ids.len() == 1 { "its" } else { "their" },
1787 pluralize!(preds.len()),
1790 err.span_note(spans, &msg);
1793 let preds: Vec<_> = errors
1795 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1797 self.suggest_derive(err, &preds);
1802 err: &mut Diagnostic,
1803 unsatisfied_predicates: &[(
1804 ty::Predicate<'tcx>,
1805 Option<ty::Predicate<'tcx>>,
1806 Option<ObligationCause<'tcx>>,
1809 let mut derives = Vec::<(String, Span, Symbol)>::new();
1810 let mut traits = Vec::<Span>::new();
1811 for (pred, _, _) in unsatisfied_predicates {
1812 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1813 let adt = match trait_pred.self_ty().ty_adt_def() {
1814 Some(adt) if adt.did().is_local() => adt,
1817 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1818 let can_derive = match diagnostic_name {
1819 sym::Default => !adt.is_enum(),
1827 | sym::Debug => true,
1831 let self_name = trait_pred.self_ty().to_string();
1832 let self_span = self.tcx.def_span(adt.did());
1833 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1834 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1836 if let Some(parent_diagnostic_name) =
1837 self.tcx.get_diagnostic_name(super_trait.def_id())
1842 parent_diagnostic_name,
1847 derives.push((self_name, self_span, diagnostic_name));
1849 traits.push(self.tcx.def_span(trait_pred.def_id()));
1852 traits.push(self.tcx.def_span(trait_pred.def_id()));
1861 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1862 for (self_name, self_span, trait_name) in derives.into_iter() {
1863 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1865 if last_self_name == &self_name {
1866 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1870 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1873 let len = traits.len();
1875 let span: MultiSpan = traits.into();
1878 &format!("the following trait{} must be implemented", pluralize!(len),),
1882 for (self_name, self_span, traits) in &derives_grouped {
1883 err.span_suggestion_verbose(
1884 self_span.shrink_to_lo(),
1885 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1886 format!("#[derive({})]\n", traits),
1887 Applicability::MaybeIncorrect,
1892 fn check_for_deref_method(
1894 err: &mut Diagnostic,
1895 self_source: SelfSource<'tcx>,
1899 let SelfSource::QPath(ty) = self_source else { return; };
1900 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1901 if let Ok(pick) = self.probe_for_name(
1908 ProbeScope::TraitsInScope,
1910 if deref_ty.is_suggestable(self.tcx, true)
1911 // If this method receives `&self`, then the provided
1912 // argument _should_ coerce, so it's valid to suggest
1913 // just changing the path.
1914 && pick.item.fn_has_self_parameter
1915 && let Some(self_ty) =
1916 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1919 let suggested_path = match deref_ty.kind() {
1928 | ty::Param(_) => format!("{deref_ty}"),
1929 // we need to test something like <&[_]>::len
1930 // and Vec::function();
1931 // <&[_]>::len doesn't need an extra "<>" between
1932 // but for Adt type like Vec::function()
1933 // we would suggest <[_]>::function();
1934 _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
1935 _ => format!("<{deref_ty}>"),
1937 err.span_suggestion_verbose(
1939 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1941 Applicability::MaybeIncorrect,
1946 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1954 /// Print out the type for use in value namespace.
1955 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1957 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1958 _ => self.ty_to_string(ty),
1962 fn suggest_await_before_method(
1964 err: &mut Diagnostic,
1967 call: &hir::Expr<'_>,
1970 let output_ty = match self.get_impl_future_output_ty(ty) {
1971 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1974 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1975 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1977 err.span_suggestion_verbose(
1978 span.shrink_to_lo(),
1979 "consider `await`ing on the `Future` and calling the method on its `Output`",
1981 Applicability::MaybeIncorrect,
1986 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1987 let parent_map = self.tcx.visible_parent_map(());
1989 // Separate out candidates that must be imported with a glob, because they are named `_`
1990 // and cannot be referred with their identifier.
1991 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1992 if let Some(parent_did) = parent_map.get(trait_did) {
1993 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1994 if *parent_did != self.tcx.parent(*trait_did)
1997 .module_children(*parent_did)
1999 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2000 .all(|child| child.ident.name == kw::Underscore)
2009 let module_did = self.tcx.parent_module(self.body_id);
2010 let (module, _, _) = self.tcx.hir().get_module(module_did);
2011 let span = module.spans.inject_use_span;
2013 let path_strings = candidates.iter().map(|trait_did| {
2014 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2017 let glob_path_strings = globs.iter().map(|trait_did| {
2018 let parent_did = parent_map.get(trait_did).unwrap();
2020 "use {}::*; // trait {}\n",
2021 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2022 self.tcx.item_name(*trait_did),
2026 err.span_suggestions(
2029 path_strings.chain(glob_path_strings),
2030 Applicability::MaybeIncorrect,
2034 fn suggest_valid_traits(
2036 err: &mut Diagnostic,
2037 valid_out_of_scope_traits: Vec<DefId>,
2039 if !valid_out_of_scope_traits.is_empty() {
2040 let mut candidates = valid_out_of_scope_traits;
2044 // `TryFrom` and `FromIterator` have no methods
2045 let edition_fix = candidates
2047 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2050 err.help("items from traits can only be used if the trait is in scope");
2052 "the following {traits_are} implemented but not in scope; \
2053 perhaps add a `use` for {one_of_them}:",
2054 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2055 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2058 self.suggest_use_candidates(err, msg, candidates);
2059 if let Some(did) = edition_fix {
2061 "'{}' is included in the prelude starting in Edition 2021",
2062 with_crate_prefix!(self.tcx.def_path_str(did))
2072 fn suggest_traits_to_import(
2074 err: &mut Diagnostic,
2078 inputs_len: Option<usize>,
2079 source: SelfSource<'tcx>,
2080 valid_out_of_scope_traits: Vec<DefId>,
2081 unsatisfied_predicates: &[(
2082 ty::Predicate<'tcx>,
2083 Option<ty::Predicate<'tcx>>,
2084 Option<ObligationCause<'tcx>>,
2086 static_candidates: &[CandidateSource],
2087 unsatisfied_bounds: bool,
2089 let mut alt_rcvr_sugg = false;
2090 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2092 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2093 span, item_name, rcvr_ty, rcvr
2096 self.tcx.lang_items().clone_trait(),
2097 self.tcx.lang_items().deref_trait(),
2098 self.tcx.lang_items().deref_mut_trait(),
2099 self.tcx.lang_items().drop_trait(),
2100 self.tcx.get_diagnostic_item(sym::AsRef),
2102 // Try alternative arbitrary self types that could fulfill this call.
2103 // FIXME: probe for all types that *could* be arbitrary self-types, not
2105 for (rcvr_ty, post) in &[
2107 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2108 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2110 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2112 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2113 // We point at the method, but we just skip the rest of the check for arbitrary
2114 // self types and rely on the suggestion to `use` the trait from
2115 // `suggest_valid_traits`.
2116 let did = Some(pick.item.container_id(self.tcx));
2117 let skip = skippable.contains(&did);
2118 if pick.autoderefs == 0 && !skip {
2120 pick.item.ident(self.tcx).span,
2121 &format!("the method is available for `{}` here", rcvr_ty),
2126 Err(MethodError::Ambiguity(_)) => {
2127 // If the method is defined (but ambiguous) for the receiver we have, it is also
2128 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2129 // the receiver, then it might disambiguate this method, but I think these
2130 // suggestions are generally misleading (see #94218).
2136 for (rcvr_ty, pre) in &[
2137 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2138 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2139 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2140 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2142 if let Some(new_rcvr_t) = *rcvr_ty
2143 && let Ok(pick) = self.lookup_probe(
2148 ProbeScope::AllTraits,
2151 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2152 let did = Some(pick.item.container_id(self.tcx));
2153 // We don't want to suggest a container type when the missing
2154 // method is `.clone()` or `.deref()` otherwise we'd suggest
2155 // `Arc::new(foo).clone()`, which is far from what the user wants.
2156 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2157 // implement the `AsRef` trait.
2158 let skip = skippable.contains(&did)
2159 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2160 || 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);
2161 // Make sure the method is defined for the *actual* receiver: we don't
2162 // want to treat `Box<Self>` as a receiver if it only works because of
2163 // an autoderef to `&self`
2164 if pick.autoderefs == 0 && !skip {
2166 pick.item.ident(self.tcx).span,
2167 &format!("the method is available for `{}` here", new_rcvr_t),
2169 err.multipart_suggestion(
2170 "consider wrapping the receiver expression with the \
2173 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2174 (rcvr.span.shrink_to_hi(), ")".to_string()),
2176 Applicability::MaybeIncorrect,
2178 // We don't care about the other suggestions.
2179 alt_rcvr_sugg = true;
2185 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2189 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2191 let mut arbitrary_rcvr = vec![];
2192 // There are no traits implemented, so lets suggest some traits to
2193 // implement, by finding ones that have the item name, and are
2194 // legal to implement.
2195 let mut candidates = all_traits(self.tcx)
2197 // Don't issue suggestions for unstable traits since they're
2198 // unlikely to be implementable anyway
2199 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2200 Some(attr) => attr.level.is_stable(),
2204 // Static candidates are already implemented, and known not to work
2205 // Do not suggest them again
2206 static_candidates.iter().all(|sc| match *sc {
2207 CandidateSource::Trait(def_id) => def_id != info.def_id,
2208 CandidateSource::Impl(def_id) => {
2209 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2214 // We approximate the coherence rules to only suggest
2215 // traits that are legal to implement by requiring that
2216 // either the type or trait is local. Multi-dispatch means
2217 // this isn't perfect (that is, there are cases when
2218 // implementing a trait would be legal but is rejected
2220 unsatisfied_predicates.iter().all(|(p, _, _)| {
2221 match p.kind().skip_binder() {
2222 // Hide traits if they are present in predicates as they can be fixed without
2223 // having to implement them.
2224 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2225 ty::PredicateKind::Projection(p) => {
2226 p.projection_ty.item_def_id == info.def_id
2230 }) && (type_is_local || info.def_id.is_local())
2232 .associated_value(info.def_id, item_name)
2234 if let ty::AssocKind::Fn = item.kind {
2238 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2239 if let Some(hir::Node::TraitItem(hir::TraitItem {
2240 kind: hir::TraitItemKind::Fn(fn_sig, method),
2242 })) = id.map(|id| self.tcx.hir().get(id))
2244 let self_first_arg = match method {
2245 hir::TraitFn::Required([ident, ..]) => {
2246 ident.name == kw::SelfLower
2248 hir::TraitFn::Provided(body_id) => {
2249 self.tcx.hir().body(*body_id).params.first().map_or(
2254 hir::PatKind::Binding(_, _, ident, _)
2255 if ident.name == kw::SelfLower
2263 if !fn_sig.decl.implicit_self.has_implicit_self()
2266 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2267 arbitrary_rcvr.push(ty.span);
2273 // We only want to suggest public or local traits (#45781).
2274 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2278 .collect::<Vec<_>>();
2279 for span in &arbitrary_rcvr {
2282 "the method might not be found because of this arbitrary self type",
2289 if !candidates.is_empty() {
2290 // Sort from most relevant to least relevant.
2291 candidates.sort_by(|a, b| a.cmp(b).reverse());
2294 let param_type = match rcvr_ty.kind() {
2295 ty::Param(param) => Some(param),
2296 ty::Ref(_, ty, _) => match ty.kind() {
2297 ty::Param(param) => Some(param),
2302 err.help(if param_type.is_some() {
2303 "items from traits can only be used if the type parameter is bounded by the trait"
2305 "items from traits can only be used if the trait is implemented and in scope"
2307 let candidates_len = candidates.len();
2308 let message = |action| {
2310 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2313 if candidates_len == 1 { "trait defines" } else { "traits define" },
2315 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2319 // Obtain the span for `param` and use it for a structured suggestion.
2320 if let Some(param) = param_type {
2321 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2322 let type_param = generics.type_param(param, self.tcx);
2323 let hir = self.tcx.hir();
2324 if let Some(def_id) = type_param.def_id.as_local() {
2325 let id = hir.local_def_id_to_hir_id(def_id);
2326 // Get the `hir::Param` to verify whether it already has any bounds.
2327 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2328 // instead we suggest `T: Foo + Bar` in that case.
2330 Node::GenericParam(param) => {
2336 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2337 let (sp, mut introducer) = if let Some(span) =
2338 ast_generics.bounds_span_for_suggestions(def_id)
2340 (span, Introducer::Plus)
2341 } else if let Some(colon_span) = param.colon_span {
2342 (colon_span.shrink_to_hi(), Introducer::Nothing)
2344 (param.span.shrink_to_hi(), Introducer::Colon)
2348 hir::GenericParamKind::Type { synthetic: true, .. },
2350 introducer = Introducer::Plus
2352 let trait_def_ids: FxHashSet<DefId> = ast_generics
2353 .bounds_for_param(def_id)
2354 .flat_map(|bp| bp.bounds.iter())
2355 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2357 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2358 err.span_suggestions(
2361 "restrict type parameter `{}` with",
2364 candidates.iter().map(|t| {
2368 Introducer::Plus => " +",
2369 Introducer::Colon => ":",
2370 Introducer::Nothing => "",
2372 self.tcx.def_path_str(t.def_id),
2375 Applicability::MaybeIncorrect,
2380 Node::Item(hir::Item {
2381 kind: hir::ItemKind::Trait(.., bounds, _),
2385 let (sp, sep, article) = if bounds.is_empty() {
2386 (ident.span.shrink_to_hi(), ":", "a")
2388 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2390 err.span_suggestions(
2392 &message(format!("add {} supertrait for", article)),
2393 candidates.iter().map(|t| {
2394 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2396 Applicability::MaybeIncorrect,
2405 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2406 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2407 // cases where a positive bound implies a negative impl.
2408 (candidates, Vec::new())
2409 } else if let Some(simp_rcvr_ty) =
2410 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2412 let mut potential_candidates = Vec::new();
2413 let mut explicitly_negative = Vec::new();
2414 for candidate in candidates {
2415 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2418 .all_impls(candidate.def_id)
2420 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2423 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2425 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2426 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2429 explicitly_negative.push(candidate);
2431 potential_candidates.push(candidate);
2434 (potential_candidates, explicitly_negative)
2436 // We don't know enough about `recv_ty` to make proper suggestions.
2437 (candidates, Vec::new())
2440 let action = if let Some(param) = param_type {
2441 format!("restrict type parameter `{}` with", param)
2443 // FIXME: it might only need to be imported into scope, not implemented.
2444 "implement".to_string()
2446 match &potential_candidates[..] {
2448 [trait_info] if trait_info.def_id.is_local() => {
2450 self.tcx.def_span(trait_info.def_id),
2452 "`{}` defines an item `{}`, perhaps you need to {} it",
2453 self.tcx.def_path_str(trait_info.def_id),
2460 let mut msg = message(action);
2461 for (i, trait_info) in trait_infos.iter().enumerate() {
2462 msg.push_str(&format!(
2463 "\ncandidate #{}: `{}`",
2465 self.tcx.def_path_str(trait_info.def_id),
2471 match &explicitly_negative[..] {
2475 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2476 self.tcx.def_path_str(trait_info.def_id),
2482 let mut msg = format!(
2483 "the following traits define an item `{}`, but are explicitly unimplemented:",
2486 for trait_info in trait_infos {
2487 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2495 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2496 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2497 pub(crate) fn suggest_else_fn_with_closure(
2499 err: &mut Diagnostic,
2500 expr: &hir::Expr<'_>,
2504 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2505 else { return false; };
2507 if !self.can_coerce(output, expected) {
2511 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2512 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2513 let hir::ExprKind::MethodCall(
2514 hir::PathSegment { ident: method_name, .. },
2518 ) = call_expr.kind &&
2519 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2520 let new_name = Ident {
2521 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2522 span: method_name.span,
2524 let probe = self.lookup_probe(
2529 ProbeScope::TraitsInScope,
2532 // check the method arguments number
2533 if let Ok(pick) = probe &&
2534 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2535 let fn_args = fn_sig.skip_binder().inputs() &&
2536 fn_args.len() == args.len() + 1 {
2537 err.span_suggestion_verbose(
2538 method_name.span.shrink_to_hi(),
2539 &format!("try calling `{}` instead", new_name.name.as_str()),
2541 Applicability::MaybeIncorrect,
2549 /// Checks whether there is a local type somewhere in the chain of
2550 /// autoderefs of `rcvr_ty`.
2551 fn type_derefs_to_local(
2555 source: SelfSource<'tcx>,
2557 fn is_local(ty: Ty<'_>) -> bool {
2559 ty::Adt(def, _) => def.did().is_local(),
2560 ty::Foreign(did) => did.is_local(),
2561 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2562 ty::Param(_) => true,
2564 // Everything else (primitive types, etc.) is effectively
2565 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2566 // the noise from these sort of types is usually just really
2567 // annoying, rather than any sort of help).
2572 // This occurs for UFCS desugaring of `T::method`, where there is no
2573 // receiver expression for the method call, and thus no autoderef.
2574 if let SelfSource::QPath(_) = source {
2575 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2578 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2582 #[derive(Copy, Clone, Debug)]
2583 pub enum SelfSource<'a> {
2584 QPath(&'a hir::Ty<'a>),
2585 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2588 #[derive(Copy, Clone)]
2589 pub struct TraitInfo {
2593 impl PartialEq for TraitInfo {
2594 fn eq(&self, other: &TraitInfo) -> bool {
2595 self.cmp(other) == Ordering::Equal
2598 impl Eq for TraitInfo {}
2599 impl PartialOrd for TraitInfo {
2600 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2601 Some(self.cmp(other))
2604 impl Ord for TraitInfo {
2605 fn cmp(&self, other: &TraitInfo) -> Ordering {
2606 // Local crates are more important than remote ones (local:
2607 // `cnum == 0`), and otherwise we throw in the defid for totality.
2609 let lhs = (other.def_id.krate, other.def_id);
2610 let rhs = (self.def_id.krate, self.def_id);
2615 /// Retrieves all traits in this crate and any dependent crates,
2616 /// and wraps them into `TraitInfo` for custom sorting.
2617 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2618 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2621 fn print_disambiguation_help<'tcx>(
2623 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2624 err: &mut Diagnostic,
2627 kind: ty::AssocKind,
2630 candidate: Option<usize>,
2631 source_map: &source_map::SourceMap,
2632 fn_has_self_parameter: bool,
2634 let mut applicability = Applicability::MachineApplicable;
2635 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2638 if rcvr_ty.is_region_ptr() {
2639 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2643 std::iter::once(receiver)
2645 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2646 applicability = Applicability::HasPlaceholders;
2649 .collect::<Vec<_>>()
2652 let trait_name = if !fn_has_self_parameter {
2653 format!("<{} as {}>", rcvr_ty, trait_name)
2657 (span, format!("{}::{}{}", trait_name, item_name, args))
2659 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2661 err.span_suggestion_verbose(
2664 "disambiguate the {} for {}",
2665 kind.as_def_kind().descr(def_id),
2666 if let Some(candidate) = candidate {
2667 format!("candidate #{}", candidate)
2669 "the candidate".to_string()