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::ProjectionTy {
561 substs: substs_with_infer_self,
562 item_def_id: projection_ty.item_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::<Span>::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(self.tcx.def_span(trait_pred.def_id()));
1898 traits.push(self.tcx.def_span(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();
1921 let span: MultiSpan = traits.into();
1924 &format!("the following trait{} must be implemented", pluralize!(len),),
1928 for (self_name, self_span, traits) in &derives_grouped {
1929 err.span_suggestion_verbose(
1930 self_span.shrink_to_lo(),
1931 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1932 format!("#[derive({})]\n", traits),
1933 Applicability::MaybeIncorrect,
1938 fn check_for_deref_method(
1940 err: &mut Diagnostic,
1941 self_source: SelfSource<'tcx>,
1945 let SelfSource::QPath(ty) = self_source else { return; };
1946 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1947 if let Ok(pick) = self.probe_for_name(
1953 ProbeScope::TraitsInScope,
1955 if deref_ty.is_suggestable(self.tcx, true)
1956 // If this method receives `&self`, then the provided
1957 // argument _should_ coerce, so it's valid to suggest
1958 // just changing the path.
1959 && pick.item.fn_has_self_parameter
1960 && let Some(self_ty) =
1961 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1964 let suggested_path = match deref_ty.kind() {
1973 | ty::Param(_) => format!("{deref_ty}"),
1974 // we need to test something like <&[_]>::len or <(&[u32])>::len
1975 // and Vec::function();
1976 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
1977 // but for Adt type like Vec::function()
1978 // we would suggest <[_]>::function();
1979 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
1980 _ => format!("<{deref_ty}>"),
1982 err.span_suggestion_verbose(
1984 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1986 Applicability::MaybeIncorrect,
1991 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1999 /// Print out the type for use in value namespace.
2000 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2002 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2003 _ => self.ty_to_string(ty),
2007 fn suggest_await_before_method(
2009 err: &mut Diagnostic,
2012 call: &hir::Expr<'_>,
2015 let output_ty = match self.get_impl_future_output_ty(ty) {
2016 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2019 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
2020 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2022 err.span_suggestion_verbose(
2023 span.shrink_to_lo(),
2024 "consider `await`ing on the `Future` and calling the method on its `Output`",
2026 Applicability::MaybeIncorrect,
2031 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2032 let parent_map = self.tcx.visible_parent_map(());
2034 // Separate out candidates that must be imported with a glob, because they are named `_`
2035 // and cannot be referred with their identifier.
2036 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2037 if let Some(parent_did) = parent_map.get(trait_did) {
2038 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2039 if *parent_did != self.tcx.parent(*trait_did)
2042 .module_children(*parent_did)
2044 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2045 .all(|child| child.ident.name == kw::Underscore)
2054 let module_did = self.tcx.parent_module(self.body_id);
2055 let (module, _, _) = self.tcx.hir().get_module(module_did);
2056 let span = module.spans.inject_use_span;
2058 let path_strings = candidates.iter().map(|trait_did| {
2059 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2062 let glob_path_strings = globs.iter().map(|trait_did| {
2063 let parent_did = parent_map.get(trait_did).unwrap();
2065 "use {}::*; // trait {}\n",
2066 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2067 self.tcx.item_name(*trait_did),
2071 err.span_suggestions(
2074 path_strings.chain(glob_path_strings),
2075 Applicability::MaybeIncorrect,
2079 fn suggest_valid_traits(
2081 err: &mut Diagnostic,
2082 valid_out_of_scope_traits: Vec<DefId>,
2084 if !valid_out_of_scope_traits.is_empty() {
2085 let mut candidates = valid_out_of_scope_traits;
2089 // `TryFrom` and `FromIterator` have no methods
2090 let edition_fix = candidates
2092 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2095 err.help("items from traits can only be used if the trait is in scope");
2097 "the following {traits_are} implemented but not in scope; \
2098 perhaps add a `use` for {one_of_them}:",
2099 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2100 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2103 self.suggest_use_candidates(err, msg, candidates);
2104 if let Some(did) = edition_fix {
2106 "'{}' is included in the prelude starting in Edition 2021",
2107 with_crate_prefix!(self.tcx.def_path_str(did))
2117 fn suggest_traits_to_import(
2119 err: &mut Diagnostic,
2123 inputs_len: Option<usize>,
2124 source: SelfSource<'tcx>,
2125 valid_out_of_scope_traits: Vec<DefId>,
2126 unsatisfied_predicates: &[(
2127 ty::Predicate<'tcx>,
2128 Option<ty::Predicate<'tcx>>,
2129 Option<ObligationCause<'tcx>>,
2131 static_candidates: &[CandidateSource],
2132 unsatisfied_bounds: bool,
2134 let mut alt_rcvr_sugg = false;
2135 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2137 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2138 span, item_name, rcvr_ty, rcvr
2141 self.tcx.lang_items().clone_trait(),
2142 self.tcx.lang_items().deref_trait(),
2143 self.tcx.lang_items().deref_mut_trait(),
2144 self.tcx.lang_items().drop_trait(),
2145 self.tcx.get_diagnostic_item(sym::AsRef),
2147 // Try alternative arbitrary self types that could fulfill this call.
2148 // FIXME: probe for all types that *could* be arbitrary self-types, not
2150 for (rcvr_ty, post) in &[
2152 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2153 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2155 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2157 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2158 // We point at the method, but we just skip the rest of the check for arbitrary
2159 // self types and rely on the suggestion to `use` the trait from
2160 // `suggest_valid_traits`.
2161 let did = Some(pick.item.container_id(self.tcx));
2162 let skip = skippable.contains(&did);
2163 if pick.autoderefs == 0 && !skip {
2165 pick.item.ident(self.tcx).span,
2166 &format!("the method is available for `{}` here", rcvr_ty),
2171 Err(MethodError::Ambiguity(_)) => {
2172 // If the method is defined (but ambiguous) for the receiver we have, it is also
2173 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2174 // the receiver, then it might disambiguate this method, but I think these
2175 // suggestions are generally misleading (see #94218).
2181 for (rcvr_ty, pre) in &[
2182 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2183 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2184 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2185 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2187 if let Some(new_rcvr_t) = *rcvr_ty
2188 && let Ok(pick) = self.lookup_probe(
2192 ProbeScope::AllTraits,
2195 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2196 let did = Some(pick.item.container_id(self.tcx));
2197 // We don't want to suggest a container type when the missing
2198 // method is `.clone()` or `.deref()` otherwise we'd suggest
2199 // `Arc::new(foo).clone()`, which is far from what the user wants.
2200 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2201 // implement the `AsRef` trait.
2202 let skip = skippable.contains(&did)
2203 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2204 || 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);
2205 // Make sure the method is defined for the *actual* receiver: we don't
2206 // want to treat `Box<Self>` as a receiver if it only works because of
2207 // an autoderef to `&self`
2208 if pick.autoderefs == 0 && !skip {
2210 pick.item.ident(self.tcx).span,
2211 &format!("the method is available for `{}` here", new_rcvr_t),
2213 err.multipart_suggestion(
2214 "consider wrapping the receiver expression with the \
2217 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2218 (rcvr.span.shrink_to_hi(), ")".to_string()),
2220 Applicability::MaybeIncorrect,
2222 // We don't care about the other suggestions.
2223 alt_rcvr_sugg = true;
2229 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2233 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2235 let mut arbitrary_rcvr = vec![];
2236 // There are no traits implemented, so lets suggest some traits to
2237 // implement, by finding ones that have the item name, and are
2238 // legal to implement.
2239 let mut candidates = all_traits(self.tcx)
2241 // Don't issue suggestions for unstable traits since they're
2242 // unlikely to be implementable anyway
2243 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2244 Some(attr) => attr.level.is_stable(),
2248 // Static candidates are already implemented, and known not to work
2249 // Do not suggest them again
2250 static_candidates.iter().all(|sc| match *sc {
2251 CandidateSource::Trait(def_id) => def_id != info.def_id,
2252 CandidateSource::Impl(def_id) => {
2253 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2258 // We approximate the coherence rules to only suggest
2259 // traits that are legal to implement by requiring that
2260 // either the type or trait is local. Multi-dispatch means
2261 // this isn't perfect (that is, there are cases when
2262 // implementing a trait would be legal but is rejected
2264 unsatisfied_predicates.iter().all(|(p, _, _)| {
2265 match p.kind().skip_binder() {
2266 // Hide traits if they are present in predicates as they can be fixed without
2267 // having to implement them.
2268 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2269 t.def_id() == info.def_id
2271 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2272 p.projection_ty.item_def_id == info.def_id
2276 }) && (type_is_local || info.def_id.is_local())
2278 .associated_value(info.def_id, item_name)
2280 if let ty::AssocKind::Fn = item.kind {
2284 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2285 if let Some(hir::Node::TraitItem(hir::TraitItem {
2286 kind: hir::TraitItemKind::Fn(fn_sig, method),
2288 })) = id.map(|id| self.tcx.hir().get(id))
2290 let self_first_arg = match method {
2291 hir::TraitFn::Required([ident, ..]) => {
2292 ident.name == kw::SelfLower
2294 hir::TraitFn::Provided(body_id) => {
2295 self.tcx.hir().body(*body_id).params.first().map_or(
2300 hir::PatKind::Binding(_, _, ident, _)
2301 if ident.name == kw::SelfLower
2309 if !fn_sig.decl.implicit_self.has_implicit_self()
2312 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2313 arbitrary_rcvr.push(ty.span);
2319 // We only want to suggest public or local traits (#45781).
2320 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2324 .collect::<Vec<_>>();
2325 for span in &arbitrary_rcvr {
2328 "the method might not be found because of this arbitrary self type",
2335 if !candidates.is_empty() {
2336 // Sort from most relevant to least relevant.
2337 candidates.sort_by(|a, b| a.cmp(b).reverse());
2340 let param_type = match rcvr_ty.kind() {
2341 ty::Param(param) => Some(param),
2342 ty::Ref(_, ty, _) => match ty.kind() {
2343 ty::Param(param) => Some(param),
2348 err.help(if param_type.is_some() {
2349 "items from traits can only be used if the type parameter is bounded by the trait"
2351 "items from traits can only be used if the trait is implemented and in scope"
2353 let candidates_len = candidates.len();
2354 let message = |action| {
2356 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2359 if candidates_len == 1 { "trait defines" } else { "traits define" },
2361 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2365 // Obtain the span for `param` and use it for a structured suggestion.
2366 if let Some(param) = param_type {
2367 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2368 let type_param = generics.type_param(param, self.tcx);
2369 let hir = self.tcx.hir();
2370 if let Some(def_id) = type_param.def_id.as_local() {
2371 let id = hir.local_def_id_to_hir_id(def_id);
2372 // Get the `hir::Param` to verify whether it already has any bounds.
2373 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2374 // instead we suggest `T: Foo + Bar` in that case.
2376 Node::GenericParam(param) => {
2382 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2383 let (sp, mut introducer) = if let Some(span) =
2384 ast_generics.bounds_span_for_suggestions(def_id)
2386 (span, Introducer::Plus)
2387 } else if let Some(colon_span) = param.colon_span {
2388 (colon_span.shrink_to_hi(), Introducer::Nothing)
2390 (param.span.shrink_to_hi(), Introducer::Colon)
2394 hir::GenericParamKind::Type { synthetic: true, .. },
2396 introducer = Introducer::Plus
2398 let trait_def_ids: FxHashSet<DefId> = ast_generics
2399 .bounds_for_param(def_id)
2400 .flat_map(|bp| bp.bounds.iter())
2401 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2403 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2404 err.span_suggestions(
2407 "restrict type parameter `{}` with",
2410 candidates.iter().map(|t| {
2414 Introducer::Plus => " +",
2415 Introducer::Colon => ":",
2416 Introducer::Nothing => "",
2418 self.tcx.def_path_str(t.def_id),
2421 Applicability::MaybeIncorrect,
2426 Node::Item(hir::Item {
2427 kind: hir::ItemKind::Trait(.., bounds, _),
2431 let (sp, sep, article) = if bounds.is_empty() {
2432 (ident.span.shrink_to_hi(), ":", "a")
2434 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2436 err.span_suggestions(
2438 &message(format!("add {} supertrait for", article)),
2439 candidates.iter().map(|t| {
2440 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2442 Applicability::MaybeIncorrect,
2451 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2452 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2453 // cases where a positive bound implies a negative impl.
2454 (candidates, Vec::new())
2455 } else if let Some(simp_rcvr_ty) =
2456 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2458 let mut potential_candidates = Vec::new();
2459 let mut explicitly_negative = Vec::new();
2460 for candidate in candidates {
2461 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2464 .all_impls(candidate.def_id)
2466 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2469 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2471 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2472 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2475 explicitly_negative.push(candidate);
2477 potential_candidates.push(candidate);
2480 (potential_candidates, explicitly_negative)
2482 // We don't know enough about `recv_ty` to make proper suggestions.
2483 (candidates, Vec::new())
2486 let action = if let Some(param) = param_type {
2487 format!("restrict type parameter `{}` with", param)
2489 // FIXME: it might only need to be imported into scope, not implemented.
2490 "implement".to_string()
2492 match &potential_candidates[..] {
2494 [trait_info] if trait_info.def_id.is_local() => {
2496 self.tcx.def_span(trait_info.def_id),
2498 "`{}` defines an item `{}`, perhaps you need to {} it",
2499 self.tcx.def_path_str(trait_info.def_id),
2506 let mut msg = message(action);
2507 for (i, trait_info) in trait_infos.iter().enumerate() {
2508 msg.push_str(&format!(
2509 "\ncandidate #{}: `{}`",
2511 self.tcx.def_path_str(trait_info.def_id),
2517 match &explicitly_negative[..] {
2521 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2522 self.tcx.def_path_str(trait_info.def_id),
2528 let mut msg = format!(
2529 "the following traits define an item `{}`, but are explicitly unimplemented:",
2532 for trait_info in trait_infos {
2533 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2541 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2542 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2543 pub(crate) fn suggest_else_fn_with_closure(
2545 err: &mut Diagnostic,
2546 expr: &hir::Expr<'_>,
2550 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2551 else { return false; };
2553 if !self.can_coerce(output, expected) {
2557 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2558 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2559 let hir::ExprKind::MethodCall(
2560 hir::PathSegment { ident: method_name, .. },
2564 ) = call_expr.kind &&
2565 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2566 let new_name = Ident {
2567 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2568 span: method_name.span,
2570 let probe = self.lookup_probe(
2574 ProbeScope::TraitsInScope,
2577 // check the method arguments number
2578 if let Ok(pick) = probe &&
2579 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2580 let fn_args = fn_sig.skip_binder().inputs() &&
2581 fn_args.len() == args.len() + 1 {
2582 err.span_suggestion_verbose(
2583 method_name.span.shrink_to_hi(),
2584 &format!("try calling `{}` instead", new_name.name.as_str()),
2586 Applicability::MaybeIncorrect,
2594 /// Checks whether there is a local type somewhere in the chain of
2595 /// autoderefs of `rcvr_ty`.
2596 fn type_derefs_to_local(
2600 source: SelfSource<'tcx>,
2602 fn is_local(ty: Ty<'_>) -> bool {
2604 ty::Adt(def, _) => def.did().is_local(),
2605 ty::Foreign(did) => did.is_local(),
2606 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2607 ty::Param(_) => true,
2609 // Everything else (primitive types, etc.) is effectively
2610 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2611 // the noise from these sort of types is usually just really
2612 // annoying, rather than any sort of help).
2617 // This occurs for UFCS desugaring of `T::method`, where there is no
2618 // receiver expression for the method call, and thus no autoderef.
2619 if let SelfSource::QPath(_) = source {
2620 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2623 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2627 #[derive(Copy, Clone, Debug)]
2628 pub enum SelfSource<'a> {
2629 QPath(&'a hir::Ty<'a>),
2630 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2633 #[derive(Copy, Clone)]
2634 pub struct TraitInfo {
2638 impl PartialEq for TraitInfo {
2639 fn eq(&self, other: &TraitInfo) -> bool {
2640 self.cmp(other) == Ordering::Equal
2643 impl Eq for TraitInfo {}
2644 impl PartialOrd for TraitInfo {
2645 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2646 Some(self.cmp(other))
2649 impl Ord for TraitInfo {
2650 fn cmp(&self, other: &TraitInfo) -> Ordering {
2651 // Local crates are more important than remote ones (local:
2652 // `cnum == 0`), and otherwise we throw in the defid for totality.
2654 let lhs = (other.def_id.krate, other.def_id);
2655 let rhs = (self.def_id.krate, self.def_id);
2660 /// Retrieves all traits in this crate and any dependent crates,
2661 /// and wraps them into `TraitInfo` for custom sorting.
2662 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2663 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2666 fn print_disambiguation_help<'tcx>(
2668 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2669 err: &mut Diagnostic,
2672 kind: ty::AssocKind,
2675 candidate: Option<usize>,
2676 source_map: &source_map::SourceMap,
2677 fn_has_self_parameter: bool,
2679 let mut applicability = Applicability::MachineApplicable;
2680 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2683 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2684 std::iter::once(receiver)
2686 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2687 applicability = Applicability::HasPlaceholders;
2690 .collect::<Vec<_>>()
2693 let trait_name = if !fn_has_self_parameter {
2694 format!("<{} as {}>", rcvr_ty, trait_name)
2698 (span, format!("{}::{}{}", trait_name, item_name, args))
2700 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2702 err.span_suggestion_verbose(
2705 "disambiguate the {} for {}",
2706 kind.as_def_kind().descr(def_id),
2707 if let Some(candidate) = candidate {
2708 format!("candidate #{}", candidate)
2710 "the candidate".to_string()