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::{simplify_type, TreatParams};
24 use rustc_middle::ty::print::with_crate_prefix;
25 use rustc_middle::ty::{
26 self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable,
28 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
29 use rustc_span::symbol::{kw, sym, Ident};
30 use rustc_span::Symbol;
31 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
32 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
33 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
34 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
35 use rustc_trait_selection::traits::{
36 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
39 use std::cmp::Ordering;
42 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
43 use super::{CandidateSource, MethodError, NoMatchData};
45 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
49 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
50 // so we look for these beforehand.
51 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
52 // If it's not a simple function, look for things which implement `FnOnce`.
54 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
58 // This conditional prevents us from asking to call errors and unresolved types.
59 // It might seem that we can use `predicate_must_hold_modulo_regions`,
60 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
61 // type resolution always gives a "maybe" here.
62 if self.autoderef(span, ty).any(|(ty, _)| {
63 info!("check deref {:?} error", ty);
64 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
69 self.autoderef(span, ty).any(|(ty, _)| {
70 info!("check deref {:?} impl FnOnce", ty);
72 let fn_once_substs = tcx.mk_substs_trait(
75 .next_ty_var(TypeVariableOrigin {
76 kind: TypeVariableOriginKind::MiscVariable,
81 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
82 let poly_trait_ref = ty::Binder::dummy(trait_ref);
83 let obligation = Obligation::misc(
87 poly_trait_ref.without_const().to_predicate(tcx),
89 self.predicate_may_hold(&obligation)
96 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
97 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
100 pub fn report_method_error(
105 source: SelfSource<'tcx>,
106 error: MethodError<'tcx>,
107 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
108 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
109 // Avoid suggestions when we don't know what's going on.
110 if rcvr_ty.references_error() {
114 let report_candidates = |span: Span,
115 err: &mut Diagnostic,
116 sources: &mut Vec<CandidateSource>,
120 // Dynamic limit to avoid hiding just one candidate, which is silly.
121 let limit = if sources.len() == 5 { 5 } else { 4 };
123 for (idx, source) in sources.iter().take(limit).enumerate() {
125 CandidateSource::Impl(impl_did) => {
126 // Provide the best span we can. Use the item, if local to crate, else
127 // the impl, if local to crate (item may be defaulted), else nothing.
128 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
129 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
130 self.associated_value(impl_trait_ref.def_id, item_name)
135 let note_span = if item.def_id.is_local() {
136 Some(self.tcx.def_span(item.def_id))
137 } else if impl_did.is_local() {
138 Some(self.tcx.def_span(impl_did))
143 let impl_ty = self.tcx.at(span).type_of(impl_did);
145 let insertion = match self.tcx.impl_trait_ref(impl_did) {
146 None => String::new(),
147 Some(trait_ref) => format!(
148 " of the trait `{}`",
149 self.tcx.def_path_str(trait_ref.def_id)
153 let (note_str, idx) = if sources.len() > 1 {
156 "candidate #{} is defined in an impl{} for the type `{}`",
166 "the candidate is defined in an impl{} for the type `{}`",
172 if let Some(note_span) = note_span {
173 // We have a span pointing to the method. Show note with snippet.
174 err.span_note(note_span, ¬e_str);
178 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
179 let path = self.tcx.def_path_str(trait_ref.def_id);
181 let ty = match item.kind {
182 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
183 ty::AssocKind::Fn => self
189 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
193 print_disambiguation_help(
203 self.tcx.sess.source_map(),
204 item.fn_has_self_parameter,
208 CandidateSource::Trait(trait_did) => {
209 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
210 let item_span = self.tcx.def_span(item.def_id);
211 let idx = if sources.len() > 1 {
213 "candidate #{} is defined in the trait `{}`",
215 self.tcx.def_path_str(trait_did)
217 err.span_note(item_span, msg);
221 "the candidate is defined in the trait `{}`",
222 self.tcx.def_path_str(trait_did)
224 err.span_note(item_span, msg);
227 let path = self.tcx.def_path_str(trait_did);
228 print_disambiguation_help(
238 self.tcx.sess.source_map(),
239 item.fn_has_self_parameter,
244 if sources.len() > limit {
245 err.note(&format!("and {} others", sources.len() - limit));
249 let sugg_span = if let SelfSource::MethodCall(expr) = source {
250 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
251 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
257 MethodError::NoMatch(NoMatchData {
258 mut static_candidates,
259 unsatisfied_predicates,
266 let actual = self.resolve_vars_if_possible(rcvr_ty);
267 let ty_str = self.ty_to_string(actual);
268 let is_method = mode == Mode::MethodCall;
269 let item_kind = if is_method {
271 } else if actual.is_enum() {
272 "variant or associated item"
274 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
275 (Some(name), false) if name.is_lowercase() => "function or associated item",
276 (Some(_), false) => "associated item",
277 (Some(_), true) | (None, false) => "variant or associated item",
278 (None, true) => "variant",
282 if self.suggest_wrapping_range_with_parens(
283 tcx, actual, source, span, item_name, &ty_str,
284 ) || self.suggest_constraining_numerical_ty(
285 tcx, actual, source, span, item_kind, item_name, &ty_str,
289 span = item_name.span;
291 // Don't show generic arguments when the method can't be found in any implementation (#81576).
292 let mut ty_str_reported = ty_str.clone();
293 if let ty::Adt(_, generics) = actual.kind() {
294 if generics.len() > 0 {
295 let mut autoderef = self.autoderef(span, actual);
296 let candidate_found = autoderef.any(|(ty, _)| {
297 if let ty::Adt(adt_def, _) = ty.kind() {
299 .inherent_impls(adt_def.did())
301 .filter_map(|def_id| self.associated_value(*def_id, item_name))
308 let has_deref = autoderef.step_count() > 0;
309 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
310 if let Some((path_string, _)) = ty_str.split_once('<') {
311 ty_str_reported = path_string.to_string();
317 let mut err = struct_span_err!(
321 "no {} named `{}` found for {} `{}` in the current scope",
324 actual.prefix_string(self.tcx),
327 if actual.references_error() {
328 err.downgrade_to_delayed_bug();
331 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
332 self.suggest_await_before_method(
333 &mut err, item_name, actual, cal, span,
336 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
339 "you are looking for the module in `std`, not the primitive type",
341 Applicability::MachineApplicable,
344 if let ty::RawPtr(_) = &actual.kind() {
346 "try using `<*const T>::as_ref()` to get a reference to the \
347 type behind the pointer: https://doc.rust-lang.org/std/\
348 primitive.pointer.html#method.as_ref",
351 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
352 to invalid or uninitialized memory is undefined behavior",
356 let ty_span = match actual.kind() {
357 ty::Param(param_type) => Some(
358 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
360 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
363 if let Some(span) = ty_span {
367 "{item_kind} `{item_name}` not found for this {}",
368 actual.prefix_string(self.tcx)
373 if let SelfSource::MethodCall(rcvr_expr) = source {
374 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
378 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
379 let probe = self.lookup_probe(
384 ProbeScope::AllTraits,
390 let mut custom_span_label = false;
392 if !static_candidates.is_empty() {
394 "found the following associated functions; to be used as methods, \
395 functions must have a `self` parameter",
397 err.span_label(span, "this is an associated function, not a method");
398 custom_span_label = true;
400 if static_candidates.len() == 1 {
401 let mut has_unsuggestable_args = false;
402 let ty_str = if let Some(CandidateSource::Impl(impl_did)) =
403 static_candidates.get(0)
405 // When the "method" is resolved through dereferencing, we really want the
406 // original type that has the associated function for accurate suggestions.
408 let ty = tcx.at(span).type_of(*impl_did);
409 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
410 (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => {
411 // If there are any inferred arguments, (`{integer}`), we should replace
412 // them with underscores to allow the compiler to infer them
413 let infer_substs: Vec<GenericArg<'_>> = substs
416 if !arg.is_suggestable(tcx, true) {
417 has_unsuggestable_args = true;
419 GenericArgKind::Lifetime(_) => self
420 .next_region_var(RegionVariableOrigin::MiscVariable(
421 rustc_span::DUMMY_SP,
424 GenericArgKind::Type(_) => self
425 .next_ty_var(TypeVariableOrigin {
426 span: rustc_span::DUMMY_SP,
427 kind: TypeVariableOriginKind::MiscVariable,
430 GenericArgKind::Const(arg) => self
433 ConstVariableOrigin {
434 span: rustc_span::DUMMY_SP,
435 kind: ConstVariableOriginKind::MiscVariable,
444 .collect::<Vec<_>>();
446 tcx.value_path_str_with_substs(
448 tcx.intern_substs(&infer_substs),
451 _ => self.ty_to_value_string(ty.peel_refs()),
454 self.ty_to_value_string(actual.peel_refs())
456 if let SelfSource::MethodCall(_) = source {
457 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) &&
458 let Some(assoc) = self.associated_value(*impl_did, item_name) {
459 let sig = self.tcx.fn_sig(assoc.def_id);
460 if let Some(first) = sig.inputs().skip_binder().get(0) {
461 if first.peel_refs() == rcvr_ty.peel_refs() {
464 Some(if first.is_region_ptr() {
465 if first.is_mutable_ptr() { "&mut " } else { "&" }
476 let mut applicability = Applicability::MachineApplicable;
477 let args = if let Some((receiver, args)) = args {
478 // The first arg is the same kind as the receiver
479 let explicit_args = if first_arg.is_some() {
480 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
482 // There is no `Self` kind to infer the arguments from
483 if has_unsuggestable_args {
484 applicability = Applicability::HasPlaceholders;
486 args.iter().collect()
490 first_arg.unwrap_or(""),
496 .span_to_snippet(arg.span)
497 .unwrap_or_else(|_| {
498 applicability = Applicability::HasPlaceholders;
505 applicability = Applicability::HasPlaceholders;
510 "use associated function syntax instead",
511 format!("{}::{}{}", ty_str, item_name, args),
515 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
518 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
519 } else if static_candidates.len() > 1 {
520 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
523 let mut bound_spans = vec![];
524 let mut restrict_type_params = false;
525 let mut unsatisfied_bounds = false;
526 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
527 let msg = "consider using `len` instead";
528 if let SelfSource::MethodCall(_expr) = source {
529 err.span_suggestion_short(
533 Applicability::MachineApplicable,
536 err.span_label(span, msg);
538 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
539 let iterator_trait = self.tcx.def_path_str(iterator_trait);
540 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
542 } else if !unsatisfied_predicates.is_empty() {
543 let mut type_params = FxHashMap::default();
545 // Pick out the list of unimplemented traits on the receiver.
546 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
547 let mut unimplemented_traits = FxHashMap::default();
548 let mut unimplemented_traits_only = true;
549 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
550 if let (ty::PredicateKind::Trait(p), Some(cause)) =
551 (predicate.kind().skip_binder(), cause.as_ref())
553 if p.trait_ref.self_ty() != rcvr_ty {
554 // This is necessary, not just to keep the errors clean, but also
555 // because our derived obligations can wind up with a trait ref that
556 // requires a different param_env to be correctly compared.
559 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
560 predicate.kind().rebind(p.trait_ref),
562 cause: cause.clone(),
563 param_env: self.param_env,
564 predicate: *predicate,
571 // Make sure that, if any traits other than the found ones were involved,
572 // we don't don't report an unimplemented trait.
573 // We don't want to say that `iter::Cloned` is not an iterator, just
574 // because of some non-Clone item being iterated over.
575 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
576 match predicate.kind().skip_binder() {
577 ty::PredicateKind::Trait(p)
578 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
580 unimplemented_traits_only = false;
586 let mut collect_type_param_suggestions =
587 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
588 // We don't care about regions here, so it's fine to skip the binder here.
589 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
590 (self_ty.kind(), parent_pred.kind().skip_binder())
592 let hir = self.tcx.hir();
593 let node = match p.trait_ref.self_ty().kind() {
595 // Account for `fn` items like in `issue-35677.rs` to
596 // suggest restricting its type params.
598 hir.body_owner(hir::BodyId { hir_id: self.body_id });
599 Some(hir.get(parent_body))
602 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
606 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
607 if let Some(g) = kind.generics() {
609 g.tail_span_for_predicate_suggestion(),
610 g.add_where_or_trailing_comma(),
614 .or_insert_with(FxHashSet::default)
615 .insert(obligation.to_owned());
620 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
622 "doesn't satisfy `{}`",
623 if obligation.len() > 50 { quiet } else { obligation }
625 match &self_ty.kind() {
626 // Point at the type that couldn't satisfy the bound.
628 bound_spans.push((self.tcx.def_span(def.did()), msg))
630 // Point at the trait object that couldn't satisfy the bound.
631 ty::Dynamic(preds, _, _) => {
632 for pred in preds.iter() {
633 match pred.skip_binder() {
634 ty::ExistentialPredicate::Trait(tr) => bound_spans
635 .push((self.tcx.def_span(tr.def_id), msg.clone())),
636 ty::ExistentialPredicate::Projection(_)
637 | ty::ExistentialPredicate::AutoTrait(_) => {}
641 // Point at the closure that couldn't satisfy the bound.
642 ty::Closure(def_id, _) => bound_spans.push((
643 tcx.def_span(*def_id),
644 format!("doesn't satisfy `{}`", quiet),
649 let mut format_pred = |pred: ty::Predicate<'tcx>| {
650 let bound_predicate = pred.kind();
651 match bound_predicate.skip_binder() {
652 ty::PredicateKind::Projection(pred) => {
653 let pred = bound_predicate.rebind(pred);
654 // `<Foo as Iterator>::Item = String`.
655 let projection_ty = pred.skip_binder().projection_ty;
657 let substs_with_infer_self = tcx.mk_substs(
658 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
659 .chain(projection_ty.substs.iter().skip(1)),
662 let quiet_projection_ty = ty::ProjectionTy {
663 substs: substs_with_infer_self,
664 item_def_id: projection_ty.item_def_id,
667 let term = pred.skip_binder().term;
669 let obligation = format!("{} = {}", projection_ty, term);
670 let quiet = format!("{} = {}", quiet_projection_ty, term);
672 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
673 Some((obligation, projection_ty.self_ty()))
675 ty::PredicateKind::Trait(poly_trait_ref) => {
676 let p = poly_trait_ref.trait_ref;
677 let self_ty = p.self_ty();
678 let path = p.print_only_trait_path();
679 let obligation = format!("{}: {}", self_ty, path);
680 let quiet = format!("_: {}", path);
681 bound_span_label(self_ty, &obligation, &quiet);
682 Some((obligation, self_ty))
688 // Find all the requirements that come from a local `impl` block.
689 let mut skip_list: FxHashSet<_> = Default::default();
690 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
691 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
693 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
694 .filter_map(|(p, parent, c)| match c.code() {
695 ObligationCauseCode::ImplDerivedObligation(data) => {
696 Some((&data.derived, p, parent, data.impl_def_id, data))
701 let parent_trait_ref = data.parent_trait_pred;
702 let path = parent_trait_ref.print_modifiers_and_trait_path();
703 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
704 let unsatisfied_msg = "unsatisfied trait bound introduced here";
706 "unsatisfied trait bound introduced in this `derive` macro";
707 match self.tcx.hir().get_if_local(impl_def_id) {
708 // Unmet obligation comes from a `derive` macro, point at it once to
709 // avoid multiple span labels pointing at the same place.
710 Some(Node::Item(hir::Item {
711 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
714 self_ty.span.ctxt().outer_expn_data().kind,
715 ExpnKind::Macro(MacroKind::Derive, _)
717 of_trait.as_ref().map(|t| t
723 Some(ExpnKind::Macro(MacroKind::Derive, _))
726 let span = self_ty.span.ctxt().outer_expn_data().call_site;
727 let mut spans: MultiSpan = span.into();
728 spans.push_span_label(span, derive_msg);
729 let entry = spanned_predicates.entry(spans);
730 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
733 // Unmet obligation coming from an `impl`.
734 Some(Node::Item(hir::Item {
736 hir::ItemKind::Impl(hir::Impl {
737 of_trait, self_ty, generics, ..
743 unsatisfied_predicates.iter().any(|(pred, _, _)| {
744 match pred.kind().skip_binder() {
745 ty::PredicateKind::Trait(pred) => {
747 == self.tcx.lang_items().sized_trait()
748 && pred.polarity == ty::ImplPolarity::Positive
753 for param in generics.params {
754 if param.span == cause.span && sized_pred {
755 let (sp, sugg) = match param.colon_span {
756 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
757 None => (param.span.shrink_to_hi(), ": ?Sized"),
759 err.span_suggestion_verbose(
761 "consider relaxing the type parameter's implicit \
764 Applicability::MachineApplicable,
768 if let Some(pred) = parent_p {
769 // Done to add the "doesn't satisfy" `span_label`.
770 let _ = format_pred(*pred);
773 let mut spans = if cause.span != *item_span {
774 let mut spans: MultiSpan = cause.span.into();
775 spans.push_span_label(cause.span, unsatisfied_msg);
778 let mut spans = Vec::with_capacity(2);
779 if let Some(trait_ref) = of_trait {
780 spans.push(trait_ref.path.span);
782 spans.push(self_ty.span);
785 if let Some(trait_ref) = of_trait {
786 spans.push_span_label(trait_ref.path.span, "");
788 spans.push_span_label(self_ty.span, "");
790 let entry = spanned_predicates.entry(spans);
791 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
793 Some(_) => unreachable!(),
797 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
798 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
799 for (span, (_path, _self_ty, preds)) in spanned_predicates {
800 let mut preds: Vec<_> = preds
802 .filter_map(|pred| format_pred(*pred))
803 .map(|(p, _)| format!("`{}`", p))
807 let msg = if let [pred] = &preds[..] {
808 format!("trait bound {} was not satisfied", pred)
811 "the following trait bounds were not satisfied:\n{}",
815 err.span_note(span, &msg);
816 unsatisfied_bounds = true;
819 // The requirements that didn't have an `impl` span to show.
820 let mut bound_list = unsatisfied_predicates
822 .filter_map(|(pred, parent_pred, _cause)| {
823 format_pred(*pred).map(|(p, self_ty)| {
824 collect_type_param_suggestions(self_ty, *pred, &p);
827 None => format!("`{}`", &p),
828 Some(parent_pred) => match format_pred(*parent_pred) {
829 None => format!("`{}`", &p),
830 Some((parent_p, _)) => {
831 collect_type_param_suggestions(
837 "`{}`\nwhich is required by `{}`",
847 .filter(|(_, pred)| !skip_list.contains(&pred))
850 .collect::<Vec<(usize, String)>>();
852 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
853 restrict_type_params = true;
854 // #74886: Sort here so that the output is always the same.
855 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
857 err.span_suggestion_verbose(
860 "consider restricting the type parameter{s} to satisfy the \
862 s = pluralize!(obligations.len())
864 format!("{} {}", add_where_or_comma, obligations.join(", ")),
865 Applicability::MaybeIncorrect,
869 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
870 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
871 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
873 if !bound_list.is_empty() || !skip_list.is_empty() {
874 let bound_list = bound_list
876 .map(|(_, path)| path)
879 let actual_prefix = actual.prefix_string(self.tcx);
880 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
881 let (primary_message, label) =
882 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
886 .map(|(_, (trait_ref, obligation))| {
887 if trait_ref.self_ty().references_error()
888 || actual.references_error()
893 let OnUnimplementedNote { message, label, .. } = self
895 .on_unimplemented_note(trait_ref, &obligation);
902 let primary_message = primary_message.unwrap_or_else(|| format!(
903 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
905 err.set_primary_message(&primary_message);
906 if let Some(label) = label {
907 custom_span_label = true;
908 err.span_label(span, label);
910 if !bound_list.is_empty() {
912 "the following trait bounds were not satisfied:\n{bound_list}"
915 self.suggest_derive(&mut err, &unsatisfied_predicates);
917 unsatisfied_bounds = true;
921 let label_span_not_found = |err: &mut Diagnostic| {
922 if unsatisfied_predicates.is_empty() {
923 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
924 let is_string_or_ref_str = match actual.kind() {
925 ty::Ref(_, ty, _) => {
929 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
932 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
935 if is_string_or_ref_str && item_name.name == sym::iter {
936 err.span_suggestion_verbose(
938 "because of the in-memory representation of `&str`, to obtain \
939 an `Iterator` over each of its codepoint use method `chars`",
941 Applicability::MachineApplicable,
944 if let ty::Adt(adt, _) = rcvr_ty.kind() {
945 let mut inherent_impls_candidate = self
947 .inherent_impls(adt.did())
951 if let Some(assoc) = self.associated_value(*def_id, item_name) {
952 // Check for both mode is the same so we avoid suggesting
953 // incorrect associated item.
954 match (mode, assoc.fn_has_self_parameter, source) {
955 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
956 // We check that the suggest type is actually
957 // different from the received one
958 // So we avoid suggestion method with Box<Self>
960 self.tcx.at(span).type_of(*def_id) != actual
961 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
963 (Mode::Path, false, _) => true,
970 .collect::<Vec<_>>();
971 if !inherent_impls_candidate.is_empty() {
972 inherent_impls_candidate.sort();
973 inherent_impls_candidate.dedup();
975 // number of type to shows at most.
976 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
977 let type_candidates = inherent_impls_candidate
981 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
985 let additional_types = if inherent_impls_candidate.len() > limit {
987 "\nand {} more types",
988 inherent_impls_candidate.len() - limit
994 "the {item_kind} was found for\n{}{}",
995 type_candidates, additional_types
1000 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
1004 // If the method name is the name of a field with a function or closure type,
1005 // give a helping note that it has to be called as `(x.f)(...)`.
1006 if let SelfSource::MethodCall(expr) = source {
1007 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
1008 && lev_candidate.is_none()
1009 && !custom_span_label
1011 label_span_not_found(&mut err);
1013 } else if !custom_span_label {
1014 label_span_not_found(&mut err);
1017 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
1018 // can't be called due to `typeof(expr): Clone` not holding.
1019 if unsatisfied_predicates.is_empty() {
1020 self.suggest_calling_method_on_field(&mut err, source, span, actual, item_name);
1023 self.check_for_inner_self(&mut err, source, span, actual, item_name);
1026 bound_spans.dedup();
1027 for (span, msg) in bound_spans.into_iter() {
1028 err.span_label(span, &msg);
1031 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
1033 self.suggest_traits_to_import(
1038 args.map(|(_, args)| args.len() + 1),
1040 out_of_scope_traits,
1041 &unsatisfied_predicates,
1047 // Don't emit a suggestion if we found an actual method
1048 // that had unsatisfied trait bounds
1049 if unsatisfied_predicates.is_empty() && actual.is_enum() {
1050 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
1051 if let Some(suggestion) = lev_distance::find_best_match_for_name(
1052 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1056 err.span_suggestion(
1058 "there is a variant with a similar name",
1060 Applicability::MaybeIncorrect,
1065 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1066 let msg = "remove this method call";
1067 let mut fallback_span = true;
1068 if let SelfSource::MethodCall(expr) = source {
1070 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1071 if let Some(span) = call_expr.span.trim_start(expr.span) {
1072 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1073 fallback_span = false;
1077 err.span_label(span, msg);
1079 } else if let Some(lev_candidate) = lev_candidate {
1080 // Don't emit a suggestion if we found an actual method
1081 // that had unsatisfied trait bounds
1082 if unsatisfied_predicates.is_empty() {
1083 let def_kind = lev_candidate.kind.as_def_kind();
1084 // Methods are defined within the context of a struct and their first parameter is always self,
1085 // which represents the instance of the struct the method is being called on
1086 // Associated functions don’t take self as a parameter and
1087 // they are not methods because they don’t have an instance of the struct to work with.
1088 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1089 err.span_suggestion(
1091 &format!("there is a method with a similar name",),
1093 Applicability::MaybeIncorrect,
1096 err.span_suggestion(
1099 "there is {} {} with a similar name",
1101 def_kind.descr(lev_candidate.def_id),
1104 Applicability::MaybeIncorrect,
1110 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1115 MethodError::Ambiguity(mut sources) => {
1116 let mut err = struct_span_err!(
1120 "multiple applicable items in scope"
1122 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1124 report_candidates(span, &mut err, &mut sources, sugg_span);
1128 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1129 let kind = kind.descr(def_id);
1130 let mut err = struct_span_err!(
1134 "{} `{}` is private",
1138 err.span_label(item_name.span, &format!("private {}", kind));
1142 .span_if_local(def_id)
1143 .unwrap_or_else(|| self.tcx.def_span(def_id));
1144 err.span_label(sp, &format!("private {} defined here", kind));
1145 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1149 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1150 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1151 let mut err = self.sess().struct_span_err(span, &msg);
1152 err.span_label(bound_span, "this has a `Sized` requirement");
1153 if !candidates.is_empty() {
1155 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1156 add a `use` for {one_of_them}:",
1157 an = if candidates.len() == 1 { "an" } else { "" },
1158 s = pluralize!(candidates.len()),
1159 were = pluralize!("was", candidates.len()),
1160 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1162 self.suggest_use_candidates(&mut err, help, candidates);
1164 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1166 let trait_type = self.tcx.mk_ref(
1168 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1170 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1176 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1181 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1182 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1183 fn suggest_calling_field_as_fn(
1187 expr: &hir::Expr<'_>,
1189 err: &mut Diagnostic,
1192 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1193 ty::Adt(def, substs) if !def.is_enum() => {
1194 let variant = &def.non_enum_variant();
1195 tcx.find_field_index(item_name, variant).map(|index| {
1196 let field = &variant.fields[index];
1197 let field_ty = field.ty(tcx, substs);
1203 if let Some((field, field_ty)) = field_receiver {
1204 let scope = tcx.parent_module(self.body_id);
1205 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1208 if self.is_fn_ty(field_ty, span) {
1209 let expr_span = expr.span.to(item_name.span);
1210 err.multipart_suggestion(
1212 "to call the function stored in `{}`, \
1213 surround the field access with parentheses",
1217 (expr_span.shrink_to_lo(), '('.to_string()),
1218 (expr_span.shrink_to_hi(), ')'.to_string()),
1220 Applicability::MachineApplicable,
1223 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1225 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1226 err.span_suggestion(
1228 "remove the arguments",
1230 Applicability::MaybeIncorrect,
1236 let field_kind = if is_accessible { "field" } else { "private field" };
1237 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1243 /// Suggest possible range with adding parentheses, for example:
1244 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1245 fn suggest_wrapping_range_with_parens(
1249 source: SelfSource<'tcx>,
1254 if let SelfSource::MethodCall(expr) = source {
1255 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1256 if let Node::Expr(parent_expr) = parent {
1257 let lang_item = match parent_expr.kind {
1258 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1259 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1260 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1261 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1262 Some(LangItem::RangeToInclusive)
1266 ExprKind::Call(ref func, _) => match func.kind {
1267 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1268 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1269 Some(LangItem::RangeInclusiveStruct)
1276 if lang_item.is_none() {
1280 let span_included = match parent_expr.kind {
1281 hir::ExprKind::Struct(_, eps, _) => {
1282 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1284 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1285 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1293 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1295 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1297 let pick = self.probe_for_name(
1304 ProbeScope::AllTraits,
1307 let range_span = parent_expr.span.with_hi(expr.span.hi());
1308 tcx.sess.emit_err(errors::MissingParentheseInRange {
1310 ty_str: ty_str.to_string(),
1311 method_name: item_name.as_str().to_string(),
1312 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1313 func_name: item_name.name.as_str().to_string(),
1314 left: range_span.shrink_to_lo(),
1315 right: range_span.shrink_to_hi(),
1326 fn suggest_constraining_numerical_ty(
1330 source: SelfSource<'_>,
1336 let found_candidate = all_traits(self.tcx)
1338 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1339 let found_assoc = |ty: Ty<'tcx>| {
1340 simplify_type(tcx, ty, TreatParams::AsInfer)
1342 tcx.incoherent_impls(simp)
1344 .find_map(|&id| self.associated_value(id, item_name))
1348 let found_candidate = found_candidate
1349 || found_assoc(tcx.types.i8)
1350 || found_assoc(tcx.types.i16)
1351 || found_assoc(tcx.types.i32)
1352 || found_assoc(tcx.types.i64)
1353 || found_assoc(tcx.types.i128)
1354 || found_assoc(tcx.types.u8)
1355 || found_assoc(tcx.types.u16)
1356 || found_assoc(tcx.types.u32)
1357 || found_assoc(tcx.types.u64)
1358 || found_assoc(tcx.types.u128)
1359 || found_assoc(tcx.types.f32)
1360 || found_assoc(tcx.types.f32);
1362 && actual.is_numeric()
1363 && !actual.has_concrete_skeleton()
1364 && let SelfSource::MethodCall(expr) = source
1366 let mut err = struct_span_err!(
1370 "can't call {} `{}` on ambiguous numeric type `{}`",
1375 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1377 ExprKind::Lit(ref lit) => {
1382 .span_to_snippet(lit.span)
1383 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1385 // If this is a floating point literal that ends with '.',
1386 // get rid of it to stop this from becoming a member access.
1387 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1388 err.span_suggestion(
1391 "you must specify a concrete type for this numeric value, \
1395 format!("{snippet}_{concrete_type}"),
1396 Applicability::MaybeIncorrect,
1399 ExprKind::Path(QPath::Resolved(_, path)) => {
1401 if let hir::def::Res::Local(hir_id) = path.res {
1402 let span = tcx.hir().span(hir_id);
1403 let filename = tcx.sess.source_map().span_to_filename(span);
1406 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1408 "you must specify a type for this binding, like `{}`",
1412 match (filename, parent_node) {
1415 Node::Local(hir::Local {
1416 source: hir::LocalSource::Normal,
1421 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1422 err.span_suggestion(
1423 // account for `let x: _ = 42;`
1427 format!(": {concrete_type}"),
1428 Applicability::MaybeIncorrect,
1432 err.span_label(span, msg);
1445 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1446 fn suggest_calling_method_on_field(
1448 err: &mut Diagnostic,
1449 source: SelfSource<'tcx>,
1454 if let SelfSource::MethodCall(expr) = source
1455 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1456 && let Some((fields, substs)) =
1457 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1459 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1461 let lang_items = self.tcx.lang_items();
1462 let never_mention_traits = [
1463 lang_items.clone_trait(),
1464 lang_items.deref_trait(),
1465 lang_items.deref_mut_trait(),
1466 self.tcx.get_diagnostic_item(sym::AsRef),
1467 self.tcx.get_diagnostic_item(sym::AsMut),
1468 self.tcx.get_diagnostic_item(sym::Borrow),
1469 self.tcx.get_diagnostic_item(sym::BorrowMut),
1471 let candidate_fields: Vec<_> = fields
1472 .filter_map(|candidate_field| {
1473 self.check_for_nested_field_satisfying(
1481 ProbeScope::TraitsInScope,
1483 .map_or(false, |pick| {
1484 !never_mention_traits
1487 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1499 .map(|id| id.name.to_ident_string())
1500 .collect::<Vec<String>>()
1505 let len = candidate_fields.len();
1507 err.span_suggestions(
1508 item_name.span.shrink_to_lo(),
1510 "{} of the expressions' fields {} a method of the same name",
1511 if len > 1 { "some" } else { "one" },
1512 if len > 1 { "have" } else { "has" },
1514 candidate_fields.iter().map(|path| format!("{path}.")),
1515 Applicability::MaybeIncorrect,
1521 fn check_for_inner_self(
1523 err: &mut Diagnostic,
1524 source: SelfSource<'tcx>,
1530 let SelfSource::MethodCall(expr) = source else { return; };
1531 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1533 let ty::Adt(kind, substs) = actual.kind() else { return; };
1534 match kind.adt_kind() {
1535 ty::AdtKind::Enum => {
1536 let matching_variants: Vec<_> = kind
1539 .flat_map(|variant| {
1540 let [field] = &variant.fields[..] else { return None; };
1541 let field_ty = field.ty(tcx, substs);
1543 // Skip `_`, since that'll just lead to ambiguity.
1544 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1553 ProbeScope::TraitsInScope,
1556 .map(|pick| (variant, field, pick))
1560 let ret_ty_matches = |diagnostic_item| {
1561 if let Some(ret_ty) = self
1564 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1565 && let ty::Adt(kind, _) = ret_ty.kind()
1566 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1574 match &matching_variants[..] {
1575 [(_, field, pick)] => {
1576 let self_ty = field.ty(tcx, substs);
1578 tcx.def_span(pick.item.def_id),
1579 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1581 let (article, kind, variant, question) =
1582 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1583 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1584 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1585 ("an", "Option", "None", ret_ty_matches(sym::Option))
1590 err.span_suggestion_verbose(
1591 expr.span.shrink_to_hi(),
1593 "use the `?` operator to extract the `{self_ty}` value, propagating \
1594 {article} `{kind}::{variant}` value to the caller"
1597 Applicability::MachineApplicable,
1600 err.span_suggestion_verbose(
1601 expr.span.shrink_to_hi(),
1603 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1604 panicking if the value is {article} `{kind}::{variant}`"
1606 ".expect(\"REASON\")",
1607 Applicability::HasPlaceholders,
1611 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1615 // Target wrapper types - types that wrap or pretend to wrap another type,
1616 // perhaps this inner type is meant to be called?
1617 ty::AdtKind::Struct | ty::AdtKind::Union => {
1618 let [first] = ***substs else { return; };
1619 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1620 let Ok(pick) = self.lookup_probe(
1625 ProbeScope::TraitsInScope,
1628 let name = self.ty_to_value_string(actual);
1629 let inner_id = kind.did();
1630 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1631 pick.autoref_or_ptr_adjustment
1638 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1639 err.help("use `with` or `try_with` to access thread local storage");
1640 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1642 "if this `{name}` has been initialized, \
1643 use one of the `assume_init` methods to access the inner value"
1645 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1646 let (suggestion, borrow_kind, panic_if) = match mutable {
1647 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1648 Some(Mutability::Mut) => {
1649 (".borrow_mut()", "mutably borrow", "any borrows exist")
1653 err.span_suggestion_verbose(
1654 expr.span.shrink_to_hi(),
1656 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1657 panicking if {panic_if}"
1660 Applicability::MaybeIncorrect,
1662 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1663 err.span_suggestion_verbose(
1664 expr.span.shrink_to_hi(),
1666 "use `.lock().unwrap()` to borrow the `{ty}`, \
1667 blocking the current thread until it can be acquired"
1670 Applicability::MaybeIncorrect,
1672 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1673 let (suggestion, borrow_kind) = match mutable {
1674 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1675 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1678 err.span_suggestion_verbose(
1679 expr.span.shrink_to_hi(),
1681 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1682 blocking the current thread until it can be acquired"
1685 Applicability::MaybeIncorrect,
1692 tcx.def_span(pick.item.def_id),
1693 &format!("the method `{item_name}` exists on the type `{ty}`"),
1699 pub(crate) fn note_unmet_impls_on_type(
1701 err: &mut Diagnostic,
1702 errors: Vec<FulfillmentError<'tcx>>,
1704 let all_local_types_needing_impls =
1705 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1706 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1707 ty::Adt(def, _) => def.did().is_local(),
1712 let mut preds: Vec<_> = errors
1714 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1715 ty::PredicateKind::Trait(pred) => Some(pred),
1719 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1722 .filter_map(|pred| match pred.self_ty().kind() {
1723 ty::Adt(def, _) => Some(def.did()),
1726 .collect::<FxHashSet<_>>();
1727 let mut spans: MultiSpan = def_ids
1729 .filter_map(|def_id| {
1730 let span = self.tcx.def_span(*def_id);
1731 if span.is_dummy() { None } else { Some(span) }
1733 .collect::<Vec<_>>()
1736 for pred in &preds {
1737 match pred.self_ty().kind() {
1738 ty::Adt(def, _) if def.did().is_local() => {
1739 spans.push_span_label(
1740 self.tcx.def_span(def.did()),
1741 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1748 if all_local_types_needing_impls && spans.primary_span().is_some() {
1749 let msg = if preds.len() == 1 {
1751 "an implementation of `{}` might be missing for `{}`",
1752 preds[0].trait_ref.print_only_trait_path(),
1757 "the following type{} would have to `impl` {} required trait{} for this \
1758 operation to be valid",
1759 pluralize!(def_ids.len()),
1760 if def_ids.len() == 1 { "its" } else { "their" },
1761 pluralize!(preds.len()),
1764 err.span_note(spans, &msg);
1767 let preds: Vec<_> = errors
1769 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1771 self.suggest_derive(err, &preds);
1776 err: &mut Diagnostic,
1777 unsatisfied_predicates: &[(
1778 ty::Predicate<'tcx>,
1779 Option<ty::Predicate<'tcx>>,
1780 Option<ObligationCause<'tcx>>,
1783 let mut derives = Vec::<(String, Span, Symbol)>::new();
1784 let mut traits = Vec::<Span>::new();
1785 for (pred, _, _) in unsatisfied_predicates {
1786 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1787 let adt = match trait_pred.self_ty().ty_adt_def() {
1788 Some(adt) if adt.did().is_local() => adt,
1791 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1792 let can_derive = match diagnostic_name {
1793 sym::Default => !adt.is_enum(),
1801 | sym::Debug => true,
1805 let self_name = trait_pred.self_ty().to_string();
1806 let self_span = self.tcx.def_span(adt.did());
1807 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1808 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1810 if let Some(parent_diagnostic_name) =
1811 self.tcx.get_diagnostic_name(super_trait.def_id())
1816 parent_diagnostic_name,
1821 derives.push((self_name, self_span, diagnostic_name));
1823 traits.push(self.tcx.def_span(trait_pred.def_id()));
1826 traits.push(self.tcx.def_span(trait_pred.def_id()));
1835 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1836 for (self_name, self_span, trait_name) in derives.into_iter() {
1837 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1839 if last_self_name == &self_name {
1840 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1844 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1847 let len = traits.len();
1849 let span: MultiSpan = traits.into();
1852 &format!("the following trait{} must be implemented", pluralize!(len),),
1856 for (self_name, self_span, traits) in &derives_grouped {
1857 err.span_suggestion_verbose(
1858 self_span.shrink_to_lo(),
1859 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1860 format!("#[derive({})]\n", traits),
1861 Applicability::MaybeIncorrect,
1866 fn check_for_deref_method(
1868 err: &mut Diagnostic,
1869 self_source: SelfSource<'tcx>,
1873 let SelfSource::QPath(ty) = self_source else { return; };
1874 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1875 if let Ok(pick) = self.probe_for_name(
1882 ProbeScope::TraitsInScope,
1884 if deref_ty.is_suggestable(self.tcx, true)
1885 // If this method receives `&self`, then the provided
1886 // argument _should_ coerce, so it's valid to suggest
1887 // just changing the path.
1888 && pick.item.fn_has_self_parameter
1889 && let Some(self_ty) =
1890 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1893 let suggested_path = match deref_ty.kind() {
1902 | ty::Param(_) => format!("{deref_ty}"),
1903 // we need to test something like <&[_]>::len
1904 // and Vec::function();
1905 // <&[_]>::len doesn't need an extra "<>" between
1906 // but for Adt type like Vec::function()
1907 // we would suggest <[_]>::function();
1908 _ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
1909 _ => format!("<{deref_ty}>"),
1911 err.span_suggestion_verbose(
1913 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1915 Applicability::MaybeIncorrect,
1920 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1928 /// Print out the type for use in value namespace.
1929 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1931 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
1932 _ => self.ty_to_string(ty),
1936 fn suggest_await_before_method(
1938 err: &mut Diagnostic,
1941 call: &hir::Expr<'_>,
1944 let output_ty = match self.get_impl_future_output_ty(ty) {
1945 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1948 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1949 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1951 err.span_suggestion_verbose(
1952 span.shrink_to_lo(),
1953 "consider `await`ing on the `Future` and calling the method on its `Output`",
1955 Applicability::MaybeIncorrect,
1960 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1961 let parent_map = self.tcx.visible_parent_map(());
1963 // Separate out candidates that must be imported with a glob, because they are named `_`
1964 // and cannot be referred with their identifier.
1965 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1966 if let Some(parent_did) = parent_map.get(trait_did) {
1967 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1968 if *parent_did != self.tcx.parent(*trait_did)
1971 .module_children(*parent_did)
1973 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1974 .all(|child| child.ident.name == kw::Underscore)
1983 let module_did = self.tcx.parent_module(self.body_id);
1984 let (module, _, _) = self.tcx.hir().get_module(module_did);
1985 let span = module.spans.inject_use_span;
1987 let path_strings = candidates.iter().map(|trait_did| {
1988 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1991 let glob_path_strings = globs.iter().map(|trait_did| {
1992 let parent_did = parent_map.get(trait_did).unwrap();
1994 "use {}::*; // trait {}\n",
1995 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1996 self.tcx.item_name(*trait_did),
2000 err.span_suggestions(
2003 path_strings.chain(glob_path_strings),
2004 Applicability::MaybeIncorrect,
2008 fn suggest_valid_traits(
2010 err: &mut Diagnostic,
2011 valid_out_of_scope_traits: Vec<DefId>,
2013 if !valid_out_of_scope_traits.is_empty() {
2014 let mut candidates = valid_out_of_scope_traits;
2018 // `TryFrom` and `FromIterator` have no methods
2019 let edition_fix = candidates
2021 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2024 err.help("items from traits can only be used if the trait is in scope");
2026 "the following {traits_are} implemented but not in scope; \
2027 perhaps add a `use` for {one_of_them}:",
2028 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2029 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2032 self.suggest_use_candidates(err, msg, candidates);
2033 if let Some(did) = edition_fix {
2035 "'{}' is included in the prelude starting in Edition 2021",
2036 with_crate_prefix!(self.tcx.def_path_str(did))
2046 fn suggest_traits_to_import(
2048 err: &mut Diagnostic,
2052 inputs_len: Option<usize>,
2053 source: SelfSource<'tcx>,
2054 valid_out_of_scope_traits: Vec<DefId>,
2055 unsatisfied_predicates: &[(
2056 ty::Predicate<'tcx>,
2057 Option<ty::Predicate<'tcx>>,
2058 Option<ObligationCause<'tcx>>,
2060 static_candidates: &[CandidateSource],
2061 unsatisfied_bounds: bool,
2063 let mut alt_rcvr_sugg = false;
2064 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2066 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2067 span, item_name, rcvr_ty, rcvr
2070 self.tcx.lang_items().clone_trait(),
2071 self.tcx.lang_items().deref_trait(),
2072 self.tcx.lang_items().deref_mut_trait(),
2073 self.tcx.lang_items().drop_trait(),
2074 self.tcx.get_diagnostic_item(sym::AsRef),
2076 // Try alternative arbitrary self types that could fulfill this call.
2077 // FIXME: probe for all types that *could* be arbitrary self-types, not
2079 for (rcvr_ty, post) in &[
2081 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2082 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2084 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2086 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2087 // We point at the method, but we just skip the rest of the check for arbitrary
2088 // self types and rely on the suggestion to `use` the trait from
2089 // `suggest_valid_traits`.
2090 let did = Some(pick.item.container_id(self.tcx));
2091 let skip = skippable.contains(&did);
2092 if pick.autoderefs == 0 && !skip {
2094 pick.item.ident(self.tcx).span,
2095 &format!("the method is available for `{}` here", rcvr_ty),
2100 Err(MethodError::Ambiguity(_)) => {
2101 // If the method is defined (but ambiguous) for the receiver we have, it is also
2102 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2103 // the receiver, then it might disambiguate this method, but I think these
2104 // suggestions are generally misleading (see #94218).
2110 for (rcvr_ty, pre) in &[
2111 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2112 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2113 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2114 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2116 if let Some(new_rcvr_t) = *rcvr_ty
2117 && let Ok(pick) = self.lookup_probe(
2122 ProbeScope::AllTraits,
2125 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2126 let did = Some(pick.item.container_id(self.tcx));
2127 // We don't want to suggest a container type when the missing
2128 // method is `.clone()` or `.deref()` otherwise we'd suggest
2129 // `Arc::new(foo).clone()`, which is far from what the user wants.
2130 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2131 // implement the `AsRef` trait.
2132 let skip = skippable.contains(&did)
2133 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2134 || 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);
2135 // Make sure the method is defined for the *actual* receiver: we don't
2136 // want to treat `Box<Self>` as a receiver if it only works because of
2137 // an autoderef to `&self`
2138 if pick.autoderefs == 0 && !skip {
2140 pick.item.ident(self.tcx).span,
2141 &format!("the method is available for `{}` here", new_rcvr_t),
2143 err.multipart_suggestion(
2144 "consider wrapping the receiver expression with the \
2147 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2148 (rcvr.span.shrink_to_hi(), ")".to_string()),
2150 Applicability::MaybeIncorrect,
2152 // We don't care about the other suggestions.
2153 alt_rcvr_sugg = true;
2159 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2163 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2165 let mut arbitrary_rcvr = vec![];
2166 // There are no traits implemented, so lets suggest some traits to
2167 // implement, by finding ones that have the item name, and are
2168 // legal to implement.
2169 let mut candidates = all_traits(self.tcx)
2171 // Don't issue suggestions for unstable traits since they're
2172 // unlikely to be implementable anyway
2173 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2174 Some(attr) => attr.level.is_stable(),
2178 // Static candidates are already implemented, and known not to work
2179 // Do not suggest them again
2180 static_candidates.iter().all(|sc| match *sc {
2181 CandidateSource::Trait(def_id) => def_id != info.def_id,
2182 CandidateSource::Impl(def_id) => {
2183 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2188 // We approximate the coherence rules to only suggest
2189 // traits that are legal to implement by requiring that
2190 // either the type or trait is local. Multi-dispatch means
2191 // this isn't perfect (that is, there are cases when
2192 // implementing a trait would be legal but is rejected
2194 unsatisfied_predicates.iter().all(|(p, _, _)| {
2195 match p.kind().skip_binder() {
2196 // Hide traits if they are present in predicates as they can be fixed without
2197 // having to implement them.
2198 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2199 ty::PredicateKind::Projection(p) => {
2200 p.projection_ty.item_def_id == info.def_id
2204 }) && (type_is_local || info.def_id.is_local())
2206 .associated_value(info.def_id, item_name)
2208 if let ty::AssocKind::Fn = item.kind {
2212 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2213 if let Some(hir::Node::TraitItem(hir::TraitItem {
2214 kind: hir::TraitItemKind::Fn(fn_sig, method),
2216 })) = id.map(|id| self.tcx.hir().get(id))
2218 let self_first_arg = match method {
2219 hir::TraitFn::Required([ident, ..]) => {
2220 ident.name == kw::SelfLower
2222 hir::TraitFn::Provided(body_id) => {
2223 self.tcx.hir().body(*body_id).params.first().map_or(
2228 hir::PatKind::Binding(_, _, ident, _)
2229 if ident.name == kw::SelfLower
2237 if !fn_sig.decl.implicit_self.has_implicit_self()
2240 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2241 arbitrary_rcvr.push(ty.span);
2247 // We only want to suggest public or local traits (#45781).
2248 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2252 .collect::<Vec<_>>();
2253 for span in &arbitrary_rcvr {
2256 "the method might not be found because of this arbitrary self type",
2263 if !candidates.is_empty() {
2264 // Sort from most relevant to least relevant.
2265 candidates.sort_by(|a, b| a.cmp(b).reverse());
2268 let param_type = match rcvr_ty.kind() {
2269 ty::Param(param) => Some(param),
2270 ty::Ref(_, ty, _) => match ty.kind() {
2271 ty::Param(param) => Some(param),
2276 err.help(if param_type.is_some() {
2277 "items from traits can only be used if the type parameter is bounded by the trait"
2279 "items from traits can only be used if the trait is implemented and in scope"
2281 let candidates_len = candidates.len();
2282 let message = |action| {
2284 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2287 if candidates_len == 1 { "trait defines" } else { "traits define" },
2289 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2293 // Obtain the span for `param` and use it for a structured suggestion.
2294 if let Some(param) = param_type {
2295 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2296 let type_param = generics.type_param(param, self.tcx);
2297 let hir = self.tcx.hir();
2298 if let Some(def_id) = type_param.def_id.as_local() {
2299 let id = hir.local_def_id_to_hir_id(def_id);
2300 // Get the `hir::Param` to verify whether it already has any bounds.
2301 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2302 // instead we suggest `T: Foo + Bar` in that case.
2304 Node::GenericParam(param) => {
2310 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2311 let (sp, mut introducer) = if let Some(span) =
2312 ast_generics.bounds_span_for_suggestions(def_id)
2314 (span, Introducer::Plus)
2315 } else if let Some(colon_span) = param.colon_span {
2316 (colon_span.shrink_to_hi(), Introducer::Nothing)
2318 (param.span.shrink_to_hi(), Introducer::Colon)
2322 hir::GenericParamKind::Type { synthetic: true, .. },
2324 introducer = Introducer::Plus
2326 let trait_def_ids: FxHashSet<DefId> = ast_generics
2327 .bounds_for_param(def_id)
2328 .flat_map(|bp| bp.bounds.iter())
2329 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2331 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2332 err.span_suggestions(
2335 "restrict type parameter `{}` with",
2338 candidates.iter().map(|t| {
2342 Introducer::Plus => " +",
2343 Introducer::Colon => ":",
2344 Introducer::Nothing => "",
2346 self.tcx.def_path_str(t.def_id),
2349 Applicability::MaybeIncorrect,
2354 Node::Item(hir::Item {
2355 kind: hir::ItemKind::Trait(.., bounds, _),
2359 let (sp, sep, article) = if bounds.is_empty() {
2360 (ident.span.shrink_to_hi(), ":", "a")
2362 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2364 err.span_suggestions(
2366 &message(format!("add {} supertrait for", article)),
2367 candidates.iter().map(|t| {
2368 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2370 Applicability::MaybeIncorrect,
2379 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2380 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2381 // cases where a positive bound implies a negative impl.
2382 (candidates, Vec::new())
2383 } else if let Some(simp_rcvr_ty) =
2384 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2386 let mut potential_candidates = Vec::new();
2387 let mut explicitly_negative = Vec::new();
2388 for candidate in candidates {
2389 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2392 .all_impls(candidate.def_id)
2394 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2397 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2399 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2400 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2403 explicitly_negative.push(candidate);
2405 potential_candidates.push(candidate);
2408 (potential_candidates, explicitly_negative)
2410 // We don't know enough about `recv_ty` to make proper suggestions.
2411 (candidates, Vec::new())
2414 let action = if let Some(param) = param_type {
2415 format!("restrict type parameter `{}` with", param)
2417 // FIXME: it might only need to be imported into scope, not implemented.
2418 "implement".to_string()
2420 match &potential_candidates[..] {
2422 [trait_info] if trait_info.def_id.is_local() => {
2424 self.tcx.def_span(trait_info.def_id),
2426 "`{}` defines an item `{}`, perhaps you need to {} it",
2427 self.tcx.def_path_str(trait_info.def_id),
2434 let mut msg = message(action);
2435 for (i, trait_info) in trait_infos.iter().enumerate() {
2436 msg.push_str(&format!(
2437 "\ncandidate #{}: `{}`",
2439 self.tcx.def_path_str(trait_info.def_id),
2445 match &explicitly_negative[..] {
2449 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2450 self.tcx.def_path_str(trait_info.def_id),
2456 let mut msg = format!(
2457 "the following traits define an item `{}`, but are explicitly unimplemented:",
2460 for trait_info in trait_infos {
2461 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2469 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2470 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2471 pub(crate) fn suggest_else_fn_with_closure(
2473 err: &mut Diagnostic,
2474 expr: &hir::Expr<'_>,
2478 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2479 else { return false; };
2481 if !self.can_coerce(output, expected) {
2485 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2486 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2487 let hir::ExprKind::MethodCall(
2488 hir::PathSegment { ident: method_name, .. },
2492 ) = call_expr.kind &&
2493 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2494 let new_name = Ident {
2495 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2496 span: method_name.span,
2498 let probe = self.lookup_probe(
2503 ProbeScope::TraitsInScope,
2506 // check the method arguments number
2507 if let Ok(pick) = probe &&
2508 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2509 let fn_args = fn_sig.skip_binder().inputs() &&
2510 fn_args.len() == args.len() + 1 {
2511 err.span_suggestion_verbose(
2512 method_name.span.shrink_to_hi(),
2513 &format!("try calling `{}` instead", new_name.name.as_str()),
2515 Applicability::MaybeIncorrect,
2523 /// Checks whether there is a local type somewhere in the chain of
2524 /// autoderefs of `rcvr_ty`.
2525 fn type_derefs_to_local(
2529 source: SelfSource<'tcx>,
2531 fn is_local(ty: Ty<'_>) -> bool {
2533 ty::Adt(def, _) => def.did().is_local(),
2534 ty::Foreign(did) => did.is_local(),
2535 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2536 ty::Param(_) => true,
2538 // Everything else (primitive types, etc.) is effectively
2539 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2540 // the noise from these sort of types is usually just really
2541 // annoying, rather than any sort of help).
2546 // This occurs for UFCS desugaring of `T::method`, where there is no
2547 // receiver expression for the method call, and thus no autoderef.
2548 if let SelfSource::QPath(_) = source {
2549 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2552 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2556 #[derive(Copy, Clone, Debug)]
2557 pub enum SelfSource<'a> {
2558 QPath(&'a hir::Ty<'a>),
2559 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2562 #[derive(Copy, Clone)]
2563 pub struct TraitInfo {
2567 impl PartialEq for TraitInfo {
2568 fn eq(&self, other: &TraitInfo) -> bool {
2569 self.cmp(other) == Ordering::Equal
2572 impl Eq for TraitInfo {}
2573 impl PartialOrd for TraitInfo {
2574 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2575 Some(self.cmp(other))
2578 impl Ord for TraitInfo {
2579 fn cmp(&self, other: &TraitInfo) -> Ordering {
2580 // Local crates are more important than remote ones (local:
2581 // `cnum == 0`), and otherwise we throw in the defid for totality.
2583 let lhs = (other.def_id.krate, other.def_id);
2584 let rhs = (self.def_id.krate, self.def_id);
2589 /// Retrieves all traits in this crate and any dependent crates,
2590 /// and wraps them into `TraitInfo` for custom sorting.
2591 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2592 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2595 fn print_disambiguation_help<'tcx>(
2597 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2598 err: &mut Diagnostic,
2601 kind: ty::AssocKind,
2604 candidate: Option<usize>,
2605 source_map: &source_map::SourceMap,
2606 fn_has_self_parameter: bool,
2608 let mut applicability = Applicability::MachineApplicable;
2609 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2612 if rcvr_ty.is_region_ptr() {
2613 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2617 std::iter::once(receiver)
2619 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2620 applicability = Applicability::HasPlaceholders;
2623 .collect::<Vec<_>>()
2626 let trait_name = if !fn_has_self_parameter {
2627 format!("<{} as {}>", rcvr_ty, trait_name)
2631 (span, format!("{}::{}{}", trait_name, item_name, args))
2633 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2635 err.span_suggestion_verbose(
2638 "disambiguate the {} for {}",
2639 kind.as_def_kind().descr(def_id),
2640 if let Some(candidate) = candidate {
2641 format!("candidate #{}", candidate)
2643 "the candidate".to_string()