1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
13 use rustc_hir::def::DefKind;
14 use rustc_hir::def_id::DefId;
15 use rustc_hir::lang_items::LangItem;
16 use rustc_hir::{ExprKind, Node, QPath};
17 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
18 use rustc_middle::traits::util::supertraits;
19 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
20 use rustc_middle::ty::print::with_crate_prefix;
21 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
22 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
23 use rustc_span::symbol::{kw, sym, Ident};
24 use rustc_span::Symbol;
25 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
26 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
27 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
28 use rustc_trait_selection::traits::{
29 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
32 use std::cmp::Ordering;
35 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
36 use super::{CandidateSource, MethodError, NoMatchData};
38 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
42 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
43 // so we look for these beforehand.
44 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
45 // If it's not a simple function, look for things which implement `FnOnce`.
47 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
51 // This conditional prevents us from asking to call errors and unresolved types.
52 // It might seem that we can use `predicate_must_hold_modulo_regions`,
53 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
54 // type resolution always gives a "maybe" here.
55 if self.autoderef(span, ty).any(|(ty, _)| {
56 info!("check deref {:?} error", ty);
57 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
62 self.autoderef(span, ty).any(|(ty, _)| {
63 info!("check deref {:?} impl FnOnce", ty);
65 let fn_once_substs = tcx.mk_substs_trait(
68 .next_ty_var(TypeVariableOrigin {
69 kind: TypeVariableOriginKind::MiscVariable,
74 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
75 let poly_trait_ref = ty::Binder::dummy(trait_ref);
76 let obligation = Obligation::misc(
80 poly_trait_ref.without_const().to_predicate(tcx),
82 self.predicate_may_hold(&obligation)
89 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
90 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
93 pub fn report_method_error(
98 source: SelfSource<'tcx>,
99 error: MethodError<'tcx>,
100 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
101 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
102 // Avoid suggestions when we don't know what's going on.
103 if rcvr_ty.references_error() {
107 let report_candidates = |span: Span,
108 err: &mut Diagnostic,
109 sources: &mut Vec<CandidateSource>,
113 // Dynamic limit to avoid hiding just one candidate, which is silly.
114 let limit = if sources.len() == 5 { 5 } else { 4 };
116 for (idx, source) in sources.iter().take(limit).enumerate() {
118 CandidateSource::Impl(impl_did) => {
119 // Provide the best span we can. Use the item, if local to crate, else
120 // the impl, if local to crate (item may be defaulted), else nothing.
121 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
122 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
123 self.associated_value(impl_trait_ref.def_id, item_name)
128 let note_span = if item.def_id.is_local() {
129 Some(self.tcx.def_span(item.def_id))
130 } else if impl_did.is_local() {
131 Some(self.tcx.def_span(impl_did))
136 let impl_ty = self.tcx.at(span).type_of(impl_did);
138 let insertion = match self.tcx.impl_trait_ref(impl_did) {
139 None => String::new(),
140 Some(trait_ref) => format!(
141 " of the trait `{}`",
142 self.tcx.def_path_str(trait_ref.def_id)
146 let (note_str, idx) = if sources.len() > 1 {
149 "candidate #{} is defined in an impl{} for the type `{}`",
159 "the candidate is defined in an impl{} for the type `{}`",
165 if let Some(note_span) = note_span {
166 // We have a span pointing to the method. Show note with snippet.
167 err.span_note(note_span, ¬e_str);
171 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
172 let path = self.tcx.def_path_str(trait_ref.def_id);
174 let ty = match item.kind {
175 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
176 ty::AssocKind::Fn => self
182 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
186 print_disambiguation_help(
196 self.tcx.sess.source_map(),
197 item.fn_has_self_parameter,
201 CandidateSource::Trait(trait_did) => {
202 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
203 let item_span = self.tcx.def_span(item.def_id);
204 let idx = if sources.len() > 1 {
206 "candidate #{} is defined in the trait `{}`",
208 self.tcx.def_path_str(trait_did)
210 err.span_note(item_span, msg);
214 "the candidate is defined in the trait `{}`",
215 self.tcx.def_path_str(trait_did)
217 err.span_note(item_span, msg);
220 let path = self.tcx.def_path_str(trait_did);
221 print_disambiguation_help(
231 self.tcx.sess.source_map(),
232 item.fn_has_self_parameter,
237 if sources.len() > limit {
238 err.note(&format!("and {} others", sources.len() - limit));
242 let sugg_span = if let SelfSource::MethodCall(expr) = source {
243 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
244 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
250 MethodError::NoMatch(NoMatchData {
251 mut static_candidates,
252 unsatisfied_predicates,
259 let actual = self.resolve_vars_if_possible(rcvr_ty);
260 let ty_str = self.ty_to_string(actual);
261 let is_method = mode == Mode::MethodCall;
262 let item_kind = if is_method {
264 } else if actual.is_enum() {
265 "variant or associated item"
267 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
268 (Some(name), false) if name.is_lowercase() => "function or associated item",
269 (Some(_), false) => "associated item",
270 (Some(_), true) | (None, false) => "variant or associated item",
271 (None, true) => "variant",
275 if self.suggest_wrapping_range_with_parens(
276 tcx, actual, source, span, item_name, &ty_str,
277 ) || self.suggest_constraining_numerical_ty(
278 tcx, actual, source, span, item_kind, item_name, &ty_str,
283 span = item_name.span;
285 // Don't show generic arguments when the method can't be found in any implementation (#81576).
286 let mut ty_str_reported = ty_str.clone();
287 if let ty::Adt(_, generics) = actual.kind() {
288 if generics.len() > 0 {
289 let mut autoderef = self.autoderef(span, actual);
290 let candidate_found = autoderef.any(|(ty, _)| {
291 if let ty::Adt(adt_def, _) = ty.kind() {
293 .inherent_impls(adt_def.did())
295 .filter_map(|def_id| self.associated_value(*def_id, item_name))
302 let has_deref = autoderef.step_count() > 0;
303 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
304 if let Some((path_string, _)) = ty_str.split_once('<') {
305 ty_str_reported = path_string.to_string();
311 let mut err = struct_span_err!(
315 "no {} named `{}` found for {} `{}` in the current scope",
318 actual.prefix_string(self.tcx),
321 if actual.references_error() {
322 err.downgrade_to_delayed_bug();
325 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
326 self.suggest_await_before_method(
327 &mut err, item_name, actual, cal, span,
330 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
333 "you are looking for the module in `std`, not the primitive type",
335 Applicability::MachineApplicable,
338 if let ty::RawPtr(_) = &actual.kind() {
340 "try using `<*const T>::as_ref()` to get a reference to the \
341 type behind the pointer: https://doc.rust-lang.org/std/\
342 primitive.pointer.html#method.as_ref",
345 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
346 to invalid or uninitialized memory is undefined behavior",
350 let ty_span = match actual.kind() {
351 ty::Param(param_type) => Some(
352 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
354 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
357 if let Some(span) = ty_span {
361 "{item_kind} `{item_name}` not found for this {}",
362 actual.prefix_string(self.tcx)
367 if let SelfSource::MethodCall(rcvr_expr) = source {
368 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
372 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
373 let probe = self.lookup_probe(
378 ProbeScope::AllTraits,
384 let mut custom_span_label = false;
386 if !static_candidates.is_empty() {
388 "found the following associated functions; to be used as methods, \
389 functions must have a `self` parameter",
391 err.span_label(span, "this is an associated function, not a method");
392 custom_span_label = true;
394 if static_candidates.len() == 1 {
396 if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
397 // When the "method" is resolved through dereferencing, we really want the
398 // original type that has the associated function for accurate suggestions.
400 let ty = tcx.at(span).type_of(*impl_did);
401 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
402 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
403 // Use `actual` as it will have more `substs` filled in.
404 self.ty_to_value_string(actual.peel_refs())
406 _ => self.ty_to_value_string(ty.peel_refs()),
409 self.ty_to_value_string(actual.peel_refs())
411 if let SelfSource::MethodCall(expr) = source {
414 "use associated function syntax instead",
415 format!("{}::{}", ty_str, item_name),
416 Applicability::MachineApplicable,
419 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
422 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
423 } else if static_candidates.len() > 1 {
424 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
427 let mut bound_spans = vec![];
428 let mut restrict_type_params = false;
429 let mut unsatisfied_bounds = false;
430 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
431 let msg = "consider using `len` instead";
432 if let SelfSource::MethodCall(_expr) = source {
433 err.span_suggestion_short(
437 Applicability::MachineApplicable,
440 err.span_label(span, msg);
442 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
443 let iterator_trait = self.tcx.def_path_str(iterator_trait);
444 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
446 } else if !unsatisfied_predicates.is_empty() {
447 let mut type_params = FxHashMap::default();
449 // Pick out the list of unimplemented traits on the receiver.
450 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
451 let mut unimplemented_traits = FxHashMap::default();
452 let mut unimplemented_traits_only = true;
453 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
454 if let (ty::PredicateKind::Trait(p), Some(cause)) =
455 (predicate.kind().skip_binder(), cause.as_ref())
457 if p.trait_ref.self_ty() != rcvr_ty {
458 // This is necessary, not just to keep the errors clean, but also
459 // because our derived obligations can wind up with a trait ref that
460 // requires a different param_env to be correctly compared.
463 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
464 predicate.kind().rebind(p.trait_ref),
466 cause: cause.clone(),
467 param_env: self.param_env,
468 predicate: *predicate,
475 // Make sure that, if any traits other than the found ones were involved,
476 // we don't don't report an unimplemented trait.
477 // We don't want to say that `iter::Cloned` is not an iterator, just
478 // because of some non-Clone item being iterated over.
479 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
480 match predicate.kind().skip_binder() {
481 ty::PredicateKind::Trait(p)
482 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
484 unimplemented_traits_only = false;
490 let mut collect_type_param_suggestions =
491 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
492 // We don't care about regions here, so it's fine to skip the binder here.
493 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
494 (self_ty.kind(), parent_pred.kind().skip_binder())
496 let hir = self.tcx.hir();
497 let node = match p.trait_ref.self_ty().kind() {
499 // Account for `fn` items like in `issue-35677.rs` to
500 // suggest restricting its type params.
502 hir.body_owner(hir::BodyId { hir_id: self.body_id });
503 Some(hir.get(parent_body))
506 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
510 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
511 if let Some(g) = kind.generics() {
513 g.tail_span_for_predicate_suggestion(),
514 g.add_where_or_trailing_comma(),
518 .or_insert_with(FxHashSet::default)
519 .insert(obligation.to_owned());
524 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
526 "doesn't satisfy `{}`",
527 if obligation.len() > 50 { quiet } else { obligation }
529 match &self_ty.kind() {
530 // Point at the type that couldn't satisfy the bound.
532 bound_spans.push((self.tcx.def_span(def.did()), msg))
534 // Point at the trait object that couldn't satisfy the bound.
535 ty::Dynamic(preds, _, _) => {
536 for pred in preds.iter() {
537 match pred.skip_binder() {
538 ty::ExistentialPredicate::Trait(tr) => bound_spans
539 .push((self.tcx.def_span(tr.def_id), msg.clone())),
540 ty::ExistentialPredicate::Projection(_)
541 | ty::ExistentialPredicate::AutoTrait(_) => {}
545 // Point at the closure that couldn't satisfy the bound.
546 ty::Closure(def_id, _) => bound_spans.push((
547 tcx.def_span(*def_id),
548 format!("doesn't satisfy `{}`", quiet),
553 let mut format_pred = |pred: ty::Predicate<'tcx>| {
554 let bound_predicate = pred.kind();
555 match bound_predicate.skip_binder() {
556 ty::PredicateKind::Projection(pred) => {
557 let pred = bound_predicate.rebind(pred);
558 // `<Foo as Iterator>::Item = String`.
559 let projection_ty = pred.skip_binder().projection_ty;
561 let substs_with_infer_self = tcx.mk_substs(
562 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
563 .chain(projection_ty.substs.iter().skip(1)),
566 let quiet_projection_ty = ty::ProjectionTy {
567 substs: substs_with_infer_self,
568 item_def_id: projection_ty.item_def_id,
571 let term = pred.skip_binder().term;
573 let obligation = format!("{} = {}", projection_ty, term);
574 let quiet = format!("{} = {}", quiet_projection_ty, term);
576 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
577 Some((obligation, projection_ty.self_ty()))
579 ty::PredicateKind::Trait(poly_trait_ref) => {
580 let p = poly_trait_ref.trait_ref;
581 let self_ty = p.self_ty();
582 let path = p.print_only_trait_path();
583 let obligation = format!("{}: {}", self_ty, path);
584 let quiet = format!("_: {}", path);
585 bound_span_label(self_ty, &obligation, &quiet);
586 Some((obligation, self_ty))
592 // Find all the requirements that come from a local `impl` block.
593 let mut skip_list: FxHashSet<_> = Default::default();
594 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
595 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
597 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
598 .filter_map(|(p, parent, c)| match c.code() {
599 ObligationCauseCode::ImplDerivedObligation(data) => {
600 Some((&data.derived, p, parent, data.impl_def_id, data))
605 let parent_trait_ref = data.parent_trait_pred;
606 let path = parent_trait_ref.print_modifiers_and_trait_path();
607 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
608 let unsatisfied_msg = "unsatisfied trait bound introduced here";
610 "unsatisfied trait bound introduced in this `derive` macro";
611 match self.tcx.hir().get_if_local(impl_def_id) {
612 // Unmet obligation comes from a `derive` macro, point at it once to
613 // avoid multiple span labels pointing at the same place.
614 Some(Node::Item(hir::Item {
615 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
618 self_ty.span.ctxt().outer_expn_data().kind,
619 ExpnKind::Macro(MacroKind::Derive, _)
621 of_trait.as_ref().map(|t| t
627 Some(ExpnKind::Macro(MacroKind::Derive, _))
630 let span = self_ty.span.ctxt().outer_expn_data().call_site;
631 let mut spans: MultiSpan = span.into();
632 spans.push_span_label(span, derive_msg);
633 let entry = spanned_predicates.entry(spans);
634 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
637 // Unmet obligation coming from an `impl`.
638 Some(Node::Item(hir::Item {
640 hir::ItemKind::Impl(hir::Impl {
641 of_trait, self_ty, generics, ..
647 unsatisfied_predicates.iter().any(|(pred, _, _)| {
648 match pred.kind().skip_binder() {
649 ty::PredicateKind::Trait(pred) => {
651 == self.tcx.lang_items().sized_trait()
652 && pred.polarity == ty::ImplPolarity::Positive
657 for param in generics.params {
658 if param.span == cause.span && sized_pred {
659 let (sp, sugg) = match param.colon_span {
660 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
661 None => (param.span.shrink_to_hi(), ": ?Sized"),
663 err.span_suggestion_verbose(
665 "consider relaxing the type parameter's implicit \
668 Applicability::MachineApplicable,
672 if let Some(pred) = parent_p {
673 // Done to add the "doesn't satisfy" `span_label`.
674 let _ = format_pred(*pred);
677 let mut spans = if cause.span != *item_span {
678 let mut spans: MultiSpan = cause.span.into();
679 spans.push_span_label(cause.span, unsatisfied_msg);
682 let mut spans = Vec::with_capacity(2);
683 if let Some(trait_ref) = of_trait {
684 spans.push(trait_ref.path.span);
686 spans.push(self_ty.span);
689 if let Some(trait_ref) = of_trait {
690 spans.push_span_label(trait_ref.path.span, "");
692 spans.push_span_label(self_ty.span, "");
694 let entry = spanned_predicates.entry(spans);
695 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
697 Some(_) => unreachable!(),
701 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
702 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
703 for (span, (_path, _self_ty, preds)) in spanned_predicates {
704 let mut preds: Vec<_> = preds
706 .filter_map(|pred| format_pred(*pred))
707 .map(|(p, _)| format!("`{}`", p))
711 let msg = if let [pred] = &preds[..] {
712 format!("trait bound {} was not satisfied", pred)
715 "the following trait bounds were not satisfied:\n{}",
719 err.span_note(span, &msg);
720 unsatisfied_bounds = true;
723 // The requirements that didn't have an `impl` span to show.
724 let mut bound_list = unsatisfied_predicates
726 .filter_map(|(pred, parent_pred, _cause)| {
727 format_pred(*pred).map(|(p, self_ty)| {
728 collect_type_param_suggestions(self_ty, *pred, &p);
731 None => format!("`{}`", &p),
732 Some(parent_pred) => match format_pred(*parent_pred) {
733 None => format!("`{}`", &p),
734 Some((parent_p, _)) => {
735 collect_type_param_suggestions(
741 "`{}`\nwhich is required by `{}`",
751 .filter(|(_, pred)| !skip_list.contains(&pred))
754 .collect::<Vec<(usize, String)>>();
756 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
757 restrict_type_params = true;
758 // #74886: Sort here so that the output is always the same.
759 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
761 err.span_suggestion_verbose(
764 "consider restricting the type parameter{s} to satisfy the \
766 s = pluralize!(obligations.len())
768 format!("{} {}", add_where_or_comma, obligations.join(", ")),
769 Applicability::MaybeIncorrect,
773 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
774 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
775 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
777 if !bound_list.is_empty() || !skip_list.is_empty() {
778 let bound_list = bound_list
780 .map(|(_, path)| path)
783 let actual_prefix = actual.prefix_string(self.tcx);
784 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
785 let (primary_message, label) =
786 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
790 .map(|(_, (trait_ref, obligation))| {
791 if trait_ref.self_ty().references_error()
792 || actual.references_error()
797 let OnUnimplementedNote { message, label, .. } = self
799 .on_unimplemented_note(trait_ref, &obligation);
806 let primary_message = primary_message.unwrap_or_else(|| format!(
807 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
809 err.set_primary_message(&primary_message);
810 if let Some(label) = label {
811 custom_span_label = true;
812 err.span_label(span, label);
814 if !bound_list.is_empty() {
816 "the following trait bounds were not satisfied:\n{bound_list}"
819 self.suggest_derive(&mut err, &unsatisfied_predicates);
821 unsatisfied_bounds = true;
825 let label_span_not_found = |err: &mut Diagnostic| {
826 if unsatisfied_predicates.is_empty() {
827 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
828 let is_string_or_ref_str = match actual.kind() {
829 ty::Ref(_, ty, _) => {
833 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
836 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
839 if is_string_or_ref_str && item_name.name == sym::iter {
840 err.span_suggestion_verbose(
842 "because of the in-memory representation of `&str`, to obtain \
843 an `Iterator` over each of its codepoint use method `chars`",
845 Applicability::MachineApplicable,
848 if let ty::Adt(adt, _) = rcvr_ty.kind() {
849 let mut inherent_impls_candidate = self
851 .inherent_impls(adt.did())
855 if let Some(assoc) = self.associated_value(*def_id, item_name) {
856 // Check for both mode is the same so we avoid suggesting
857 // incorrect associated item.
858 match (mode, assoc.fn_has_self_parameter, source) {
859 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
860 // We check that the suggest type is actually
861 // different from the received one
862 // So we avoid suggestion method with Box<Self>
864 self.tcx.at(span).type_of(*def_id) != actual
865 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
867 (Mode::Path, false, _) => true,
874 .collect::<Vec<_>>();
875 if !inherent_impls_candidate.is_empty() {
876 inherent_impls_candidate.sort();
877 inherent_impls_candidate.dedup();
879 // number of type to shows at most.
880 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
881 let type_candidates = inherent_impls_candidate
885 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
889 let additional_types = if inherent_impls_candidate.len() > limit {
891 "\nand {} more types",
892 inherent_impls_candidate.len() - limit
898 "the {item_kind} was found for\n{}{}",
899 type_candidates, additional_types
904 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
908 // If the method name is the name of a field with a function or closure type,
909 // give a helping note that it has to be called as `(x.f)(...)`.
910 if let SelfSource::MethodCall(expr) = source {
911 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
912 && lev_candidate.is_none()
913 && !custom_span_label
915 label_span_not_found(&mut err);
917 } else if !custom_span_label {
918 label_span_not_found(&mut err);
921 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
922 // can't be called due to `typeof(expr): Clone` not holding.
923 if unsatisfied_predicates.is_empty() {
924 self.suggest_calling_method_on_field(&mut err, source, span, actual, item_name);
927 self.check_for_inner_self(&mut err, source, span, actual, item_name);
931 for (span, msg) in bound_spans.into_iter() {
932 err.span_label(span, &msg);
935 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
937 self.suggest_traits_to_import(
942 args.map(|(_, args)| args.len() + 1),
945 &unsatisfied_predicates,
951 // Don't emit a suggestion if we found an actual method
952 // that had unsatisfied trait bounds
953 if unsatisfied_predicates.is_empty() && actual.is_enum() {
954 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
955 if let Some(suggestion) = lev_distance::find_best_match_for_name(
956 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
962 "there is a variant with a similar name",
964 Applicability::MaybeIncorrect,
969 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
970 let msg = "remove this method call";
971 let mut fallback_span = true;
972 if let SelfSource::MethodCall(expr) = source {
974 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
975 if let Some(span) = call_expr.span.trim_start(expr.span) {
976 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
977 fallback_span = false;
981 err.span_label(span, msg);
983 } else if let Some(lev_candidate) = lev_candidate {
984 // Don't emit a suggestion if we found an actual method
985 // that had unsatisfied trait bounds
986 if unsatisfied_predicates.is_empty() {
987 let def_kind = lev_candidate.kind.as_def_kind();
988 // Methods are defined within the context of a struct and their first parameter is always self,
989 // which represents the instance of the struct the method is being called on
990 // Associated functions don’t take self as a parameter and
991 // they are not methods because they don’t have an instance of the struct to work with.
992 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
995 &format!("there is a method with a similar name",),
997 Applicability::MaybeIncorrect,
1000 err.span_suggestion(
1003 "there is {} {} with a similar name",
1005 def_kind.descr(lev_candidate.def_id),
1008 Applicability::MaybeIncorrect,
1014 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1019 MethodError::Ambiguity(mut sources) => {
1020 let mut err = struct_span_err!(
1024 "multiple applicable items in scope"
1026 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1028 report_candidates(span, &mut err, &mut sources, sugg_span);
1032 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1033 let kind = kind.descr(def_id);
1034 let mut err = struct_span_err!(
1038 "{} `{}` is private",
1042 err.span_label(item_name.span, &format!("private {}", kind));
1046 .span_if_local(def_id)
1047 .unwrap_or_else(|| self.tcx.def_span(def_id));
1048 err.span_label(sp, &format!("private {} defined here", kind));
1049 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1053 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1054 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1055 let mut err = self.sess().struct_span_err(span, &msg);
1056 err.span_label(bound_span, "this has a `Sized` requirement");
1057 if !candidates.is_empty() {
1059 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1060 add a `use` for {one_of_them}:",
1061 an = if candidates.len() == 1 { "an" } else { "" },
1062 s = pluralize!(candidates.len()),
1063 were = pluralize!("was", candidates.len()),
1064 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1066 self.suggest_use_candidates(&mut err, help, candidates);
1068 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1070 let trait_type = self.tcx.mk_ref(
1072 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1074 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1080 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1085 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1086 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1087 fn suggest_calling_field_as_fn(
1091 expr: &hir::Expr<'_>,
1093 err: &mut Diagnostic,
1096 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1097 ty::Adt(def, substs) if !def.is_enum() => {
1098 let variant = &def.non_enum_variant();
1099 tcx.find_field_index(item_name, variant).map(|index| {
1100 let field = &variant.fields[index];
1101 let field_ty = field.ty(tcx, substs);
1107 if let Some((field, field_ty)) = field_receiver {
1108 let scope = tcx.parent_module(self.body_id);
1109 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1112 if self.is_fn_ty(field_ty, span) {
1113 let expr_span = expr.span.to(item_name.span);
1114 err.multipart_suggestion(
1116 "to call the function stored in `{}`, \
1117 surround the field access with parentheses",
1121 (expr_span.shrink_to_lo(), '('.to_string()),
1122 (expr_span.shrink_to_hi(), ')'.to_string()),
1124 Applicability::MachineApplicable,
1127 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1129 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1130 err.span_suggestion(
1132 "remove the arguments",
1134 Applicability::MaybeIncorrect,
1140 let field_kind = if is_accessible { "field" } else { "private field" };
1141 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1147 /// Suggest possible range with adding parentheses, for example:
1148 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1149 fn suggest_wrapping_range_with_parens(
1153 source: SelfSource<'tcx>,
1158 if let SelfSource::MethodCall(expr) = source {
1159 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1160 if let Node::Expr(parent_expr) = parent {
1161 let lang_item = match parent_expr.kind {
1162 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1163 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1164 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1165 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1166 Some(LangItem::RangeToInclusive)
1170 ExprKind::Call(ref func, _) => match func.kind {
1171 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1172 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1173 Some(LangItem::RangeInclusiveStruct)
1180 if lang_item.is_none() {
1184 let span_included = match parent_expr.kind {
1185 hir::ExprKind::Struct(_, eps, _) => {
1186 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1188 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1189 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1197 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1199 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1201 let pick = self.probe_for_name(
1208 ProbeScope::AllTraits,
1211 let range_span = parent_expr.span.with_hi(expr.span.hi());
1212 tcx.sess.emit_err(errors::MissingParentheseInRange {
1214 ty_str: ty_str.to_string(),
1215 method_name: item_name.as_str().to_string(),
1216 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1217 func_name: item_name.name.as_str().to_string(),
1218 left: range_span.shrink_to_lo(),
1219 right: range_span.shrink_to_hi(),
1230 fn suggest_constraining_numerical_ty(
1234 source: SelfSource<'_>,
1240 let found_candidate = all_traits(self.tcx)
1242 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1243 let found_assoc = |ty: Ty<'tcx>| {
1244 simplify_type(tcx, ty, TreatParams::AsInfer)
1246 tcx.incoherent_impls(simp)
1248 .find_map(|&id| self.associated_value(id, item_name))
1252 let found_candidate = found_candidate
1253 || found_assoc(tcx.types.i8)
1254 || found_assoc(tcx.types.i16)
1255 || found_assoc(tcx.types.i32)
1256 || found_assoc(tcx.types.i64)
1257 || found_assoc(tcx.types.i128)
1258 || found_assoc(tcx.types.u8)
1259 || found_assoc(tcx.types.u16)
1260 || found_assoc(tcx.types.u32)
1261 || found_assoc(tcx.types.u64)
1262 || found_assoc(tcx.types.u128)
1263 || found_assoc(tcx.types.f32)
1264 || found_assoc(tcx.types.f32);
1266 && actual.is_numeric()
1267 && !actual.has_concrete_skeleton()
1268 && let SelfSource::MethodCall(expr) = source
1270 let mut err = struct_span_err!(
1274 "can't call {} `{}` on ambiguous numeric type `{}`",
1279 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1281 ExprKind::Lit(ref lit) => {
1286 .span_to_snippet(lit.span)
1287 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1289 // If this is a floating point literal that ends with '.',
1290 // get rid of it to stop this from becoming a member access.
1291 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1292 err.span_suggestion(
1295 "you must specify a concrete type for this numeric value, \
1299 format!("{snippet}_{concrete_type}"),
1300 Applicability::MaybeIncorrect,
1303 ExprKind::Path(QPath::Resolved(_, path)) => {
1305 if let hir::def::Res::Local(hir_id) = path.res {
1306 let span = tcx.hir().span(hir_id);
1307 let filename = tcx.sess.source_map().span_to_filename(span);
1310 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1312 "you must specify a type for this binding, like `{}`",
1316 match (filename, parent_node) {
1319 Node::Local(hir::Local {
1320 source: hir::LocalSource::Normal,
1325 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1326 err.span_suggestion(
1327 // account for `let x: _ = 42;`
1331 format!(": {concrete_type}"),
1332 Applicability::MaybeIncorrect,
1336 err.span_label(span, msg);
1349 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1350 fn suggest_calling_method_on_field(
1352 err: &mut Diagnostic,
1353 source: SelfSource<'tcx>,
1358 if let SelfSource::MethodCall(expr) = source
1359 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1360 && let Some((fields, substs)) =
1361 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1363 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1365 let lang_items = self.tcx.lang_items();
1366 let never_mention_traits = [
1367 lang_items.clone_trait(),
1368 lang_items.deref_trait(),
1369 lang_items.deref_mut_trait(),
1370 self.tcx.get_diagnostic_item(sym::AsRef),
1371 self.tcx.get_diagnostic_item(sym::AsMut),
1372 self.tcx.get_diagnostic_item(sym::Borrow),
1373 self.tcx.get_diagnostic_item(sym::BorrowMut),
1375 let candidate_fields: Vec<_> = fields
1376 .filter_map(|candidate_field| {
1377 self.check_for_nested_field_satisfying(
1385 ProbeScope::TraitsInScope,
1387 .map_or(false, |pick| {
1388 !never_mention_traits
1391 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1403 .map(|id| id.name.to_ident_string())
1404 .collect::<Vec<String>>()
1409 let len = candidate_fields.len();
1411 err.span_suggestions(
1412 item_name.span.shrink_to_lo(),
1414 "{} of the expressions' fields {} a method of the same name",
1415 if len > 1 { "some" } else { "one" },
1416 if len > 1 { "have" } else { "has" },
1418 candidate_fields.iter().map(|path| format!("{path}.")),
1419 Applicability::MaybeIncorrect,
1425 fn check_for_inner_self(
1427 err: &mut Diagnostic,
1428 source: SelfSource<'tcx>,
1434 let SelfSource::MethodCall(expr) = source else { return; };
1435 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1437 let ty::Adt(kind, substs) = actual.kind() else { return; };
1438 match kind.adt_kind() {
1439 ty::AdtKind::Enum => {
1440 let matching_variants: Vec<_> = kind
1443 .flat_map(|variant| {
1444 let [field] = &variant.fields[..] else { return None; };
1445 let field_ty = field.ty(tcx, substs);
1447 // Skip `_`, since that'll just lead to ambiguity.
1448 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1457 ProbeScope::TraitsInScope,
1460 .map(|pick| (variant, field, pick))
1464 let ret_ty_matches = |diagnostic_item| {
1465 if let Some(ret_ty) = self
1468 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1469 && let ty::Adt(kind, _) = ret_ty.kind()
1470 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1478 match &matching_variants[..] {
1479 [(_, field, pick)] => {
1480 let self_ty = field.ty(tcx, substs);
1482 tcx.def_span(pick.item.def_id),
1483 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1485 let (article, kind, variant, question) =
1486 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1487 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1488 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1489 ("an", "Option", "None", ret_ty_matches(sym::Option))
1494 err.span_suggestion_verbose(
1495 expr.span.shrink_to_hi(),
1497 "use the `?` operator to extract the `{self_ty}` value, propagating \
1498 {article} `{kind}::{variant}` value to the caller"
1501 Applicability::MachineApplicable,
1504 err.span_suggestion_verbose(
1505 expr.span.shrink_to_hi(),
1507 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1508 panicking if the value is {article} `{kind}::{variant}`"
1510 ".expect(\"REASON\")",
1511 Applicability::HasPlaceholders,
1515 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1519 // Target wrapper types - types that wrap or pretend to wrap another type,
1520 // perhaps this inner type is meant to be called?
1521 ty::AdtKind::Struct | ty::AdtKind::Union => {
1522 let [first] = ***substs else { return; };
1523 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1524 let Ok(pick) = self.lookup_probe(
1529 ProbeScope::TraitsInScope,
1532 let name = self.ty_to_value_string(actual);
1533 let inner_id = kind.did();
1534 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1535 pick.autoref_or_ptr_adjustment
1542 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1543 err.help("use `with` or `try_with` to access thread local storage");
1544 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1546 "if this `{name}` has been initialized, \
1547 use one of the `assume_init` methods to access the inner value"
1549 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1550 let (suggestion, borrow_kind, panic_if) = match mutable {
1551 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1552 Some(Mutability::Mut) => {
1553 (".borrow_mut()", "mutably borrow", "any borrows exist")
1557 err.span_suggestion_verbose(
1558 expr.span.shrink_to_hi(),
1560 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1561 panicking if {panic_if}"
1564 Applicability::MaybeIncorrect,
1566 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1567 err.span_suggestion_verbose(
1568 expr.span.shrink_to_hi(),
1570 "use `.lock().unwrap()` to borrow the `{ty}`, \
1571 blocking the current thread until it can be acquired"
1574 Applicability::MaybeIncorrect,
1576 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1577 let (suggestion, borrow_kind) = match mutable {
1578 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1579 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1582 err.span_suggestion_verbose(
1583 expr.span.shrink_to_hi(),
1585 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1586 blocking the current thread until it can be acquired"
1589 Applicability::MaybeIncorrect,
1596 tcx.def_span(pick.item.def_id),
1597 &format!("the method `{item_name}` exists on the type `{ty}`"),
1603 pub(crate) fn note_unmet_impls_on_type(
1605 err: &mut Diagnostic,
1606 errors: Vec<FulfillmentError<'tcx>>,
1608 let all_local_types_needing_impls =
1609 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1610 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1611 ty::Adt(def, _) => def.did().is_local(),
1616 let mut preds: Vec<_> = errors
1618 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1619 ty::PredicateKind::Trait(pred) => Some(pred),
1623 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1626 .filter_map(|pred| match pred.self_ty().kind() {
1627 ty::Adt(def, _) => Some(def.did()),
1630 .collect::<FxHashSet<_>>();
1631 let mut spans: MultiSpan = def_ids
1633 .filter_map(|def_id| {
1634 let span = self.tcx.def_span(*def_id);
1635 if span.is_dummy() { None } else { Some(span) }
1637 .collect::<Vec<_>>()
1640 for pred in &preds {
1641 match pred.self_ty().kind() {
1642 ty::Adt(def, _) if def.did().is_local() => {
1643 spans.push_span_label(
1644 self.tcx.def_span(def.did()),
1645 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1652 if all_local_types_needing_impls && spans.primary_span().is_some() {
1653 let msg = if preds.len() == 1 {
1655 "an implementation of `{}` might be missing for `{}`",
1656 preds[0].trait_ref.print_only_trait_path(),
1661 "the following type{} would have to `impl` {} required trait{} for this \
1662 operation to be valid",
1663 pluralize!(def_ids.len()),
1664 if def_ids.len() == 1 { "its" } else { "their" },
1665 pluralize!(preds.len()),
1668 err.span_note(spans, &msg);
1671 let preds: Vec<_> = errors
1673 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1675 self.suggest_derive(err, &preds);
1680 err: &mut Diagnostic,
1681 unsatisfied_predicates: &[(
1682 ty::Predicate<'tcx>,
1683 Option<ty::Predicate<'tcx>>,
1684 Option<ObligationCause<'tcx>>,
1687 let mut derives = Vec::<(String, Span, Symbol)>::new();
1688 let mut traits = Vec::<Span>::new();
1689 for (pred, _, _) in unsatisfied_predicates {
1690 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1691 let adt = match trait_pred.self_ty().ty_adt_def() {
1692 Some(adt) if adt.did().is_local() => adt,
1695 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1696 let can_derive = match diagnostic_name {
1697 sym::Default => !adt.is_enum(),
1705 | sym::Debug => true,
1709 let self_name = trait_pred.self_ty().to_string();
1710 let self_span = self.tcx.def_span(adt.did());
1711 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1712 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1714 if let Some(parent_diagnostic_name) =
1715 self.tcx.get_diagnostic_name(super_trait.def_id())
1720 parent_diagnostic_name,
1725 derives.push((self_name, self_span, diagnostic_name));
1727 traits.push(self.tcx.def_span(trait_pred.def_id()));
1730 traits.push(self.tcx.def_span(trait_pred.def_id()));
1739 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1740 for (self_name, self_span, trait_name) in derives.into_iter() {
1741 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1743 if last_self_name == &self_name {
1744 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1748 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1751 let len = traits.len();
1753 let span: MultiSpan = traits.into();
1756 &format!("the following trait{} must be implemented", pluralize!(len),),
1760 for (self_name, self_span, traits) in &derives_grouped {
1761 err.span_suggestion_verbose(
1762 self_span.shrink_to_lo(),
1763 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1764 format!("#[derive({})]\n", traits),
1765 Applicability::MaybeIncorrect,
1770 fn check_for_deref_method(
1772 err: &mut Diagnostic,
1773 self_source: SelfSource<'tcx>,
1777 let SelfSource::QPath(ty) = self_source else { return; };
1778 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1779 if let Ok(pick) = self.probe_for_name(
1786 ProbeScope::TraitsInScope,
1788 if deref_ty.is_suggestable(self.tcx, true)
1789 // If this method receives `&self`, then the provided
1790 // argument _should_ coerce, so it's valid to suggest
1791 // just changing the path.
1792 && pick.item.fn_has_self_parameter
1793 && let Some(self_ty) =
1794 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1797 let suggested_path = match deref_ty.kind() {
1806 | ty::Param(_) => format!("{deref_ty}"),
1807 _ => format!("<{deref_ty}>"),
1809 err.span_suggestion_verbose(
1811 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1813 Applicability::MaybeIncorrect,
1818 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1826 /// Print out the type for use in value namespace.
1827 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1829 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1830 _ => self.ty_to_string(ty),
1834 fn suggest_await_before_method(
1836 err: &mut Diagnostic,
1839 call: &hir::Expr<'_>,
1842 let output_ty = match self.get_impl_future_output_ty(ty) {
1843 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1846 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1847 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1849 err.span_suggestion_verbose(
1850 span.shrink_to_lo(),
1851 "consider `await`ing on the `Future` and calling the method on its `Output`",
1853 Applicability::MaybeIncorrect,
1858 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1859 let parent_map = self.tcx.visible_parent_map(());
1861 // Separate out candidates that must be imported with a glob, because they are named `_`
1862 // and cannot be referred with their identifier.
1863 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1864 if let Some(parent_did) = parent_map.get(trait_did) {
1865 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1866 if *parent_did != self.tcx.parent(*trait_did)
1869 .module_children(*parent_did)
1871 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1872 .all(|child| child.ident.name == kw::Underscore)
1881 let module_did = self.tcx.parent_module(self.body_id);
1882 let (module, _, _) = self.tcx.hir().get_module(module_did);
1883 let span = module.spans.inject_use_span;
1885 let path_strings = candidates.iter().map(|trait_did| {
1886 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1889 let glob_path_strings = globs.iter().map(|trait_did| {
1890 let parent_did = parent_map.get(trait_did).unwrap();
1892 "use {}::*; // trait {}\n",
1893 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1894 self.tcx.item_name(*trait_did),
1898 err.span_suggestions(
1901 path_strings.chain(glob_path_strings),
1902 Applicability::MaybeIncorrect,
1906 fn suggest_valid_traits(
1908 err: &mut Diagnostic,
1909 valid_out_of_scope_traits: Vec<DefId>,
1911 if !valid_out_of_scope_traits.is_empty() {
1912 let mut candidates = valid_out_of_scope_traits;
1916 // `TryFrom` and `FromIterator` have no methods
1917 let edition_fix = candidates
1919 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1922 err.help("items from traits can only be used if the trait is in scope");
1924 "the following {traits_are} implemented but not in scope; \
1925 perhaps add a `use` for {one_of_them}:",
1926 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1927 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1930 self.suggest_use_candidates(err, msg, candidates);
1931 if let Some(did) = edition_fix {
1933 "'{}' is included in the prelude starting in Edition 2021",
1934 with_crate_prefix!(self.tcx.def_path_str(did))
1944 fn suggest_traits_to_import(
1946 err: &mut Diagnostic,
1950 inputs_len: Option<usize>,
1951 source: SelfSource<'tcx>,
1952 valid_out_of_scope_traits: Vec<DefId>,
1953 unsatisfied_predicates: &[(
1954 ty::Predicate<'tcx>,
1955 Option<ty::Predicate<'tcx>>,
1956 Option<ObligationCause<'tcx>>,
1958 static_candidates: &[CandidateSource],
1959 unsatisfied_bounds: bool,
1961 let mut alt_rcvr_sugg = false;
1962 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1964 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
1965 span, item_name, rcvr_ty, rcvr
1968 self.tcx.lang_items().clone_trait(),
1969 self.tcx.lang_items().deref_trait(),
1970 self.tcx.lang_items().deref_mut_trait(),
1971 self.tcx.lang_items().drop_trait(),
1972 self.tcx.get_diagnostic_item(sym::AsRef),
1974 // Try alternative arbitrary self types that could fulfill this call.
1975 // FIXME: probe for all types that *could* be arbitrary self-types, not
1977 for (rcvr_ty, post) in &[
1979 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1980 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1982 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1984 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1985 // We point at the method, but we just skip the rest of the check for arbitrary
1986 // self types and rely on the suggestion to `use` the trait from
1987 // `suggest_valid_traits`.
1988 let did = Some(pick.item.container_id(self.tcx));
1989 let skip = skippable.contains(&did);
1990 if pick.autoderefs == 0 && !skip {
1992 pick.item.ident(self.tcx).span,
1993 &format!("the method is available for `{}` here", rcvr_ty),
1998 Err(MethodError::Ambiguity(_)) => {
1999 // If the method is defined (but ambiguous) for the receiver we have, it is also
2000 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2001 // the receiver, then it might disambiguate this method, but I think these
2002 // suggestions are generally misleading (see #94218).
2008 for (rcvr_ty, pre) in &[
2009 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2010 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2011 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2012 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2014 if let Some(new_rcvr_t) = *rcvr_ty
2015 && let Ok(pick) = self.lookup_probe(
2020 ProbeScope::AllTraits,
2023 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2024 let did = Some(pick.item.container_id(self.tcx));
2025 // We don't want to suggest a container type when the missing
2026 // method is `.clone()` or `.deref()` otherwise we'd suggest
2027 // `Arc::new(foo).clone()`, which is far from what the user wants.
2028 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2029 // implement the `AsRef` trait.
2030 let skip = skippable.contains(&did)
2031 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2032 || 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);
2033 // Make sure the method is defined for the *actual* receiver: we don't
2034 // want to treat `Box<Self>` as a receiver if it only works because of
2035 // an autoderef to `&self`
2036 if pick.autoderefs == 0 && !skip {
2038 pick.item.ident(self.tcx).span,
2039 &format!("the method is available for `{}` here", new_rcvr_t),
2041 err.multipart_suggestion(
2042 "consider wrapping the receiver expression with the \
2045 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2046 (rcvr.span.shrink_to_hi(), ")".to_string()),
2048 Applicability::MaybeIncorrect,
2050 // We don't care about the other suggestions.
2051 alt_rcvr_sugg = true;
2057 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2061 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2063 let mut arbitrary_rcvr = vec![];
2064 // There are no traits implemented, so lets suggest some traits to
2065 // implement, by finding ones that have the item name, and are
2066 // legal to implement.
2067 let mut candidates = all_traits(self.tcx)
2069 // Don't issue suggestions for unstable traits since they're
2070 // unlikely to be implementable anyway
2071 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2072 Some(attr) => attr.level.is_stable(),
2076 // Static candidates are already implemented, and known not to work
2077 // Do not suggest them again
2078 static_candidates.iter().all(|sc| match *sc {
2079 CandidateSource::Trait(def_id) => def_id != info.def_id,
2080 CandidateSource::Impl(def_id) => {
2081 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2086 // We approximate the coherence rules to only suggest
2087 // traits that are legal to implement by requiring that
2088 // either the type or trait is local. Multi-dispatch means
2089 // this isn't perfect (that is, there are cases when
2090 // implementing a trait would be legal but is rejected
2092 unsatisfied_predicates.iter().all(|(p, _, _)| {
2093 match p.kind().skip_binder() {
2094 // Hide traits if they are present in predicates as they can be fixed without
2095 // having to implement them.
2096 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2097 ty::PredicateKind::Projection(p) => {
2098 p.projection_ty.item_def_id == info.def_id
2102 }) && (type_is_local || info.def_id.is_local())
2104 .associated_value(info.def_id, item_name)
2106 if let ty::AssocKind::Fn = item.kind {
2110 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2111 if let Some(hir::Node::TraitItem(hir::TraitItem {
2112 kind: hir::TraitItemKind::Fn(fn_sig, method),
2114 })) = id.map(|id| self.tcx.hir().get(id))
2116 let self_first_arg = match method {
2117 hir::TraitFn::Required([ident, ..]) => {
2118 ident.name == kw::SelfLower
2120 hir::TraitFn::Provided(body_id) => {
2121 self.tcx.hir().body(*body_id).params.first().map_or(
2126 hir::PatKind::Binding(_, _, ident, _)
2127 if ident.name == kw::SelfLower
2135 if !fn_sig.decl.implicit_self.has_implicit_self()
2138 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2139 arbitrary_rcvr.push(ty.span);
2145 // We only want to suggest public or local traits (#45781).
2146 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2150 .collect::<Vec<_>>();
2151 for span in &arbitrary_rcvr {
2154 "the method might not be found because of this arbitrary self type",
2161 if !candidates.is_empty() {
2162 // Sort from most relevant to least relevant.
2163 candidates.sort_by(|a, b| a.cmp(b).reverse());
2166 let param_type = match rcvr_ty.kind() {
2167 ty::Param(param) => Some(param),
2168 ty::Ref(_, ty, _) => match ty.kind() {
2169 ty::Param(param) => Some(param),
2174 err.help(if param_type.is_some() {
2175 "items from traits can only be used if the type parameter is bounded by the trait"
2177 "items from traits can only be used if the trait is implemented and in scope"
2179 let candidates_len = candidates.len();
2180 let message = |action| {
2182 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2185 if candidates_len == 1 { "trait defines" } else { "traits define" },
2187 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2191 // Obtain the span for `param` and use it for a structured suggestion.
2192 if let Some(param) = param_type {
2193 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2194 let type_param = generics.type_param(param, self.tcx);
2195 let hir = self.tcx.hir();
2196 if let Some(def_id) = type_param.def_id.as_local() {
2197 let id = hir.local_def_id_to_hir_id(def_id);
2198 // Get the `hir::Param` to verify whether it already has any bounds.
2199 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2200 // instead we suggest `T: Foo + Bar` in that case.
2202 Node::GenericParam(param) => {
2208 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2209 let (sp, mut introducer) = if let Some(span) =
2210 ast_generics.bounds_span_for_suggestions(def_id)
2212 (span, Introducer::Plus)
2213 } else if let Some(colon_span) = param.colon_span {
2214 (colon_span.shrink_to_hi(), Introducer::Nothing)
2216 (param.span.shrink_to_hi(), Introducer::Colon)
2220 hir::GenericParamKind::Type { synthetic: true, .. },
2222 introducer = Introducer::Plus
2224 let trait_def_ids: FxHashSet<DefId> = ast_generics
2225 .bounds_for_param(def_id)
2226 .flat_map(|bp| bp.bounds.iter())
2227 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2229 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2230 err.span_suggestions(
2233 "restrict type parameter `{}` with",
2236 candidates.iter().map(|t| {
2240 Introducer::Plus => " +",
2241 Introducer::Colon => ":",
2242 Introducer::Nothing => "",
2244 self.tcx.def_path_str(t.def_id),
2247 Applicability::MaybeIncorrect,
2252 Node::Item(hir::Item {
2253 kind: hir::ItemKind::Trait(.., bounds, _),
2257 let (sp, sep, article) = if bounds.is_empty() {
2258 (ident.span.shrink_to_hi(), ":", "a")
2260 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2262 err.span_suggestions(
2264 &message(format!("add {} supertrait for", article)),
2265 candidates.iter().map(|t| {
2266 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2268 Applicability::MaybeIncorrect,
2277 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2278 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2279 // cases where a positive bound implies a negative impl.
2280 (candidates, Vec::new())
2281 } else if let Some(simp_rcvr_ty) =
2282 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2284 let mut potential_candidates = Vec::new();
2285 let mut explicitly_negative = Vec::new();
2286 for candidate in candidates {
2287 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2290 .all_impls(candidate.def_id)
2292 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2295 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2297 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2298 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2301 explicitly_negative.push(candidate);
2303 potential_candidates.push(candidate);
2306 (potential_candidates, explicitly_negative)
2308 // We don't know enough about `recv_ty` to make proper suggestions.
2309 (candidates, Vec::new())
2312 let action = if let Some(param) = param_type {
2313 format!("restrict type parameter `{}` with", param)
2315 // FIXME: it might only need to be imported into scope, not implemented.
2316 "implement".to_string()
2318 match &potential_candidates[..] {
2320 [trait_info] if trait_info.def_id.is_local() => {
2322 self.tcx.def_span(trait_info.def_id),
2324 "`{}` defines an item `{}`, perhaps you need to {} it",
2325 self.tcx.def_path_str(trait_info.def_id),
2332 let mut msg = message(action);
2333 for (i, trait_info) in trait_infos.iter().enumerate() {
2334 msg.push_str(&format!(
2335 "\ncandidate #{}: `{}`",
2337 self.tcx.def_path_str(trait_info.def_id),
2343 match &explicitly_negative[..] {
2347 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2348 self.tcx.def_path_str(trait_info.def_id),
2354 let mut msg = format!(
2355 "the following traits define an item `{}`, but are explicitly unimplemented:",
2358 for trait_info in trait_infos {
2359 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2367 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2368 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2369 pub(crate) fn suggest_else_fn_with_closure(
2371 err: &mut Diagnostic,
2372 expr: &hir::Expr<'_>,
2376 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2377 else { return false; };
2379 if !self.can_coerce(output, expected) {
2383 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2384 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2385 let hir::ExprKind::MethodCall(
2386 hir::PathSegment { ident: method_name, .. },
2390 ) = call_expr.kind &&
2391 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2392 let new_name = Ident {
2393 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2394 span: method_name.span,
2396 let probe = self.lookup_probe(
2401 ProbeScope::TraitsInScope,
2404 // check the method arguments number
2405 if let Ok(pick) = probe &&
2406 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2407 let fn_args = fn_sig.skip_binder().inputs() &&
2408 fn_args.len() == args.len() + 1 {
2409 err.span_suggestion_verbose(
2410 method_name.span.shrink_to_hi(),
2411 &format!("try calling `{}` instead", new_name.name.as_str()),
2413 Applicability::MaybeIncorrect,
2421 /// Checks whether there is a local type somewhere in the chain of
2422 /// autoderefs of `rcvr_ty`.
2423 fn type_derefs_to_local(
2427 source: SelfSource<'tcx>,
2429 fn is_local(ty: Ty<'_>) -> bool {
2431 ty::Adt(def, _) => def.did().is_local(),
2432 ty::Foreign(did) => did.is_local(),
2433 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2434 ty::Param(_) => true,
2436 // Everything else (primitive types, etc.) is effectively
2437 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2438 // the noise from these sort of types is usually just really
2439 // annoying, rather than any sort of help).
2444 // This occurs for UFCS desugaring of `T::method`, where there is no
2445 // receiver expression for the method call, and thus no autoderef.
2446 if let SelfSource::QPath(_) = source {
2447 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2450 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2454 #[derive(Copy, Clone, Debug)]
2455 pub enum SelfSource<'a> {
2456 QPath(&'a hir::Ty<'a>),
2457 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2460 #[derive(Copy, Clone)]
2461 pub struct TraitInfo {
2465 impl PartialEq for TraitInfo {
2466 fn eq(&self, other: &TraitInfo) -> bool {
2467 self.cmp(other) == Ordering::Equal
2470 impl Eq for TraitInfo {}
2471 impl PartialOrd for TraitInfo {
2472 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2473 Some(self.cmp(other))
2476 impl Ord for TraitInfo {
2477 fn cmp(&self, other: &TraitInfo) -> Ordering {
2478 // Local crates are more important than remote ones (local:
2479 // `cnum == 0`), and otherwise we throw in the defid for totality.
2481 let lhs = (other.def_id.krate, other.def_id);
2482 let rhs = (self.def_id.krate, self.def_id);
2487 /// Retrieves all traits in this crate and any dependent crates,
2488 /// and wraps them into `TraitInfo` for custom sorting.
2489 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2490 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2493 fn print_disambiguation_help<'tcx>(
2495 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2496 err: &mut Diagnostic,
2499 kind: ty::AssocKind,
2502 candidate: Option<usize>,
2503 source_map: &source_map::SourceMap,
2504 fn_has_self_parameter: bool,
2506 let mut applicability = Applicability::MachineApplicable;
2507 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2510 if rcvr_ty.is_region_ptr() {
2511 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2515 std::iter::once(receiver)
2517 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2518 applicability = Applicability::HasPlaceholders;
2521 .collect::<Vec<_>>()
2524 let trait_name = if !fn_has_self_parameter {
2525 format!("<{} as {}>", rcvr_ty, trait_name)
2529 (span, format!("{}::{}{}", trait_name, item_name, args))
2531 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2533 err.span_suggestion_verbose(
2536 "disambiguate the {} for {}",
2537 kind.as_def_kind().descr(def_id),
2538 if let Some(candidate) = candidate {
2539 format!("candidate #{}", candidate)
2541 "the candidate".to_string()