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};
8 use rustc_errors::StashKey;
10 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
14 use rustc_hir::def::DefKind;
15 use rustc_hir::def_id::DefId;
16 use rustc_hir::lang_items::LangItem;
17 use rustc_hir::PatKind::Binding;
18 use rustc_hir::PathSegment;
19 use rustc_hir::{ExprKind, Node, QPath};
20 use rustc_infer::infer::{
21 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
24 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
25 use rustc_middle::traits::util::supertraits;
26 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
27 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
28 use rustc_middle::ty::print::with_crate_prefix;
29 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
30 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
31 use rustc_span::symbol::{kw, sym, Ident};
32 use rustc_span::Symbol;
33 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
34 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
35 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
36 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
37 use rustc_trait_selection::traits::{
38 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
41 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
42 use super::{CandidateSource, MethodError, NoMatchData};
43 use rustc_hir::intravisit::Visitor;
44 use std::cmp::Ordering;
47 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
51 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
52 // so we look for these beforehand.
53 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
54 // If it's not a simple function, look for things which implement `FnOnce`.
56 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
60 // This conditional prevents us from asking to call errors and unresolved types.
61 // It might seem that we can use `predicate_must_hold_modulo_regions`,
62 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
63 // type resolution always gives a "maybe" here.
64 if self.autoderef(span, ty).any(|(ty, _)| {
65 info!("check deref {:?} error", ty);
66 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
71 self.autoderef(span, ty).any(|(ty, _)| {
72 info!("check deref {:?} impl FnOnce", ty);
74 let trait_ref = tcx.mk_trait_ref(
78 self.next_ty_var(TypeVariableOrigin {
79 kind: TypeVariableOriginKind::MiscVariable,
84 let poly_trait_ref = ty::Binder::dummy(trait_ref);
85 let obligation = Obligation::misc(
90 poly_trait_ref.without_const(),
92 self.predicate_may_hold(&obligation)
99 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
100 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
103 pub fn report_method_error(
108 source: SelfSource<'tcx>,
109 error: MethodError<'tcx>,
110 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
111 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
112 // Avoid suggestions when we don't know what's going on.
113 if rcvr_ty.references_error() {
117 let report_candidates = |span: Span,
118 err: &mut Diagnostic,
119 sources: &mut Vec<CandidateSource>,
120 sugg_span: Option<Span>| {
123 // Dynamic limit to avoid hiding just one candidate, which is silly.
124 let limit = if sources.len() == 5 { 5 } else { 4 };
126 for (idx, source) in sources.iter().take(limit).enumerate() {
128 CandidateSource::Impl(impl_did) => {
129 // Provide the best span we can. Use the item, if local to crate, else
130 // the impl, if local to crate (item may be defaulted), else nothing.
131 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
132 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
133 self.associated_value(impl_trait_ref.def_id, item_name)
138 let note_span = if item.def_id.is_local() {
139 Some(self.tcx.def_span(item.def_id))
140 } else if impl_did.is_local() {
141 Some(self.tcx.def_span(impl_did))
146 let impl_ty = self.tcx.at(span).type_of(impl_did);
148 let insertion = match self.tcx.impl_trait_ref(impl_did) {
149 None => String::new(),
150 Some(trait_ref) => format!(
151 " of the trait `{}`",
152 self.tcx.def_path_str(trait_ref.def_id)
156 let (note_str, idx) = if sources.len() > 1 {
159 "candidate #{} is defined in an impl{} for the type `{}`",
169 "the candidate is defined in an impl{} for the type `{}`",
175 if let Some(note_span) = note_span {
176 // We have a span pointing to the method. Show note with snippet.
177 err.span_note(note_span, ¬e_str);
181 if let Some(sugg_span) = sugg_span
182 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
183 let path = self.tcx.def_path_str(trait_ref.def_id);
185 let ty = match item.kind {
186 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
187 ty::AssocKind::Fn => self
193 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
197 print_disambiguation_help(
207 self.tcx.sess.source_map(),
208 item.fn_has_self_parameter,
212 CandidateSource::Trait(trait_did) => {
213 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
214 let item_span = self.tcx.def_span(item.def_id);
215 let idx = if sources.len() > 1 {
217 "candidate #{} is defined in the trait `{}`",
219 self.tcx.def_path_str(trait_did)
221 err.span_note(item_span, msg);
225 "the candidate is defined in the trait `{}`",
226 self.tcx.def_path_str(trait_did)
228 err.span_note(item_span, msg);
231 if let Some(sugg_span) = sugg_span {
232 let path = self.tcx.def_path_str(trait_did);
233 print_disambiguation_help(
243 self.tcx.sess.source_map(),
244 item.fn_has_self_parameter,
250 if sources.len() > limit {
251 err.note(&format!("and {} others", sources.len() - limit));
255 let sugg_span = if let SelfSource::MethodCall(expr) = source {
256 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
257 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
263 MethodError::NoMatch(NoMatchData {
264 mut static_candidates,
265 unsatisfied_predicates,
272 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
273 let ty_str = self.ty_to_string(rcvr_ty);
274 let is_method = mode == Mode::MethodCall;
275 let item_kind = if is_method {
277 } else if rcvr_ty.is_enum() {
278 "variant or associated item"
280 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
281 (Some(name), false) if name.is_lowercase() => "function or associated item",
282 (Some(_), false) => "associated item",
283 (Some(_), true) | (None, false) => "variant or associated item",
284 (None, true) => "variant",
288 if self.suggest_wrapping_range_with_parens(
289 tcx, rcvr_ty, source, span, item_name, &ty_str,
290 ) || self.suggest_constraining_numerical_ty(
291 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
295 span = item_name.span;
297 // Don't show generic arguments when the method can't be found in any implementation (#81576).
298 let mut ty_str_reported = ty_str.clone();
299 if let ty::Adt(_, generics) = rcvr_ty.kind() {
300 if generics.len() > 0 {
301 let mut autoderef = self.autoderef(span, rcvr_ty);
302 let candidate_found = autoderef.any(|(ty, _)| {
303 if let ty::Adt(adt_def, _) = ty.kind() {
305 .inherent_impls(adt_def.did())
307 .filter_map(|def_id| self.associated_value(*def_id, item_name))
314 let has_deref = autoderef.step_count() > 0;
315 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
316 if let Some((path_string, _)) = ty_str.split_once('<') {
317 ty_str_reported = path_string.to_string();
323 let mut err = struct_span_err!(
327 "no {} named `{}` found for {} `{}` in the current scope",
330 rcvr_ty.prefix_string(self.tcx),
333 if rcvr_ty.references_error() {
334 err.downgrade_to_delayed_bug();
337 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
338 self.suggest_await_before_method(
339 &mut err, item_name, rcvr_ty, cal, span,
342 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
345 "you are looking for the module in `std`, not the primitive type",
347 Applicability::MachineApplicable,
350 if let ty::RawPtr(_) = &rcvr_ty.kind() {
352 "try using `<*const T>::as_ref()` to get a reference to the \
353 type behind the pointer: https://doc.rust-lang.org/std/\
354 primitive.pointer.html#method.as_ref",
357 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
358 to invalid or uninitialized memory is undefined behavior",
362 let ty_span = match rcvr_ty.kind() {
363 ty::Param(param_type) => Some(
364 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
366 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
369 if let Some(span) = ty_span {
373 "{item_kind} `{item_name}` not found for this {}",
374 rcvr_ty.prefix_string(self.tcx)
379 if let SelfSource::MethodCall(rcvr_expr) = source {
380 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
384 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
385 let probe = self.lookup_probe(
389 ProbeScope::AllTraits,
395 let mut custom_span_label = false;
397 if !static_candidates.is_empty() {
399 "found the following associated functions; to be used as methods, \
400 functions must have a `self` parameter",
402 err.span_label(span, "this is an associated function, not a method");
403 custom_span_label = true;
405 if static_candidates.len() == 1 {
406 self.suggest_associated_call_syntax(
416 report_candidates(span, &mut err, &mut static_candidates, None);
417 } else if static_candidates.len() > 1 {
418 report_candidates(span, &mut err, &mut static_candidates, Some(sugg_span));
421 let mut bound_spans = vec![];
422 let mut restrict_type_params = false;
423 let mut unsatisfied_bounds = false;
424 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
425 let msg = "consider using `len` instead";
426 if let SelfSource::MethodCall(_expr) = source {
427 err.span_suggestion_short(
431 Applicability::MachineApplicable,
434 err.span_label(span, msg);
436 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
437 let iterator_trait = self.tcx.def_path_str(iterator_trait);
438 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
440 } else if !unsatisfied_predicates.is_empty() {
441 let mut type_params = FxHashMap::default();
443 // Pick out the list of unimplemented traits on the receiver.
444 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
445 let mut unimplemented_traits = FxHashMap::default();
446 let mut unimplemented_traits_only = true;
447 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
448 if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
449 (predicate.kind().skip_binder(), cause.as_ref())
451 if p.trait_ref.self_ty() != rcvr_ty {
452 // This is necessary, not just to keep the errors clean, but also
453 // because our derived obligations can wind up with a trait ref that
454 // requires a different param_env to be correctly compared.
457 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
458 predicate.kind().rebind(p.trait_ref),
460 cause: cause.clone(),
461 param_env: self.param_env,
462 predicate: *predicate,
469 // Make sure that, if any traits other than the found ones were involved,
470 // we don't don't report an unimplemented trait.
471 // We don't want to say that `iter::Cloned` is not an iterator, just
472 // because of some non-Clone item being iterated over.
473 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
474 match predicate.kind().skip_binder() {
475 ty::PredicateKind::Clause(ty::Clause::Trait(p))
476 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
478 unimplemented_traits_only = false;
484 let mut collect_type_param_suggestions =
485 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
486 // We don't care about regions here, so it's fine to skip the binder here.
487 if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
488 (self_ty.kind(), parent_pred.kind().skip_binder())
490 let hir = self.tcx.hir();
491 let node = match p.trait_ref.self_ty().kind() {
493 // Account for `fn` items like in `issue-35677.rs` to
494 // suggest restricting its type params.
496 hir.body_owner(hir::BodyId { hir_id: self.body_id });
497 Some(hir.get(parent_body))
500 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
504 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
505 if let Some(g) = kind.generics() {
507 g.tail_span_for_predicate_suggestion(),
508 g.add_where_or_trailing_comma(),
512 .or_insert_with(FxHashSet::default)
513 .insert(obligation.to_owned());
518 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
520 "doesn't satisfy `{}`",
521 if obligation.len() > 50 { quiet } else { obligation }
523 match &self_ty.kind() {
524 // Point at the type that couldn't satisfy the bound.
526 bound_spans.push((self.tcx.def_span(def.did()), msg))
528 // Point at the trait object that couldn't satisfy the bound.
529 ty::Dynamic(preds, _, _) => {
530 for pred in preds.iter() {
531 match pred.skip_binder() {
532 ty::ExistentialPredicate::Trait(tr) => bound_spans
533 .push((self.tcx.def_span(tr.def_id), msg.clone())),
534 ty::ExistentialPredicate::Projection(_)
535 | ty::ExistentialPredicate::AutoTrait(_) => {}
539 // Point at the closure that couldn't satisfy the bound.
540 ty::Closure(def_id, _) => bound_spans.push((
541 tcx.def_span(*def_id),
542 format!("doesn't satisfy `{}`", quiet),
547 let mut format_pred = |pred: ty::Predicate<'tcx>| {
548 let bound_predicate = pred.kind();
549 match bound_predicate.skip_binder() {
550 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
551 let pred = bound_predicate.rebind(pred);
552 // `<Foo as Iterator>::Item = String`.
553 let projection_ty = pred.skip_binder().projection_ty;
555 let substs_with_infer_self = tcx.mk_substs(
556 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
557 .chain(projection_ty.substs.iter().skip(1)),
560 let quiet_projection_ty = ty::AliasTy {
561 substs: substs_with_infer_self,
562 def_id: projection_ty.def_id,
565 let term = pred.skip_binder().term;
567 let obligation = format!("{} = {}", projection_ty, term);
568 let quiet = format!("{} = {}", quiet_projection_ty, term);
570 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
571 Some((obligation, projection_ty.self_ty()))
573 ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
574 let p = poly_trait_ref.trait_ref;
575 let self_ty = p.self_ty();
576 let path = p.print_only_trait_path();
577 let obligation = format!("{}: {}", self_ty, path);
578 let quiet = format!("_: {}", path);
579 bound_span_label(self_ty, &obligation, &quiet);
580 Some((obligation, self_ty))
586 // Find all the requirements that come from a local `impl` block.
587 let mut skip_list: FxHashSet<_> = Default::default();
588 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
589 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
591 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
592 .filter_map(|(p, parent, c)| match c.code() {
593 ObligationCauseCode::ImplDerivedObligation(data) => {
594 Some((&data.derived, p, parent, data.impl_def_id, data))
599 let parent_trait_ref = data.parent_trait_pred;
600 let path = parent_trait_ref.print_modifiers_and_trait_path();
601 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
602 let unsatisfied_msg = "unsatisfied trait bound introduced here";
604 "unsatisfied trait bound introduced in this `derive` macro";
605 match self.tcx.hir().get_if_local(impl_def_id) {
606 // Unmet obligation comes from a `derive` macro, point at it once to
607 // avoid multiple span labels pointing at the same place.
608 Some(Node::Item(hir::Item {
609 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
612 self_ty.span.ctxt().outer_expn_data().kind,
613 ExpnKind::Macro(MacroKind::Derive, _)
615 of_trait.as_ref().map(|t| t
621 Some(ExpnKind::Macro(MacroKind::Derive, _))
624 let span = self_ty.span.ctxt().outer_expn_data().call_site;
625 let mut spans: MultiSpan = span.into();
626 spans.push_span_label(span, derive_msg);
627 let entry = spanned_predicates.entry(spans);
628 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
631 // Unmet obligation coming from an `impl`.
632 Some(Node::Item(hir::Item {
634 hir::ItemKind::Impl(hir::Impl {
635 of_trait, self_ty, generics, ..
641 unsatisfied_predicates.iter().any(|(pred, _, _)| {
642 match pred.kind().skip_binder() {
643 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
645 == self.tcx.lang_items().sized_trait()
646 && pred.polarity == ty::ImplPolarity::Positive
651 for param in generics.params {
652 if param.span == cause.span && sized_pred {
653 let (sp, sugg) = match param.colon_span {
654 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
655 None => (param.span.shrink_to_hi(), ": ?Sized"),
657 err.span_suggestion_verbose(
659 "consider relaxing the type parameter's implicit \
662 Applicability::MachineApplicable,
666 if let Some(pred) = parent_p {
667 // Done to add the "doesn't satisfy" `span_label`.
668 let _ = format_pred(*pred);
671 let mut spans = if cause.span != *item_span {
672 let mut spans: MultiSpan = cause.span.into();
673 spans.push_span_label(cause.span, unsatisfied_msg);
676 let mut spans = Vec::with_capacity(2);
677 if let Some(trait_ref) = of_trait {
678 spans.push(trait_ref.path.span);
680 spans.push(self_ty.span);
683 if let Some(trait_ref) = of_trait {
684 spans.push_span_label(trait_ref.path.span, "");
686 spans.push_span_label(self_ty.span, "");
688 let entry = spanned_predicates.entry(spans);
689 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
691 Some(_) => unreachable!(),
695 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
696 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
697 for (span, (_path, _self_ty, preds)) in spanned_predicates {
698 let mut preds: Vec<_> = preds
700 .filter_map(|pred| format_pred(*pred))
701 .map(|(p, _)| format!("`{}`", p))
705 let msg = if let [pred] = &preds[..] {
706 format!("trait bound {} was not satisfied", pred)
709 "the following trait bounds were not satisfied:\n{}",
713 err.span_note(span, &msg);
714 unsatisfied_bounds = true;
717 // The requirements that didn't have an `impl` span to show.
718 let mut bound_list = unsatisfied_predicates
720 .filter_map(|(pred, parent_pred, _cause)| {
721 format_pred(*pred).map(|(p, self_ty)| {
722 collect_type_param_suggestions(self_ty, *pred, &p);
725 None => format!("`{}`", &p),
726 Some(parent_pred) => match format_pred(*parent_pred) {
727 None => format!("`{}`", &p),
728 Some((parent_p, _)) => {
729 collect_type_param_suggestions(
735 "`{}`\nwhich is required by `{}`",
745 .filter(|(_, pred)| !skip_list.contains(&pred))
748 .collect::<Vec<(usize, String)>>();
750 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
751 restrict_type_params = true;
752 // #74886: Sort here so that the output is always the same.
753 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
755 err.span_suggestion_verbose(
758 "consider restricting the type parameter{s} to satisfy the \
760 s = pluralize!(obligations.len())
762 format!("{} {}", add_where_or_comma, obligations.join(", ")),
763 Applicability::MaybeIncorrect,
767 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
768 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
769 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
771 if !bound_list.is_empty() || !skip_list.is_empty() {
772 let bound_list = bound_list
774 .map(|(_, path)| path)
777 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
778 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
779 let (primary_message, label) =
780 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
784 .map(|(_, (trait_ref, obligation))| {
785 if trait_ref.self_ty().references_error()
786 || rcvr_ty.references_error()
791 let OnUnimplementedNote { message, label, .. } = self
793 .on_unimplemented_note(trait_ref, &obligation);
800 let primary_message = primary_message.unwrap_or_else(|| format!(
801 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
803 err.set_primary_message(&primary_message);
804 if let Some(label) = label {
805 custom_span_label = true;
806 err.span_label(span, label);
808 if !bound_list.is_empty() {
810 "the following trait bounds were not satisfied:\n{bound_list}"
813 self.suggest_derive(&mut err, &unsatisfied_predicates);
815 unsatisfied_bounds = true;
819 let label_span_not_found = |err: &mut Diagnostic| {
820 if unsatisfied_predicates.is_empty() {
821 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
822 let is_string_or_ref_str = match rcvr_ty.kind() {
823 ty::Ref(_, ty, _) => {
827 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
830 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
833 if is_string_or_ref_str && item_name.name == sym::iter {
834 err.span_suggestion_verbose(
836 "because of the in-memory representation of `&str`, to obtain \
837 an `Iterator` over each of its codepoint use method `chars`",
839 Applicability::MachineApplicable,
842 if let ty::Adt(adt, _) = rcvr_ty.kind() {
843 let mut inherent_impls_candidate = self
845 .inherent_impls(adt.did())
849 if let Some(assoc) = self.associated_value(*def_id, item_name) {
850 // Check for both mode is the same so we avoid suggesting
851 // incorrect associated item.
852 match (mode, assoc.fn_has_self_parameter, source) {
853 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
854 // We check that the suggest type is actually
855 // different from the received one
856 // So we avoid suggestion method with Box<Self>
858 self.tcx.at(span).type_of(*def_id) != rcvr_ty
859 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
861 (Mode::Path, false, _) => true,
868 .collect::<Vec<_>>();
869 if !inherent_impls_candidate.is_empty() {
870 inherent_impls_candidate.sort();
871 inherent_impls_candidate.dedup();
873 // number of type to shows at most.
874 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
875 let type_candidates = inherent_impls_candidate
879 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
883 let additional_types = if inherent_impls_candidate.len() > limit {
885 "\nand {} more types",
886 inherent_impls_candidate.len() - limit
892 "the {item_kind} was found for\n{}{}",
893 type_candidates, additional_types
898 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
902 // If the method name is the name of a field with a function or closure type,
903 // give a helping note that it has to be called as `(x.f)(...)`.
904 if let SelfSource::MethodCall(expr) = source {
905 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
906 && lev_candidate.is_none()
907 && !custom_span_label
909 label_span_not_found(&mut err);
911 } else if !custom_span_label {
912 label_span_not_found(&mut err);
915 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
916 // can't be called due to `typeof(expr): Clone` not holding.
917 if unsatisfied_predicates.is_empty() {
918 self.suggest_calling_method_on_field(
919 &mut err, source, span, rcvr_ty, item_name,
923 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
927 for (span, msg) in bound_spans.into_iter() {
928 err.span_label(span, &msg);
931 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
933 self.suggest_traits_to_import(
938 args.map(|(_, args)| args.len() + 1),
941 &unsatisfied_predicates,
947 // Don't emit a suggestion if we found an actual method
948 // that had unsatisfied trait bounds
949 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
950 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
951 if let Some(suggestion) = lev_distance::find_best_match_for_name(
952 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
958 "there is a variant with a similar name",
960 Applicability::MaybeIncorrect,
965 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
966 let msg = "remove this method call";
967 let mut fallback_span = true;
968 if let SelfSource::MethodCall(expr) = source {
970 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
971 if let Some(span) = call_expr.span.trim_start(expr.span) {
972 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
973 fallback_span = false;
977 err.span_label(span, msg);
979 } else if let Some(lev_candidate) = lev_candidate {
980 // Don't emit a suggestion if we found an actual method
981 // that had unsatisfied trait bounds
982 if unsatisfied_predicates.is_empty() {
983 let def_kind = lev_candidate.kind.as_def_kind();
984 // Methods are defined within the context of a struct and their first parameter is always self,
985 // which represents the instance of the struct the method is being called on
986 // Associated functions don’t take self as a parameter and
987 // they are not methods because they don’t have an instance of the struct to work with.
988 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
991 &format!("there is a method with a similar name",),
993 Applicability::MaybeIncorrect,
999 "there is {} {} with a similar name",
1001 def_kind.descr(lev_candidate.def_id),
1004 Applicability::MaybeIncorrect,
1010 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1015 MethodError::Ambiguity(mut sources) => {
1016 let mut err = struct_span_err!(
1020 "multiple applicable items in scope"
1022 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1024 report_candidates(span, &mut err, &mut sources, Some(sugg_span));
1028 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1029 let kind = kind.descr(def_id);
1030 let mut err = struct_span_err!(
1034 "{} `{}` is private",
1038 err.span_label(item_name.span, &format!("private {}", kind));
1042 .span_if_local(def_id)
1043 .unwrap_or_else(|| self.tcx.def_span(def_id));
1044 err.span_label(sp, &format!("private {} defined here", kind));
1045 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1049 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1050 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1051 let mut err = self.sess().struct_span_err(span, &msg);
1052 err.span_label(bound_span, "this has a `Sized` requirement");
1053 if !candidates.is_empty() {
1055 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1056 add a `use` for {one_of_them}:",
1057 an = if candidates.len() == 1 { "an" } else { "" },
1058 s = pluralize!(candidates.len()),
1059 were = pluralize!("was", candidates.len()),
1060 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1062 self.suggest_use_candidates(&mut err, help, candidates);
1064 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1066 let trait_type = self.tcx.mk_ref(
1068 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1070 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1076 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1081 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1082 /// doesn't take a `self` receiver.
1083 fn suggest_associated_call_syntax(
1085 err: &mut Diagnostic,
1086 static_candidates: &Vec<CandidateSource>,
1088 source: SelfSource<'tcx>,
1090 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1093 let mut has_unsuggestable_args = false;
1094 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1095 // When the "method" is resolved through dereferencing, we really want the
1096 // original type that has the associated function for accurate suggestions.
1098 let impl_ty = self.tcx.type_of(*impl_did);
1099 let target_ty = self
1100 .autoderef(sugg_span, rcvr_ty)
1101 .find(|(rcvr_ty, _)| {
1102 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1103 .types_may_unify(*rcvr_ty, impl_ty)
1105 .map_or(impl_ty, |(ty, _)| ty)
1107 if let ty::Adt(def, substs) = target_ty.kind() {
1108 // If there are any inferred arguments, (`{integer}`), we should replace
1109 // them with underscores to allow the compiler to infer them
1110 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1111 if !arg.is_suggestable(self.tcx, true) {
1112 has_unsuggestable_args = true;
1113 match arg.unpack() {
1114 GenericArgKind::Lifetime(_) => self
1115 .next_region_var(RegionVariableOrigin::MiscVariable(
1116 rustc_span::DUMMY_SP,
1119 GenericArgKind::Type(_) => self
1120 .next_ty_var(TypeVariableOrigin {
1121 span: rustc_span::DUMMY_SP,
1122 kind: TypeVariableOriginKind::MiscVariable,
1125 GenericArgKind::Const(arg) => self
1128 ConstVariableOrigin {
1129 span: rustc_span::DUMMY_SP,
1130 kind: ConstVariableOriginKind::MiscVariable,
1140 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1142 self.ty_to_value_string(target_ty)
1145 self.ty_to_value_string(rcvr_ty.peel_refs())
1147 if let SelfSource::MethodCall(_) = source {
1148 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1149 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1150 && assoc.kind == ty::AssocKind::Fn
1152 let sig = self.tcx.fn_sig(assoc.def_id);
1153 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1156 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1161 let mut applicability = Applicability::MachineApplicable;
1162 let args = if let Some((receiver, args)) = args {
1163 // The first arg is the same kind as the receiver
1164 let explicit_args = if first_arg.is_some() {
1165 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1167 // There is no `Self` kind to infer the arguments from
1168 if has_unsuggestable_args {
1169 applicability = Applicability::HasPlaceholders;
1171 args.iter().collect()
1175 first_arg.unwrap_or(""),
1182 .span_to_snippet(arg.span)
1183 .unwrap_or_else(|_| {
1184 applicability = Applicability::HasPlaceholders;
1187 .collect::<Vec<_>>()
1191 applicability = Applicability::HasPlaceholders;
1194 err.span_suggestion(
1196 "use associated function syntax instead",
1197 format!("{}::{}{}", ty_str, item_name, args),
1201 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1205 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1206 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1207 fn suggest_calling_field_as_fn(
1211 expr: &hir::Expr<'_>,
1213 err: &mut Diagnostic,
1216 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1217 ty::Adt(def, substs) if !def.is_enum() => {
1218 let variant = &def.non_enum_variant();
1219 tcx.find_field_index(item_name, variant).map(|index| {
1220 let field = &variant.fields[index];
1221 let field_ty = field.ty(tcx, substs);
1227 if let Some((field, field_ty)) = field_receiver {
1228 let scope = tcx.parent_module(self.body_id);
1229 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1232 if self.is_fn_ty(field_ty, span) {
1233 let expr_span = expr.span.to(item_name.span);
1234 err.multipart_suggestion(
1236 "to call the function stored in `{}`, \
1237 surround the field access with parentheses",
1241 (expr_span.shrink_to_lo(), '('.to_string()),
1242 (expr_span.shrink_to_hi(), ')'.to_string()),
1244 Applicability::MachineApplicable,
1247 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1249 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1250 err.span_suggestion(
1252 "remove the arguments",
1254 Applicability::MaybeIncorrect,
1260 let field_kind = if is_accessible { "field" } else { "private field" };
1261 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1267 /// Suggest possible range with adding parentheses, for example:
1268 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1269 fn suggest_wrapping_range_with_parens(
1273 source: SelfSource<'tcx>,
1278 if let SelfSource::MethodCall(expr) = source {
1279 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1280 if let Node::Expr(parent_expr) = parent {
1281 let lang_item = match parent_expr.kind {
1282 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1283 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1284 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1285 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1286 Some(LangItem::RangeToInclusive)
1290 ExprKind::Call(ref func, _) => match func.kind {
1291 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1292 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1293 Some(LangItem::RangeInclusiveStruct)
1300 if lang_item.is_none() {
1304 let span_included = match parent_expr.kind {
1305 hir::ExprKind::Struct(_, eps, _) => {
1306 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1308 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1309 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1317 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1319 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1321 let pick = self.probe_for_name(
1327 ProbeScope::AllTraits,
1330 let range_span = parent_expr.span.with_hi(expr.span.hi());
1331 tcx.sess.emit_err(errors::MissingParentheseInRange {
1333 ty_str: ty_str.to_string(),
1334 method_name: item_name.as_str().to_string(),
1335 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1336 func_name: item_name.name.as_str().to_string(),
1337 left: range_span.shrink_to_lo(),
1338 right: range_span.shrink_to_hi(),
1349 fn suggest_constraining_numerical_ty(
1353 source: SelfSource<'_>,
1359 let found_candidate = all_traits(self.tcx)
1361 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1362 let found_assoc = |ty: Ty<'tcx>| {
1363 simplify_type(tcx, ty, TreatParams::AsInfer)
1365 tcx.incoherent_impls(simp)
1367 .find_map(|&id| self.associated_value(id, item_name))
1371 let found_candidate = found_candidate
1372 || found_assoc(tcx.types.i8)
1373 || found_assoc(tcx.types.i16)
1374 || found_assoc(tcx.types.i32)
1375 || found_assoc(tcx.types.i64)
1376 || found_assoc(tcx.types.i128)
1377 || found_assoc(tcx.types.u8)
1378 || found_assoc(tcx.types.u16)
1379 || found_assoc(tcx.types.u32)
1380 || found_assoc(tcx.types.u64)
1381 || found_assoc(tcx.types.u128)
1382 || found_assoc(tcx.types.f32)
1383 || found_assoc(tcx.types.f32);
1385 && actual.is_numeric()
1386 && !actual.has_concrete_skeleton()
1387 && let SelfSource::MethodCall(expr) = source
1389 let mut err = struct_span_err!(
1393 "can't call {} `{}` on ambiguous numeric type `{}`",
1398 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1400 ExprKind::Lit(ref lit) => {
1405 .span_to_snippet(lit.span)
1406 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1408 // If this is a floating point literal that ends with '.',
1409 // get rid of it to stop this from becoming a member access.
1410 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1411 err.span_suggestion(
1414 "you must specify a concrete type for this numeric value, \
1418 format!("{snippet}_{concrete_type}"),
1419 Applicability::MaybeIncorrect,
1422 ExprKind::Path(QPath::Resolved(_, path)) => {
1424 if let hir::def::Res::Local(hir_id) = path.res {
1425 let span = tcx.hir().span(hir_id);
1426 let filename = tcx.sess.source_map().span_to_filename(span);
1429 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1431 "you must specify a type for this binding, like `{}`",
1435 match (filename, parent_node) {
1438 Node::Local(hir::Local {
1439 source: hir::LocalSource::Normal,
1444 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1445 err.span_suggestion(
1446 // account for `let x: _ = 42;`
1450 format!(": {concrete_type}"),
1451 Applicability::MaybeIncorrect,
1455 err.span_label(span, msg);
1468 /// For code `rect::area(...)`,
1469 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1470 /// we try to suggest `rect.area()`
1471 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1472 debug!("suggest_assoc_method_call segs: {:?}", segs);
1473 let [seg1, seg2] = segs else { return; };
1474 let Some(mut diag) =
1475 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1478 let map = self.infcx.tcx.hir();
1479 let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
1480 struct LetVisitor<'a> {
1481 result: Option<&'a hir::Expr<'a>>,
1485 // FIXME: This really should be taking scoping, etc into account.
1486 impl<'v> Visitor<'v> for LetVisitor<'v> {
1487 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1488 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1489 && let Binding(_, _, ident, ..) = pat.kind
1490 && ident.name == self.ident_name
1492 self.result = *init;
1494 hir::intravisit::walk_stmt(self, ex);
1499 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1500 visitor.visit_body(&body);
1502 let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
1503 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1504 && let Some(expr) = visitor.result
1505 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1507 let probe = self.lookup_probe(
1511 ProbeScope::TraitsInScope,
1514 let sm = self.infcx.tcx.sess.source_map();
1515 diag.span_suggestion_verbose(
1516 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1517 "you may have meant to call an instance method",
1519 Applicability::MaybeIncorrect,
1526 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1527 fn suggest_calling_method_on_field(
1529 err: &mut Diagnostic,
1530 source: SelfSource<'tcx>,
1535 if let SelfSource::MethodCall(expr) = source
1536 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1537 && let Some((fields, substs)) =
1538 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1540 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1542 let lang_items = self.tcx.lang_items();
1543 let never_mention_traits = [
1544 lang_items.clone_trait(),
1545 lang_items.deref_trait(),
1546 lang_items.deref_mut_trait(),
1547 self.tcx.get_diagnostic_item(sym::AsRef),
1548 self.tcx.get_diagnostic_item(sym::AsMut),
1549 self.tcx.get_diagnostic_item(sym::Borrow),
1550 self.tcx.get_diagnostic_item(sym::BorrowMut),
1552 let candidate_fields: Vec<_> = fields
1553 .filter_map(|candidate_field| {
1554 self.check_for_nested_field_satisfying(
1561 ProbeScope::TraitsInScope,
1563 .map_or(false, |pick| {
1564 !never_mention_traits
1567 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1579 .map(|id| id.name.to_ident_string())
1580 .collect::<Vec<String>>()
1585 let len = candidate_fields.len();
1587 err.span_suggestions(
1588 item_name.span.shrink_to_lo(),
1590 "{} of the expressions' fields {} a method of the same name",
1591 if len > 1 { "some" } else { "one" },
1592 if len > 1 { "have" } else { "has" },
1594 candidate_fields.iter().map(|path| format!("{path}.")),
1595 Applicability::MaybeIncorrect,
1601 fn check_for_inner_self(
1603 err: &mut Diagnostic,
1604 source: SelfSource<'tcx>,
1609 let SelfSource::MethodCall(expr) = source else { return; };
1610 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1612 let ty::Adt(kind, substs) = actual.kind() else { return; };
1613 match kind.adt_kind() {
1614 ty::AdtKind::Enum => {
1615 let matching_variants: Vec<_> = kind
1618 .flat_map(|variant| {
1619 let [field] = &variant.fields[..] else { return None; };
1620 let field_ty = field.ty(tcx, substs);
1622 // Skip `_`, since that'll just lead to ambiguity.
1623 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1627 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1629 .map(|pick| (variant, field, pick))
1633 let ret_ty_matches = |diagnostic_item| {
1634 if let Some(ret_ty) = self
1637 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1638 && let ty::Adt(kind, _) = ret_ty.kind()
1639 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1647 match &matching_variants[..] {
1648 [(_, field, pick)] => {
1649 let self_ty = field.ty(tcx, substs);
1651 tcx.def_span(pick.item.def_id),
1652 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1654 let (article, kind, variant, question) =
1655 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1656 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1657 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1658 ("an", "Option", "None", ret_ty_matches(sym::Option))
1663 err.span_suggestion_verbose(
1664 expr.span.shrink_to_hi(),
1666 "use the `?` operator to extract the `{self_ty}` value, propagating \
1667 {article} `{kind}::{variant}` value to the caller"
1670 Applicability::MachineApplicable,
1673 err.span_suggestion_verbose(
1674 expr.span.shrink_to_hi(),
1676 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1677 panicking if the value is {article} `{kind}::{variant}`"
1679 ".expect(\"REASON\")",
1680 Applicability::HasPlaceholders,
1684 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1688 // Target wrapper types - types that wrap or pretend to wrap another type,
1689 // perhaps this inner type is meant to be called?
1690 ty::AdtKind::Struct | ty::AdtKind::Union => {
1691 let [first] = ***substs else { return; };
1692 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1693 let Ok(pick) = self.lookup_probe(
1697 ProbeScope::TraitsInScope,
1700 let name = self.ty_to_value_string(actual);
1701 let inner_id = kind.did();
1702 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1703 pick.autoref_or_ptr_adjustment
1710 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1711 err.help("use `with` or `try_with` to access thread local storage");
1712 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1714 "if this `{name}` has been initialized, \
1715 use one of the `assume_init` methods to access the inner value"
1717 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1718 let (suggestion, borrow_kind, panic_if) = match mutable {
1719 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1720 Some(Mutability::Mut) => {
1721 (".borrow_mut()", "mutably borrow", "any borrows exist")
1725 err.span_suggestion_verbose(
1726 expr.span.shrink_to_hi(),
1728 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1729 panicking if {panic_if}"
1732 Applicability::MaybeIncorrect,
1734 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1735 err.span_suggestion_verbose(
1736 expr.span.shrink_to_hi(),
1738 "use `.lock().unwrap()` to borrow the `{ty}`, \
1739 blocking the current thread until it can be acquired"
1742 Applicability::MaybeIncorrect,
1744 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1745 let (suggestion, borrow_kind) = match mutable {
1746 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1747 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1750 err.span_suggestion_verbose(
1751 expr.span.shrink_to_hi(),
1753 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1754 blocking the current thread until it can be acquired"
1757 Applicability::MaybeIncorrect,
1764 tcx.def_span(pick.item.def_id),
1765 &format!("the method `{item_name}` exists on the type `{ty}`"),
1771 pub(crate) fn note_unmet_impls_on_type(
1773 err: &mut Diagnostic,
1774 errors: Vec<FulfillmentError<'tcx>>,
1776 let all_local_types_needing_impls =
1777 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1778 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1779 ty::Adt(def, _) => def.did().is_local(),
1784 let mut preds: Vec<_> = errors
1786 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1787 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1791 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1794 .filter_map(|pred| match pred.self_ty().kind() {
1795 ty::Adt(def, _) => Some(def.did()),
1798 .collect::<FxHashSet<_>>();
1799 let mut spans: MultiSpan = def_ids
1801 .filter_map(|def_id| {
1802 let span = self.tcx.def_span(*def_id);
1803 if span.is_dummy() { None } else { Some(span) }
1805 .collect::<Vec<_>>()
1808 for pred in &preds {
1809 match pred.self_ty().kind() {
1810 ty::Adt(def, _) if def.did().is_local() => {
1811 spans.push_span_label(
1812 self.tcx.def_span(def.did()),
1813 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1820 if all_local_types_needing_impls && spans.primary_span().is_some() {
1821 let msg = if preds.len() == 1 {
1823 "an implementation of `{}` might be missing for `{}`",
1824 preds[0].trait_ref.print_only_trait_path(),
1829 "the following type{} would have to `impl` {} required trait{} for this \
1830 operation to be valid",
1831 pluralize!(def_ids.len()),
1832 if def_ids.len() == 1 { "its" } else { "their" },
1833 pluralize!(preds.len()),
1836 err.span_note(spans, &msg);
1839 let preds: Vec<_> = errors
1841 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1843 self.suggest_derive(err, &preds);
1848 err: &mut Diagnostic,
1849 unsatisfied_predicates: &[(
1850 ty::Predicate<'tcx>,
1851 Option<ty::Predicate<'tcx>>,
1852 Option<ObligationCause<'tcx>>,
1855 let mut derives = Vec::<(String, Span, Symbol)>::new();
1856 let mut traits = Vec::new();
1857 for (pred, _, _) in unsatisfied_predicates {
1858 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1859 let adt = match trait_pred.self_ty().ty_adt_def() {
1860 Some(adt) if adt.did().is_local() => adt,
1863 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1864 let can_derive = match diagnostic_name {
1865 sym::Default => !adt.is_enum(),
1873 | sym::Debug => true,
1877 let self_name = trait_pred.self_ty().to_string();
1878 let self_span = self.tcx.def_span(adt.did());
1879 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1880 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1882 if let Some(parent_diagnostic_name) =
1883 self.tcx.get_diagnostic_name(super_trait.def_id())
1888 parent_diagnostic_name,
1893 derives.push((self_name, self_span, diagnostic_name));
1895 traits.push(trait_pred.def_id());
1898 traits.push(trait_pred.def_id());
1907 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1908 for (self_name, self_span, trait_name) in derives.into_iter() {
1909 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1911 if last_self_name == &self_name {
1912 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1916 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1919 let len = traits.len();
1922 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
1923 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
1924 for (i, &did) in traits.iter().enumerate().skip(1) {
1926 names.push_str(", ");
1929 names.push_str(" and ");
1932 names.push_str(&self.tcx.def_path_str(did));
1937 &format!("the trait{} {} must be implemented", pluralize!(len), names),
1941 for (self_name, self_span, traits) in &derives_grouped {
1942 err.span_suggestion_verbose(
1943 self_span.shrink_to_lo(),
1944 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1945 format!("#[derive({})]\n", traits),
1946 Applicability::MaybeIncorrect,
1951 fn check_for_deref_method(
1953 err: &mut Diagnostic,
1954 self_source: SelfSource<'tcx>,
1958 let SelfSource::QPath(ty) = self_source else { return; };
1959 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1960 if let Ok(pick) = self.probe_for_name(
1966 ProbeScope::TraitsInScope,
1968 if deref_ty.is_suggestable(self.tcx, true)
1969 // If this method receives `&self`, then the provided
1970 // argument _should_ coerce, so it's valid to suggest
1971 // just changing the path.
1972 && pick.item.fn_has_self_parameter
1973 && let Some(self_ty) =
1974 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1977 let suggested_path = match deref_ty.kind() {
1985 | ty::Alias(ty::Projection, _)
1986 | ty::Param(_) => format!("{deref_ty}"),
1987 // we need to test something like <&[_]>::len or <(&[u32])>::len
1988 // and Vec::function();
1989 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
1990 // but for Adt type like Vec::function()
1991 // we would suggest <[_]>::function();
1992 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
1993 _ => format!("<{deref_ty}>"),
1995 err.span_suggestion_verbose(
1997 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1999 Applicability::MaybeIncorrect,
2004 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2012 /// Print out the type for use in value namespace.
2013 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2015 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2016 _ => self.ty_to_string(ty),
2020 fn suggest_await_before_method(
2022 err: &mut Diagnostic,
2025 call: &hir::Expr<'_>,
2028 let output_ty = match self.get_impl_future_output_ty(ty) {
2029 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2032 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
2033 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2035 err.span_suggestion_verbose(
2036 span.shrink_to_lo(),
2037 "consider `await`ing on the `Future` and calling the method on its `Output`",
2039 Applicability::MaybeIncorrect,
2044 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2045 let parent_map = self.tcx.visible_parent_map(());
2047 // Separate out candidates that must be imported with a glob, because they are named `_`
2048 // and cannot be referred with their identifier.
2049 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2050 if let Some(parent_did) = parent_map.get(trait_did) {
2051 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2052 if *parent_did != self.tcx.parent(*trait_did)
2055 .module_children(*parent_did)
2057 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2058 .all(|child| child.ident.name == kw::Underscore)
2067 let module_did = self.tcx.parent_module(self.body_id);
2068 let (module, _, _) = self.tcx.hir().get_module(module_did);
2069 let span = module.spans.inject_use_span;
2071 let path_strings = candidates.iter().map(|trait_did| {
2072 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2075 let glob_path_strings = globs.iter().map(|trait_did| {
2076 let parent_did = parent_map.get(trait_did).unwrap();
2078 "use {}::*; // trait {}\n",
2079 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2080 self.tcx.item_name(*trait_did),
2084 err.span_suggestions(
2087 path_strings.chain(glob_path_strings),
2088 Applicability::MaybeIncorrect,
2092 fn suggest_valid_traits(
2094 err: &mut Diagnostic,
2095 valid_out_of_scope_traits: Vec<DefId>,
2097 if !valid_out_of_scope_traits.is_empty() {
2098 let mut candidates = valid_out_of_scope_traits;
2102 // `TryFrom` and `FromIterator` have no methods
2103 let edition_fix = candidates
2105 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2108 err.help("items from traits can only be used if the trait is in scope");
2110 "the following {traits_are} implemented but not in scope; \
2111 perhaps add a `use` for {one_of_them}:",
2112 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2113 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2116 self.suggest_use_candidates(err, msg, candidates);
2117 if let Some(did) = edition_fix {
2119 "'{}' is included in the prelude starting in Edition 2021",
2120 with_crate_prefix!(self.tcx.def_path_str(did))
2130 fn suggest_traits_to_import(
2132 err: &mut Diagnostic,
2136 inputs_len: Option<usize>,
2137 source: SelfSource<'tcx>,
2138 valid_out_of_scope_traits: Vec<DefId>,
2139 unsatisfied_predicates: &[(
2140 ty::Predicate<'tcx>,
2141 Option<ty::Predicate<'tcx>>,
2142 Option<ObligationCause<'tcx>>,
2144 static_candidates: &[CandidateSource],
2145 unsatisfied_bounds: bool,
2147 let mut alt_rcvr_sugg = false;
2148 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2150 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2151 span, item_name, rcvr_ty, rcvr
2154 self.tcx.lang_items().clone_trait(),
2155 self.tcx.lang_items().deref_trait(),
2156 self.tcx.lang_items().deref_mut_trait(),
2157 self.tcx.lang_items().drop_trait(),
2158 self.tcx.get_diagnostic_item(sym::AsRef),
2160 // Try alternative arbitrary self types that could fulfill this call.
2161 // FIXME: probe for all types that *could* be arbitrary self-types, not
2163 for (rcvr_ty, post) in &[
2165 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2166 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2168 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2170 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2171 // We point at the method, but we just skip the rest of the check for arbitrary
2172 // self types and rely on the suggestion to `use` the trait from
2173 // `suggest_valid_traits`.
2174 let did = Some(pick.item.container_id(self.tcx));
2175 let skip = skippable.contains(&did);
2176 if pick.autoderefs == 0 && !skip {
2178 pick.item.ident(self.tcx).span,
2179 &format!("the method is available for `{}` here", rcvr_ty),
2184 Err(MethodError::Ambiguity(_)) => {
2185 // If the method is defined (but ambiguous) for the receiver we have, it is also
2186 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2187 // the receiver, then it might disambiguate this method, but I think these
2188 // suggestions are generally misleading (see #94218).
2194 for (rcvr_ty, pre) in &[
2195 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2196 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2197 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2198 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2200 if let Some(new_rcvr_t) = *rcvr_ty
2201 && let Ok(pick) = self.lookup_probe(
2205 ProbeScope::AllTraits,
2208 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2209 let did = Some(pick.item.container_id(self.tcx));
2210 // We don't want to suggest a container type when the missing
2211 // method is `.clone()` or `.deref()` otherwise we'd suggest
2212 // `Arc::new(foo).clone()`, which is far from what the user wants.
2213 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2214 // implement the `AsRef` trait.
2215 let skip = skippable.contains(&did)
2216 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2217 || 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);
2218 // Make sure the method is defined for the *actual* receiver: we don't
2219 // want to treat `Box<Self>` as a receiver if it only works because of
2220 // an autoderef to `&self`
2221 if pick.autoderefs == 0 && !skip {
2223 pick.item.ident(self.tcx).span,
2224 &format!("the method is available for `{}` here", new_rcvr_t),
2226 err.multipart_suggestion(
2227 "consider wrapping the receiver expression with the \
2230 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2231 (rcvr.span.shrink_to_hi(), ")".to_string()),
2233 Applicability::MaybeIncorrect,
2235 // We don't care about the other suggestions.
2236 alt_rcvr_sugg = true;
2242 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2246 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2248 let mut arbitrary_rcvr = vec![];
2249 // There are no traits implemented, so lets suggest some traits to
2250 // implement, by finding ones that have the item name, and are
2251 // legal to implement.
2252 let mut candidates = all_traits(self.tcx)
2254 // Don't issue suggestions for unstable traits since they're
2255 // unlikely to be implementable anyway
2256 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2257 Some(attr) => attr.level.is_stable(),
2261 // Static candidates are already implemented, and known not to work
2262 // Do not suggest them again
2263 static_candidates.iter().all(|sc| match *sc {
2264 CandidateSource::Trait(def_id) => def_id != info.def_id,
2265 CandidateSource::Impl(def_id) => {
2266 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2271 // We approximate the coherence rules to only suggest
2272 // traits that are legal to implement by requiring that
2273 // either the type or trait is local. Multi-dispatch means
2274 // this isn't perfect (that is, there are cases when
2275 // implementing a trait would be legal but is rejected
2277 unsatisfied_predicates.iter().all(|(p, _, _)| {
2278 match p.kind().skip_binder() {
2279 // Hide traits if they are present in predicates as they can be fixed without
2280 // having to implement them.
2281 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2282 t.def_id() == info.def_id
2284 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2285 p.projection_ty.def_id == info.def_id
2289 }) && (type_is_local || info.def_id.is_local())
2291 .associated_value(info.def_id, item_name)
2293 if let ty::AssocKind::Fn = item.kind {
2297 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2298 if let Some(hir::Node::TraitItem(hir::TraitItem {
2299 kind: hir::TraitItemKind::Fn(fn_sig, method),
2301 })) = id.map(|id| self.tcx.hir().get(id))
2303 let self_first_arg = match method {
2304 hir::TraitFn::Required([ident, ..]) => {
2305 ident.name == kw::SelfLower
2307 hir::TraitFn::Provided(body_id) => {
2308 self.tcx.hir().body(*body_id).params.first().map_or(
2313 hir::PatKind::Binding(_, _, ident, _)
2314 if ident.name == kw::SelfLower
2322 if !fn_sig.decl.implicit_self.has_implicit_self()
2325 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2326 arbitrary_rcvr.push(ty.span);
2332 // We only want to suggest public or local traits (#45781).
2333 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2337 .collect::<Vec<_>>();
2338 for span in &arbitrary_rcvr {
2341 "the method might not be found because of this arbitrary self type",
2348 if !candidates.is_empty() {
2349 // Sort from most relevant to least relevant.
2350 candidates.sort_by(|a, b| a.cmp(b).reverse());
2353 let param_type = match rcvr_ty.kind() {
2354 ty::Param(param) => Some(param),
2355 ty::Ref(_, ty, _) => match ty.kind() {
2356 ty::Param(param) => Some(param),
2361 err.help(if param_type.is_some() {
2362 "items from traits can only be used if the type parameter is bounded by the trait"
2364 "items from traits can only be used if the trait is implemented and in scope"
2366 let candidates_len = candidates.len();
2367 let message = |action| {
2369 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2372 if candidates_len == 1 { "trait defines" } else { "traits define" },
2374 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2378 // Obtain the span for `param` and use it for a structured suggestion.
2379 if let Some(param) = param_type {
2380 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2381 let type_param = generics.type_param(param, self.tcx);
2382 let hir = self.tcx.hir();
2383 if let Some(def_id) = type_param.def_id.as_local() {
2384 let id = hir.local_def_id_to_hir_id(def_id);
2385 // Get the `hir::Param` to verify whether it already has any bounds.
2386 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2387 // instead we suggest `T: Foo + Bar` in that case.
2389 Node::GenericParam(param) => {
2395 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2396 let (sp, mut introducer) = if let Some(span) =
2397 ast_generics.bounds_span_for_suggestions(def_id)
2399 (span, Introducer::Plus)
2400 } else if let Some(colon_span) = param.colon_span {
2401 (colon_span.shrink_to_hi(), Introducer::Nothing)
2403 (param.span.shrink_to_hi(), Introducer::Colon)
2407 hir::GenericParamKind::Type { synthetic: true, .. },
2409 introducer = Introducer::Plus
2411 let trait_def_ids: FxHashSet<DefId> = ast_generics
2412 .bounds_for_param(def_id)
2413 .flat_map(|bp| bp.bounds.iter())
2414 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2416 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2417 err.span_suggestions(
2420 "restrict type parameter `{}` with",
2423 candidates.iter().map(|t| {
2427 Introducer::Plus => " +",
2428 Introducer::Colon => ":",
2429 Introducer::Nothing => "",
2431 self.tcx.def_path_str(t.def_id),
2434 Applicability::MaybeIncorrect,
2439 Node::Item(hir::Item {
2440 kind: hir::ItemKind::Trait(.., bounds, _),
2444 let (sp, sep, article) = if bounds.is_empty() {
2445 (ident.span.shrink_to_hi(), ":", "a")
2447 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2449 err.span_suggestions(
2451 &message(format!("add {} supertrait for", article)),
2452 candidates.iter().map(|t| {
2453 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2455 Applicability::MaybeIncorrect,
2464 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2465 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2466 // cases where a positive bound implies a negative impl.
2467 (candidates, Vec::new())
2468 } else if let Some(simp_rcvr_ty) =
2469 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2471 let mut potential_candidates = Vec::new();
2472 let mut explicitly_negative = Vec::new();
2473 for candidate in candidates {
2474 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2477 .all_impls(candidate.def_id)
2479 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2482 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2484 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2485 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2488 explicitly_negative.push(candidate);
2490 potential_candidates.push(candidate);
2493 (potential_candidates, explicitly_negative)
2495 // We don't know enough about `recv_ty` to make proper suggestions.
2496 (candidates, Vec::new())
2499 let action = if let Some(param) = param_type {
2500 format!("restrict type parameter `{}` with", param)
2502 // FIXME: it might only need to be imported into scope, not implemented.
2503 "implement".to_string()
2505 match &potential_candidates[..] {
2507 [trait_info] if trait_info.def_id.is_local() => {
2509 self.tcx.def_span(trait_info.def_id),
2511 "`{}` defines an item `{}`, perhaps you need to {} it",
2512 self.tcx.def_path_str(trait_info.def_id),
2519 let mut msg = message(action);
2520 for (i, trait_info) in trait_infos.iter().enumerate() {
2521 msg.push_str(&format!(
2522 "\ncandidate #{}: `{}`",
2524 self.tcx.def_path_str(trait_info.def_id),
2530 match &explicitly_negative[..] {
2534 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2535 self.tcx.def_path_str(trait_info.def_id),
2541 let mut msg = format!(
2542 "the following traits define an item `{}`, but are explicitly unimplemented:",
2545 for trait_info in trait_infos {
2546 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2554 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2555 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2556 pub(crate) fn suggest_else_fn_with_closure(
2558 err: &mut Diagnostic,
2559 expr: &hir::Expr<'_>,
2563 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2564 else { return false; };
2566 if !self.can_coerce(output, expected) {
2570 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2571 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2572 let hir::ExprKind::MethodCall(
2573 hir::PathSegment { ident: method_name, .. },
2577 ) = call_expr.kind &&
2578 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2579 let new_name = Ident {
2580 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2581 span: method_name.span,
2583 let probe = self.lookup_probe(
2587 ProbeScope::TraitsInScope,
2590 // check the method arguments number
2591 if let Ok(pick) = probe &&
2592 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2593 let fn_args = fn_sig.skip_binder().inputs() &&
2594 fn_args.len() == args.len() + 1 {
2595 err.span_suggestion_verbose(
2596 method_name.span.shrink_to_hi(),
2597 &format!("try calling `{}` instead", new_name.name.as_str()),
2599 Applicability::MaybeIncorrect,
2607 /// Checks whether there is a local type somewhere in the chain of
2608 /// autoderefs of `rcvr_ty`.
2609 fn type_derefs_to_local(
2613 source: SelfSource<'tcx>,
2615 fn is_local(ty: Ty<'_>) -> bool {
2617 ty::Adt(def, _) => def.did().is_local(),
2618 ty::Foreign(did) => did.is_local(),
2619 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2620 ty::Param(_) => true,
2622 // Everything else (primitive types, etc.) is effectively
2623 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2624 // the noise from these sort of types is usually just really
2625 // annoying, rather than any sort of help).
2630 // This occurs for UFCS desugaring of `T::method`, where there is no
2631 // receiver expression for the method call, and thus no autoderef.
2632 if let SelfSource::QPath(_) = source {
2633 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2636 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2640 #[derive(Copy, Clone, Debug)]
2641 pub enum SelfSource<'a> {
2642 QPath(&'a hir::Ty<'a>),
2643 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2646 #[derive(Copy, Clone)]
2647 pub struct TraitInfo {
2651 impl PartialEq for TraitInfo {
2652 fn eq(&self, other: &TraitInfo) -> bool {
2653 self.cmp(other) == Ordering::Equal
2656 impl Eq for TraitInfo {}
2657 impl PartialOrd for TraitInfo {
2658 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2659 Some(self.cmp(other))
2662 impl Ord for TraitInfo {
2663 fn cmp(&self, other: &TraitInfo) -> Ordering {
2664 // Local crates are more important than remote ones (local:
2665 // `cnum == 0`), and otherwise we throw in the defid for totality.
2667 let lhs = (other.def_id.krate, other.def_id);
2668 let rhs = (self.def_id.krate, self.def_id);
2673 /// Retrieves all traits in this crate and any dependent crates,
2674 /// and wraps them into `TraitInfo` for custom sorting.
2675 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2676 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2679 fn print_disambiguation_help<'tcx>(
2681 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2682 err: &mut Diagnostic,
2685 kind: ty::AssocKind,
2688 candidate: Option<usize>,
2689 source_map: &source_map::SourceMap,
2690 fn_has_self_parameter: bool,
2692 let mut applicability = Applicability::MachineApplicable;
2693 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2696 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2697 std::iter::once(receiver)
2699 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2700 applicability = Applicability::HasPlaceholders;
2703 .collect::<Vec<_>>()
2706 let trait_name = if !fn_has_self_parameter {
2707 format!("<{} as {}>", rcvr_ty, trait_name)
2711 (span, format!("{}::{}{}", trait_name, item_name, args))
2713 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2715 err.span_suggestion_verbose(
2718 "disambiguate the {} for {}",
2719 kind.as_def_kind().descr(def_id),
2720 if let Some(candidate) = candidate {
2721 format!("candidate #{}", candidate)
2723 "the candidate".to_string()