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::OnUnimplementedNote;
27 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
28 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
29 use rustc_trait_selection::traits::{
30 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
33 use std::cmp::Ordering;
36 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
37 use super::{CandidateSource, MethodError, NoMatchData};
39 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
43 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
44 // so we look for these beforehand.
45 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
46 // If it's not a simple function, look for things which implement `FnOnce`.
48 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
52 // This conditional prevents us from asking to call errors and unresolved types.
53 // It might seem that we can use `predicate_must_hold_modulo_regions`,
54 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
55 // type resolution always gives a "maybe" here.
56 if self.autoderef(span, ty).any(|(ty, _)| {
57 info!("check deref {:?} error", ty);
58 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
63 self.autoderef(span, ty).any(|(ty, _)| {
64 info!("check deref {:?} impl FnOnce", ty);
66 let fn_once_substs = tcx.mk_substs_trait(
69 .next_ty_var(TypeVariableOrigin {
70 kind: TypeVariableOriginKind::MiscVariable,
75 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
76 let poly_trait_ref = ty::Binder::dummy(trait_ref);
77 let obligation = Obligation::misc(
81 poly_trait_ref.without_const().to_predicate(tcx),
83 self.predicate_may_hold(&obligation)
90 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
91 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
94 pub fn report_method_error(
99 source: SelfSource<'tcx>,
100 error: MethodError<'tcx>,
101 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
102 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
103 // Avoid suggestions when we don't know what's going on.
104 if rcvr_ty.references_error() {
108 let report_candidates = |span: Span,
109 err: &mut Diagnostic,
110 sources: &mut Vec<CandidateSource>,
114 // Dynamic limit to avoid hiding just one candidate, which is silly.
115 let limit = if sources.len() == 5 { 5 } else { 4 };
117 for (idx, source) in sources.iter().take(limit).enumerate() {
119 CandidateSource::Impl(impl_did) => {
120 // Provide the best span we can. Use the item, if local to crate, else
121 // the impl, if local to crate (item may be defaulted), else nothing.
122 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
123 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
124 self.associated_value(impl_trait_ref.def_id, item_name)
129 let note_span = if item.def_id.is_local() {
130 Some(self.tcx.def_span(item.def_id))
131 } else if impl_did.is_local() {
132 Some(self.tcx.def_span(impl_did))
137 let impl_ty = self.tcx.at(span).type_of(impl_did);
139 let insertion = match self.tcx.impl_trait_ref(impl_did) {
140 None => String::new(),
141 Some(trait_ref) => format!(
142 " of the trait `{}`",
143 self.tcx.def_path_str(trait_ref.def_id)
147 let (note_str, idx) = if sources.len() > 1 {
150 "candidate #{} is defined in an impl{} for the type `{}`",
160 "the candidate is defined in an impl{} for the type `{}`",
166 if let Some(note_span) = note_span {
167 // We have a span pointing to the method. Show note with snippet.
168 err.span_note(note_span, ¬e_str);
172 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
173 let path = self.tcx.def_path_str(trait_ref.def_id);
175 let ty = match item.kind {
176 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
177 ty::AssocKind::Fn => self
183 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
187 print_disambiguation_help(
197 self.tcx.sess.source_map(),
198 item.fn_has_self_parameter,
202 CandidateSource::Trait(trait_did) => {
203 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
204 let item_span = self.tcx.def_span(item.def_id);
205 let idx = if sources.len() > 1 {
207 "candidate #{} is defined in the trait `{}`",
209 self.tcx.def_path_str(trait_did)
211 err.span_note(item_span, msg);
215 "the candidate is defined in the trait `{}`",
216 self.tcx.def_path_str(trait_did)
218 err.span_note(item_span, msg);
221 let path = self.tcx.def_path_str(trait_did);
222 print_disambiguation_help(
232 self.tcx.sess.source_map(),
233 item.fn_has_self_parameter,
238 if sources.len() > limit {
239 err.note(&format!("and {} others", sources.len() - limit));
243 let sugg_span = if let SelfSource::MethodCall(expr) = source {
244 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
245 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
251 MethodError::NoMatch(NoMatchData {
252 mut static_candidates,
253 unsatisfied_predicates,
260 let actual = self.resolve_vars_if_possible(rcvr_ty);
261 let ty_str = self.ty_to_string(actual);
262 let is_method = mode == Mode::MethodCall;
263 let item_kind = if is_method {
265 } else if actual.is_enum() {
266 "variant or associated item"
268 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
269 (Some(name), false) if name.is_lowercase() => "function or associated item",
270 (Some(_), false) => "associated item",
271 (Some(_), true) | (None, false) => "variant or associated item",
272 (None, true) => "variant",
276 if self.suggest_wrapping_range_with_parens(
277 tcx, actual, source, span, item_name, &ty_str,
278 ) || self.suggest_constraining_numerical_ty(
279 tcx, actual, source, span, item_kind, item_name, &ty_str,
284 span = item_name.span;
286 // Don't show generic arguments when the method can't be found in any implementation (#81576).
287 let mut ty_str_reported = ty_str.clone();
288 if let ty::Adt(_, generics) = actual.kind() {
289 if generics.len() > 0 {
290 let mut autoderef = self.autoderef(span, actual);
291 let candidate_found = autoderef.any(|(ty, _)| {
292 if let ty::Adt(adt_def, _) = ty.kind() {
294 .inherent_impls(adt_def.did())
296 .filter_map(|def_id| self.associated_value(*def_id, item_name))
303 let has_deref = autoderef.step_count() > 0;
304 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
305 if let Some((path_string, _)) = ty_str.split_once('<') {
306 ty_str_reported = path_string.to_string();
312 let mut err = struct_span_err!(
316 "no {} named `{}` found for {} `{}` in the current scope",
319 actual.prefix_string(self.tcx),
322 if actual.references_error() {
323 err.downgrade_to_delayed_bug();
326 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
327 self.suggest_await_before_method(
328 &mut err, item_name, actual, cal, span,
331 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
334 "you are looking for the module in `std`, not the primitive type",
336 Applicability::MachineApplicable,
339 if let ty::RawPtr(_) = &actual.kind() {
341 "try using `<*const T>::as_ref()` to get a reference to the \
342 type behind the pointer: https://doc.rust-lang.org/std/\
343 primitive.pointer.html#method.as_ref",
346 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
347 to invalid or uninitialized memory is undefined behavior",
351 let ty_span = match actual.kind() {
352 ty::Param(param_type) => Some(
353 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
355 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
358 if let Some(span) = ty_span {
362 "{item_kind} `{item_name}` not found for this {}",
363 actual.prefix_string(self.tcx)
368 if let SelfSource::MethodCall(rcvr_expr) = source {
369 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
373 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
374 let probe = self.lookup_probe(
379 ProbeScope::AllTraits,
385 let mut custom_span_label = false;
387 if !static_candidates.is_empty() {
389 "found the following associated functions; to be used as methods, \
390 functions must have a `self` parameter",
392 err.span_label(span, "this is an associated function, not a method");
393 custom_span_label = true;
395 if static_candidates.len() == 1 {
397 if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
398 // When the "method" is resolved through dereferencing, we really want the
399 // original type that has the associated function for accurate suggestions.
401 let ty = tcx.at(span).type_of(*impl_did);
402 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
403 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
404 // Use `actual` as it will have more `substs` filled in.
405 self.ty_to_value_string(actual.peel_refs())
407 _ => self.ty_to_value_string(ty.peel_refs()),
410 self.ty_to_value_string(actual.peel_refs())
412 if let SelfSource::MethodCall(expr) = source {
415 "use associated function syntax instead",
416 format!("{}::{}", ty_str, item_name),
417 Applicability::MachineApplicable,
420 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
423 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
424 } else if static_candidates.len() > 1 {
425 report_candidates(span, &mut err, &mut static_candidates, sugg_span);
428 let mut bound_spans = vec![];
429 let mut restrict_type_params = false;
430 let mut unsatisfied_bounds = false;
431 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
432 let msg = "consider using `len` instead";
433 if let SelfSource::MethodCall(_expr) = source {
434 err.span_suggestion_short(
438 Applicability::MachineApplicable,
441 err.span_label(span, msg);
443 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
444 let iterator_trait = self.tcx.def_path_str(iterator_trait);
445 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
447 } else if !unsatisfied_predicates.is_empty() {
448 let mut type_params = FxHashMap::default();
450 // Pick out the list of unimplemented traits on the receiver.
451 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
452 let mut unimplemented_traits = FxHashMap::default();
453 let mut unimplemented_traits_only = true;
454 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
455 if let (ty::PredicateKind::Trait(p), Some(cause)) =
456 (predicate.kind().skip_binder(), cause.as_ref())
458 if p.trait_ref.self_ty() != rcvr_ty {
459 // This is necessary, not just to keep the errors clean, but also
460 // because our derived obligations can wind up with a trait ref that
461 // requires a different param_env to be correctly compared.
464 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
465 predicate.kind().rebind(p.trait_ref),
467 cause: cause.clone(),
468 param_env: self.param_env,
469 predicate: *predicate,
476 // Make sure that, if any traits other than the found ones were involved,
477 // we don't don't report an unimplemented trait.
478 // We don't want to say that `iter::Cloned` is not an iterator, just
479 // because of some non-Clone item being iterated over.
480 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
481 match predicate.kind().skip_binder() {
482 ty::PredicateKind::Trait(p)
483 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
485 unimplemented_traits_only = false;
491 let mut collect_type_param_suggestions =
492 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
493 // We don't care about regions here, so it's fine to skip the binder here.
494 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
495 (self_ty.kind(), parent_pred.kind().skip_binder())
497 let hir = self.tcx.hir();
498 let node = match p.trait_ref.self_ty().kind() {
500 // Account for `fn` items like in `issue-35677.rs` to
501 // suggest restricting its type params.
503 hir.body_owner(hir::BodyId { hir_id: self.body_id });
504 Some(hir.get(parent_body))
507 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
511 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
512 if let Some(g) = kind.generics() {
514 g.tail_span_for_predicate_suggestion(),
515 g.add_where_or_trailing_comma(),
519 .or_insert_with(FxHashSet::default)
520 .insert(obligation.to_owned());
525 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
527 "doesn't satisfy `{}`",
528 if obligation.len() > 50 { quiet } else { obligation }
530 match &self_ty.kind() {
531 // Point at the type that couldn't satisfy the bound.
533 bound_spans.push((self.tcx.def_span(def.did()), msg))
535 // Point at the trait object that couldn't satisfy the bound.
536 ty::Dynamic(preds, _, _) => {
537 for pred in preds.iter() {
538 match pred.skip_binder() {
539 ty::ExistentialPredicate::Trait(tr) => bound_spans
540 .push((self.tcx.def_span(tr.def_id), msg.clone())),
541 ty::ExistentialPredicate::Projection(_)
542 | ty::ExistentialPredicate::AutoTrait(_) => {}
546 // Point at the closure that couldn't satisfy the bound.
547 ty::Closure(def_id, _) => bound_spans.push((
548 tcx.def_span(*def_id),
549 format!("doesn't satisfy `{}`", quiet),
554 let mut format_pred = |pred: ty::Predicate<'tcx>| {
555 let bound_predicate = pred.kind();
556 match bound_predicate.skip_binder() {
557 ty::PredicateKind::Projection(pred) => {
558 let pred = bound_predicate.rebind(pred);
559 // `<Foo as Iterator>::Item = String`.
560 let projection_ty = pred.skip_binder().projection_ty;
562 let substs_with_infer_self = tcx.mk_substs(
563 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
564 .chain(projection_ty.substs.iter().skip(1)),
567 let quiet_projection_ty = ty::ProjectionTy {
568 substs: substs_with_infer_self,
569 item_def_id: projection_ty.item_def_id,
572 let term = pred.skip_binder().term;
574 let obligation = format!("{} = {}", projection_ty, term);
575 let quiet = format!("{} = {}", quiet_projection_ty, term);
577 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
578 Some((obligation, projection_ty.self_ty()))
580 ty::PredicateKind::Trait(poly_trait_ref) => {
581 let p = poly_trait_ref.trait_ref;
582 let self_ty = p.self_ty();
583 let path = p.print_only_trait_path();
584 let obligation = format!("{}: {}", self_ty, path);
585 let quiet = format!("_: {}", path);
586 bound_span_label(self_ty, &obligation, &quiet);
587 Some((obligation, self_ty))
593 // Find all the requirements that come from a local `impl` block.
594 let mut skip_list: FxHashSet<_> = Default::default();
595 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
596 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
598 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
599 .filter_map(|(p, parent, c)| match c.code() {
600 ObligationCauseCode::ImplDerivedObligation(data) => {
601 Some((&data.derived, p, parent, data.impl_def_id, data))
606 let parent_trait_ref = data.parent_trait_pred;
607 let path = parent_trait_ref.print_modifiers_and_trait_path();
608 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
609 let unsatisfied_msg = "unsatisfied trait bound introduced here";
611 "unsatisfied trait bound introduced in this `derive` macro";
612 match self.tcx.hir().get_if_local(impl_def_id) {
613 // Unmet obligation comes from a `derive` macro, point at it once to
614 // avoid multiple span labels pointing at the same place.
615 Some(Node::Item(hir::Item {
616 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
619 self_ty.span.ctxt().outer_expn_data().kind,
620 ExpnKind::Macro(MacroKind::Derive, _)
622 of_trait.as_ref().map(|t| t
628 Some(ExpnKind::Macro(MacroKind::Derive, _))
631 let span = self_ty.span.ctxt().outer_expn_data().call_site;
632 let mut spans: MultiSpan = span.into();
633 spans.push_span_label(span, derive_msg);
634 let entry = spanned_predicates.entry(spans);
635 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
638 // Unmet obligation coming from an `impl`.
639 Some(Node::Item(hir::Item {
641 hir::ItemKind::Impl(hir::Impl {
642 of_trait, self_ty, generics, ..
648 unsatisfied_predicates.iter().any(|(pred, _, _)| {
649 match pred.kind().skip_binder() {
650 ty::PredicateKind::Trait(pred) => {
652 == self.tcx.lang_items().sized_trait()
653 && pred.polarity == ty::ImplPolarity::Positive
658 for param in generics.params {
659 if param.span == cause.span && sized_pred {
660 let (sp, sugg) = match param.colon_span {
661 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
662 None => (param.span.shrink_to_hi(), ": ?Sized"),
664 err.span_suggestion_verbose(
666 "consider relaxing the type parameter's implicit \
669 Applicability::MachineApplicable,
673 if let Some(pred) = parent_p {
674 // Done to add the "doesn't satisfy" `span_label`.
675 let _ = format_pred(*pred);
678 let mut spans = if cause.span != *item_span {
679 let mut spans: MultiSpan = cause.span.into();
680 spans.push_span_label(cause.span, unsatisfied_msg);
683 let mut spans = Vec::with_capacity(2);
684 if let Some(trait_ref) = of_trait {
685 spans.push(trait_ref.path.span);
687 spans.push(self_ty.span);
690 if let Some(trait_ref) = of_trait {
691 spans.push_span_label(trait_ref.path.span, "");
693 spans.push_span_label(self_ty.span, "");
695 let entry = spanned_predicates.entry(spans);
696 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
698 Some(_) => unreachable!(),
702 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
703 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
704 for (span, (_path, _self_ty, preds)) in spanned_predicates {
705 let mut preds: Vec<_> = preds
707 .filter_map(|pred| format_pred(*pred))
708 .map(|(p, _)| format!("`{}`", p))
712 let msg = if let [pred] = &preds[..] {
713 format!("trait bound {} was not satisfied", pred)
716 "the following trait bounds were not satisfied:\n{}",
720 err.span_note(span, &msg);
721 unsatisfied_bounds = true;
724 // The requirements that didn't have an `impl` span to show.
725 let mut bound_list = unsatisfied_predicates
727 .filter_map(|(pred, parent_pred, _cause)| {
728 format_pred(*pred).map(|(p, self_ty)| {
729 collect_type_param_suggestions(self_ty, *pred, &p);
732 None => format!("`{}`", &p),
733 Some(parent_pred) => match format_pred(*parent_pred) {
734 None => format!("`{}`", &p),
735 Some((parent_p, _)) => {
736 collect_type_param_suggestions(
742 "`{}`\nwhich is required by `{}`",
752 .filter(|(_, pred)| !skip_list.contains(&pred))
755 .collect::<Vec<(usize, String)>>();
757 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
758 restrict_type_params = true;
759 // #74886: Sort here so that the output is always the same.
760 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
762 err.span_suggestion_verbose(
765 "consider restricting the type parameter{s} to satisfy the \
767 s = pluralize!(obligations.len())
769 format!("{} {}", add_where_or_comma, obligations.join(", ")),
770 Applicability::MaybeIncorrect,
774 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
775 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
776 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
778 if !bound_list.is_empty() || !skip_list.is_empty() {
779 let bound_list = bound_list
781 .map(|(_, path)| path)
784 let actual_prefix = actual.prefix_string(self.tcx);
785 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
786 let (primary_message, label) =
787 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
791 .map(|(_, (trait_ref, obligation))| {
792 if trait_ref.self_ty().references_error()
793 || actual.references_error()
798 let OnUnimplementedNote { message, label, .. } = self
800 .on_unimplemented_note(trait_ref, &obligation);
807 let primary_message = primary_message.unwrap_or_else(|| format!(
808 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
810 err.set_primary_message(&primary_message);
811 if let Some(label) = label {
812 custom_span_label = true;
813 err.span_label(span, label);
815 if !bound_list.is_empty() {
817 "the following trait bounds were not satisfied:\n{bound_list}"
820 self.suggest_derive(&mut err, &unsatisfied_predicates);
822 unsatisfied_bounds = true;
826 let label_span_not_found = |err: &mut Diagnostic| {
827 if unsatisfied_predicates.is_empty() {
828 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
829 let is_string_or_ref_str = match actual.kind() {
830 ty::Ref(_, ty, _) => {
834 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did())
837 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did()),
840 if is_string_or_ref_str && item_name.name == sym::iter {
841 err.span_suggestion_verbose(
843 "because of the in-memory representation of `&str`, to obtain \
844 an `Iterator` over each of its codepoint use method `chars`",
846 Applicability::MachineApplicable,
849 if let ty::Adt(adt, _) = rcvr_ty.kind() {
850 let mut inherent_impls_candidate = self
852 .inherent_impls(adt.did())
856 if let Some(assoc) = self.associated_value(*def_id, item_name) {
857 // Check for both mode is the same so we avoid suggesting
858 // incorrect associated item.
859 match (mode, assoc.fn_has_self_parameter, source) {
860 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
861 // We check that the suggest type is actually
862 // different from the received one
863 // So we avoid suggestion method with Box<Self>
865 self.tcx.at(span).type_of(*def_id) != actual
866 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
868 (Mode::Path, false, _) => true,
875 .collect::<Vec<_>>();
876 if !inherent_impls_candidate.is_empty() {
877 inherent_impls_candidate.sort();
878 inherent_impls_candidate.dedup();
880 // number of type to shows at most.
881 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
882 let type_candidates = inherent_impls_candidate
886 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
890 let additional_types = if inherent_impls_candidate.len() > limit {
892 "\nand {} more types",
893 inherent_impls_candidate.len() - limit
899 "the {item_kind} was found for\n{}{}",
900 type_candidates, additional_types
905 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
909 // If the method name is the name of a field with a function or closure type,
910 // give a helping note that it has to be called as `(x.f)(...)`.
911 if let SelfSource::MethodCall(expr) = source {
912 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
913 && lev_candidate.is_none()
914 && !custom_span_label
916 label_span_not_found(&mut err);
918 } else if !custom_span_label {
919 label_span_not_found(&mut err);
922 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
923 // can't be called due to `typeof(expr): Clone` not holding.
924 if unsatisfied_predicates.is_empty() {
925 self.suggest_calling_method_on_field(&mut err, source, span, actual, item_name);
928 self.check_for_inner_self(&mut err, source, span, actual, item_name);
932 for (span, msg) in bound_spans.into_iter() {
933 err.span_label(span, &msg);
936 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
938 self.suggest_traits_to_import(
943 args.map(|(_, args)| args.len() + 1),
946 &unsatisfied_predicates,
952 // Don't emit a suggestion if we found an actual method
953 // that had unsatisfied trait bounds
954 if unsatisfied_predicates.is_empty() && actual.is_enum() {
955 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
956 if let Some(suggestion) = lev_distance::find_best_match_for_name(
957 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
963 "there is a variant with a similar name",
965 Applicability::MaybeIncorrect,
970 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
971 let msg = "remove this method call";
972 let mut fallback_span = true;
973 if let SelfSource::MethodCall(expr) = source {
975 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
976 if let Some(span) = call_expr.span.trim_start(expr.span) {
977 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
978 fallback_span = false;
982 err.span_label(span, msg);
984 } else if let Some(lev_candidate) = lev_candidate {
985 // Don't emit a suggestion if we found an actual method
986 // that had unsatisfied trait bounds
987 if unsatisfied_predicates.is_empty() {
988 let def_kind = lev_candidate.kind.as_def_kind();
989 // Methods are defined within the context of a struct and their first parameter is always self,
990 // which represents the instance of the struct the method is being called on
991 // Associated functions don’t take self as a parameter and
992 // they are not methods because they don’t have an instance of the struct to work with.
993 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
996 &format!("there is a method with a similar name",),
998 Applicability::MaybeIncorrect,
1001 err.span_suggestion(
1004 "there is {} {} with a similar name",
1006 def_kind.descr(lev_candidate.def_id),
1009 Applicability::MaybeIncorrect,
1015 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1020 MethodError::Ambiguity(mut sources) => {
1021 let mut err = struct_span_err!(
1025 "multiple applicable items in scope"
1027 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1029 report_candidates(span, &mut err, &mut sources, sugg_span);
1033 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1034 let kind = kind.descr(def_id);
1035 let mut err = struct_span_err!(
1039 "{} `{}` is private",
1043 err.span_label(item_name.span, &format!("private {}", kind));
1047 .span_if_local(def_id)
1048 .unwrap_or_else(|| self.tcx.def_span(def_id));
1049 err.span_label(sp, &format!("private {} defined here", kind));
1050 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1054 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1055 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1056 let mut err = self.sess().struct_span_err(span, &msg);
1057 err.span_label(bound_span, "this has a `Sized` requirement");
1058 if !candidates.is_empty() {
1060 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1061 add a `use` for {one_of_them}:",
1062 an = if candidates.len() == 1 { "an" } else { "" },
1063 s = pluralize!(candidates.len()),
1064 were = pluralize!("was", candidates.len()),
1065 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1067 self.suggest_use_candidates(&mut err, help, candidates);
1069 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1071 let trait_type = self.tcx.mk_ref(
1073 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1075 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1081 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1086 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1087 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1088 fn suggest_calling_field_as_fn(
1092 expr: &hir::Expr<'_>,
1094 err: &mut Diagnostic,
1097 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1098 ty::Adt(def, substs) if !def.is_enum() => {
1099 let variant = &def.non_enum_variant();
1100 tcx.find_field_index(item_name, variant).map(|index| {
1101 let field = &variant.fields[index];
1102 let field_ty = field.ty(tcx, substs);
1108 if let Some((field, field_ty)) = field_receiver {
1109 let scope = tcx.parent_module(self.body_id);
1110 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1113 if self.is_fn_ty(field_ty, span) {
1114 let expr_span = expr.span.to(item_name.span);
1115 err.multipart_suggestion(
1117 "to call the function stored in `{}`, \
1118 surround the field access with parentheses",
1122 (expr_span.shrink_to_lo(), '('.to_string()),
1123 (expr_span.shrink_to_hi(), ')'.to_string()),
1125 Applicability::MachineApplicable,
1128 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1130 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1131 err.span_suggestion(
1133 "remove the arguments",
1135 Applicability::MaybeIncorrect,
1141 let field_kind = if is_accessible { "field" } else { "private field" };
1142 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1148 /// Suggest possible range with adding parentheses, for example:
1149 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1150 fn suggest_wrapping_range_with_parens(
1154 source: SelfSource<'tcx>,
1159 if let SelfSource::MethodCall(expr) = source {
1160 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1161 if let Node::Expr(parent_expr) = parent {
1162 let lang_item = match parent_expr.kind {
1163 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1164 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1165 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1166 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1167 Some(LangItem::RangeToInclusive)
1171 ExprKind::Call(ref func, _) => match func.kind {
1172 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1173 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1174 Some(LangItem::RangeInclusiveStruct)
1181 if lang_item.is_none() {
1185 let span_included = match parent_expr.kind {
1186 hir::ExprKind::Struct(_, eps, _) => {
1187 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1189 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1190 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1198 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1200 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1202 let pick = self.probe_for_name(
1209 ProbeScope::AllTraits,
1212 let range_span = parent_expr.span.with_hi(expr.span.hi());
1213 tcx.sess.emit_err(errors::MissingParentheseInRange {
1215 ty_str: ty_str.to_string(),
1216 method_name: item_name.as_str().to_string(),
1217 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1218 func_name: item_name.name.as_str().to_string(),
1219 left: range_span.shrink_to_lo(),
1220 right: range_span.shrink_to_hi(),
1231 fn suggest_constraining_numerical_ty(
1235 source: SelfSource<'_>,
1241 let found_candidate = all_traits(self.tcx)
1243 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1244 let found_assoc = |ty: Ty<'tcx>| {
1245 simplify_type(tcx, ty, TreatParams::AsInfer)
1247 tcx.incoherent_impls(simp)
1249 .find_map(|&id| self.associated_value(id, item_name))
1253 let found_candidate = found_candidate
1254 || found_assoc(tcx.types.i8)
1255 || found_assoc(tcx.types.i16)
1256 || found_assoc(tcx.types.i32)
1257 || found_assoc(tcx.types.i64)
1258 || found_assoc(tcx.types.i128)
1259 || found_assoc(tcx.types.u8)
1260 || found_assoc(tcx.types.u16)
1261 || found_assoc(tcx.types.u32)
1262 || found_assoc(tcx.types.u64)
1263 || found_assoc(tcx.types.u128)
1264 || found_assoc(tcx.types.f32)
1265 || found_assoc(tcx.types.f32);
1267 && actual.is_numeric()
1268 && !actual.has_concrete_skeleton()
1269 && let SelfSource::MethodCall(expr) = source
1271 let mut err = struct_span_err!(
1275 "can't call {} `{}` on ambiguous numeric type `{}`",
1280 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1282 ExprKind::Lit(ref lit) => {
1287 .span_to_snippet(lit.span)
1288 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1290 // If this is a floating point literal that ends with '.',
1291 // get rid of it to stop this from becoming a member access.
1292 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1293 err.span_suggestion(
1296 "you must specify a concrete type for this numeric value, \
1300 format!("{snippet}_{concrete_type}"),
1301 Applicability::MaybeIncorrect,
1304 ExprKind::Path(QPath::Resolved(_, path)) => {
1306 if let hir::def::Res::Local(hir_id) = path.res {
1307 let span = tcx.hir().span(hir_id);
1308 let filename = tcx.sess.source_map().span_to_filename(span);
1311 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1313 "you must specify a type for this binding, like `{}`",
1317 match (filename, parent_node) {
1320 Node::Local(hir::Local {
1321 source: hir::LocalSource::Normal,
1326 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1327 err.span_suggestion(
1328 // account for `let x: _ = 42;`
1332 format!(": {concrete_type}"),
1333 Applicability::MaybeIncorrect,
1337 err.span_label(span, msg);
1350 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1351 fn suggest_calling_method_on_field(
1353 err: &mut Diagnostic,
1354 source: SelfSource<'tcx>,
1359 if let SelfSource::MethodCall(expr) = source
1360 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1361 && let Some((fields, substs)) =
1362 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1364 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1366 let lang_items = self.tcx.lang_items();
1367 let never_mention_traits = [
1368 lang_items.clone_trait(),
1369 lang_items.deref_trait(),
1370 lang_items.deref_mut_trait(),
1371 self.tcx.get_diagnostic_item(sym::AsRef),
1372 self.tcx.get_diagnostic_item(sym::AsMut),
1373 self.tcx.get_diagnostic_item(sym::Borrow),
1374 self.tcx.get_diagnostic_item(sym::BorrowMut),
1376 let candidate_fields: Vec<_> = fields
1377 .filter_map(|candidate_field| {
1378 self.check_for_nested_field_satisfying(
1386 ProbeScope::TraitsInScope,
1388 .map_or(false, |pick| {
1389 !never_mention_traits
1392 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1404 .map(|id| id.name.to_ident_string())
1405 .collect::<Vec<String>>()
1410 let len = candidate_fields.len();
1412 err.span_suggestions(
1413 item_name.span.shrink_to_lo(),
1415 "{} of the expressions' fields {} a method of the same name",
1416 if len > 1 { "some" } else { "one" },
1417 if len > 1 { "have" } else { "has" },
1419 candidate_fields.iter().map(|path| format!("{path}.")),
1420 Applicability::MaybeIncorrect,
1426 fn check_for_inner_self(
1428 err: &mut Diagnostic,
1429 source: SelfSource<'tcx>,
1435 let SelfSource::MethodCall(expr) = source else { return; };
1436 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1438 let ty::Adt(kind, substs) = actual.kind() else { return; };
1439 match kind.adt_kind() {
1440 ty::AdtKind::Enum => {
1441 let matching_variants: Vec<_> = kind
1444 .flat_map(|variant| {
1445 let [field] = &variant.fields[..] else { return None; };
1446 let field_ty = field.ty(tcx, substs);
1448 // Skip `_`, since that'll just lead to ambiguity.
1449 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1458 ProbeScope::TraitsInScope,
1461 .map(|pick| (variant, field, pick))
1465 let ret_ty_matches = |diagnostic_item| {
1466 if let Some(ret_ty) = self
1469 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1470 && let ty::Adt(kind, _) = ret_ty.kind()
1471 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1479 match &matching_variants[..] {
1480 [(_, field, pick)] => {
1481 let self_ty = field.ty(tcx, substs);
1483 tcx.def_span(pick.item.def_id),
1484 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1486 let (article, kind, variant, question) =
1487 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1488 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1489 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1490 ("an", "Option", "None", ret_ty_matches(sym::Option))
1495 err.span_suggestion_verbose(
1496 expr.span.shrink_to_hi(),
1498 "use the `?` operator to extract the `{self_ty}` value, propagating \
1499 {article} `{kind}::{variant}` value to the caller"
1502 Applicability::MachineApplicable,
1505 err.span_suggestion_verbose(
1506 expr.span.shrink_to_hi(),
1508 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1509 panicking if the value is {article} `{kind}::{variant}`"
1511 ".expect(\"REASON\")",
1512 Applicability::HasPlaceholders,
1516 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1520 // Target wrapper types - types that wrap or pretend to wrap another type,
1521 // perhaps this inner type is meant to be called?
1522 ty::AdtKind::Struct | ty::AdtKind::Union => {
1523 let [first] = ***substs else { return; };
1524 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1525 let Ok(pick) = self.lookup_probe(
1530 ProbeScope::TraitsInScope,
1533 let name = self.ty_to_value_string(actual);
1534 let inner_id = kind.did();
1535 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1536 pick.autoref_or_ptr_adjustment
1543 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1544 err.help("use `with` or `try_with` to access thread local storage");
1545 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1547 "if this `{name}` has been initialized, \
1548 use one of the `assume_init` methods to access the inner value"
1550 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1551 let (suggestion, borrow_kind, panic_if) = match mutable {
1552 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1553 Some(Mutability::Mut) => {
1554 (".borrow_mut()", "mutably borrow", "any borrows exist")
1558 err.span_suggestion_verbose(
1559 expr.span.shrink_to_hi(),
1561 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1562 panicking if {panic_if}"
1565 Applicability::MaybeIncorrect,
1567 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1568 err.span_suggestion_verbose(
1569 expr.span.shrink_to_hi(),
1571 "use `.lock().unwrap()` to borrow the `{ty}`, \
1572 blocking the current thread until it can be acquired"
1575 Applicability::MaybeIncorrect,
1577 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1578 let (suggestion, borrow_kind) = match mutable {
1579 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1580 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1583 err.span_suggestion_verbose(
1584 expr.span.shrink_to_hi(),
1586 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1587 blocking the current thread until it can be acquired"
1590 Applicability::MaybeIncorrect,
1597 tcx.def_span(pick.item.def_id),
1598 &format!("the method `{item_name}` exists on the type `{ty}`"),
1604 pub(crate) fn note_unmet_impls_on_type(
1606 err: &mut Diagnostic,
1607 errors: Vec<FulfillmentError<'tcx>>,
1609 let all_local_types_needing_impls =
1610 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1611 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1612 ty::Adt(def, _) => def.did().is_local(),
1617 let mut preds: Vec<_> = errors
1619 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1620 ty::PredicateKind::Trait(pred) => Some(pred),
1624 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1627 .filter_map(|pred| match pred.self_ty().kind() {
1628 ty::Adt(def, _) => Some(def.did()),
1631 .collect::<FxHashSet<_>>();
1632 let mut spans: MultiSpan = def_ids
1634 .filter_map(|def_id| {
1635 let span = self.tcx.def_span(*def_id);
1636 if span.is_dummy() { None } else { Some(span) }
1638 .collect::<Vec<_>>()
1641 for pred in &preds {
1642 match pred.self_ty().kind() {
1643 ty::Adt(def, _) if def.did().is_local() => {
1644 spans.push_span_label(
1645 self.tcx.def_span(def.did()),
1646 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1653 if all_local_types_needing_impls && spans.primary_span().is_some() {
1654 let msg = if preds.len() == 1 {
1656 "an implementation of `{}` might be missing for `{}`",
1657 preds[0].trait_ref.print_only_trait_path(),
1662 "the following type{} would have to `impl` {} required trait{} for this \
1663 operation to be valid",
1664 pluralize!(def_ids.len()),
1665 if def_ids.len() == 1 { "its" } else { "their" },
1666 pluralize!(preds.len()),
1669 err.span_note(spans, &msg);
1672 let preds: Vec<_> = errors
1674 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1676 self.suggest_derive(err, &preds);
1681 err: &mut Diagnostic,
1682 unsatisfied_predicates: &[(
1683 ty::Predicate<'tcx>,
1684 Option<ty::Predicate<'tcx>>,
1685 Option<ObligationCause<'tcx>>,
1688 let mut derives = Vec::<(String, Span, Symbol)>::new();
1689 let mut traits = Vec::<Span>::new();
1690 for (pred, _, _) in unsatisfied_predicates {
1691 let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue };
1692 let adt = match trait_pred.self_ty().ty_adt_def() {
1693 Some(adt) if adt.did().is_local() => adt,
1696 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1697 let can_derive = match diagnostic_name {
1698 sym::Default => !adt.is_enum(),
1706 | sym::Debug => true,
1710 let self_name = trait_pred.self_ty().to_string();
1711 let self_span = self.tcx.def_span(adt.did());
1712 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1713 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1715 if let Some(parent_diagnostic_name) =
1716 self.tcx.get_diagnostic_name(super_trait.def_id())
1721 parent_diagnostic_name,
1726 derives.push((self_name, self_span, diagnostic_name));
1728 traits.push(self.tcx.def_span(trait_pred.def_id()));
1731 traits.push(self.tcx.def_span(trait_pred.def_id()));
1740 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1741 for (self_name, self_span, trait_name) in derives.into_iter() {
1742 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1744 if last_self_name == &self_name {
1745 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1749 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1752 let len = traits.len();
1754 let span: MultiSpan = traits.into();
1757 &format!("the following trait{} must be implemented", pluralize!(len),),
1761 for (self_name, self_span, traits) in &derives_grouped {
1762 err.span_suggestion_verbose(
1763 self_span.shrink_to_lo(),
1764 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1765 format!("#[derive({})]\n", traits),
1766 Applicability::MaybeIncorrect,
1771 fn check_for_deref_method(
1773 err: &mut Diagnostic,
1774 self_source: SelfSource<'tcx>,
1778 let SelfSource::QPath(ty) = self_source else { return; };
1779 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1780 if let Ok(pick) = self.probe_for_name(
1787 ProbeScope::TraitsInScope,
1789 if deref_ty.is_suggestable(self.tcx, true)
1790 // If this method receives `&self`, then the provided
1791 // argument _should_ coerce, so it's valid to suggest
1792 // just changing the path.
1793 && pick.item.fn_has_self_parameter
1794 && let Some(self_ty) =
1795 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1798 let suggested_path = match deref_ty.kind() {
1807 | ty::Param(_) => format!("{deref_ty}"),
1808 _ => format!("<{deref_ty}>"),
1810 err.span_suggestion_verbose(
1812 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1814 Applicability::MaybeIncorrect,
1819 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1827 /// Print out the type for use in value namespace.
1828 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1830 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
1831 _ => self.ty_to_string(ty),
1835 fn suggest_await_before_method(
1837 err: &mut Diagnostic,
1840 call: &hir::Expr<'_>,
1843 let output_ty = match self.get_impl_future_output_ty(ty) {
1844 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1847 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1848 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1850 err.span_suggestion_verbose(
1851 span.shrink_to_lo(),
1852 "consider `await`ing on the `Future` and calling the method on its `Output`",
1854 Applicability::MaybeIncorrect,
1859 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
1860 let parent_map = self.tcx.visible_parent_map(());
1862 // Separate out candidates that must be imported with a glob, because they are named `_`
1863 // and cannot be referred with their identifier.
1864 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1865 if let Some(parent_did) = parent_map.get(trait_did) {
1866 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1867 if *parent_did != self.tcx.parent(*trait_did)
1870 .module_children(*parent_did)
1872 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1873 .all(|child| child.ident.name == kw::Underscore)
1882 let module_did = self.tcx.parent_module(self.body_id);
1883 let (module, _, _) = self.tcx.hir().get_module(module_did);
1884 let span = module.spans.inject_use_span;
1886 let path_strings = candidates.iter().map(|trait_did| {
1887 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
1890 let glob_path_strings = globs.iter().map(|trait_did| {
1891 let parent_did = parent_map.get(trait_did).unwrap();
1893 "use {}::*; // trait {}\n",
1894 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
1895 self.tcx.item_name(*trait_did),
1899 err.span_suggestions(
1902 path_strings.chain(glob_path_strings),
1903 Applicability::MaybeIncorrect,
1907 fn suggest_valid_traits(
1909 err: &mut Diagnostic,
1910 valid_out_of_scope_traits: Vec<DefId>,
1912 if !valid_out_of_scope_traits.is_empty() {
1913 let mut candidates = valid_out_of_scope_traits;
1917 // `TryFrom` and `FromIterator` have no methods
1918 let edition_fix = candidates
1920 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1923 err.help("items from traits can only be used if the trait is in scope");
1925 "the following {traits_are} implemented but not in scope; \
1926 perhaps add a `use` for {one_of_them}:",
1927 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1928 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1931 self.suggest_use_candidates(err, msg, candidates);
1932 if let Some(did) = edition_fix {
1934 "'{}' is included in the prelude starting in Edition 2021",
1935 with_crate_prefix!(self.tcx.def_path_str(did))
1945 fn suggest_traits_to_import(
1947 err: &mut Diagnostic,
1951 inputs_len: Option<usize>,
1952 source: SelfSource<'tcx>,
1953 valid_out_of_scope_traits: Vec<DefId>,
1954 unsatisfied_predicates: &[(
1955 ty::Predicate<'tcx>,
1956 Option<ty::Predicate<'tcx>>,
1957 Option<ObligationCause<'tcx>>,
1959 static_candidates: &[CandidateSource],
1960 unsatisfied_bounds: bool,
1962 let mut alt_rcvr_sugg = false;
1963 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1965 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
1966 span, item_name, rcvr_ty, rcvr
1969 self.tcx.lang_items().clone_trait(),
1970 self.tcx.lang_items().deref_trait(),
1971 self.tcx.lang_items().deref_mut_trait(),
1972 self.tcx.lang_items().drop_trait(),
1973 self.tcx.get_diagnostic_item(sym::AsRef),
1975 // Try alternative arbitrary self types that could fulfill this call.
1976 // FIXME: probe for all types that *could* be arbitrary self-types, not
1978 for (rcvr_ty, post) in &[
1980 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1981 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1983 match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
1985 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1986 // We point at the method, but we just skip the rest of the check for arbitrary
1987 // self types and rely on the suggestion to `use` the trait from
1988 // `suggest_valid_traits`.
1989 let did = Some(pick.item.container_id(self.tcx));
1990 let skip = skippable.contains(&did);
1991 if pick.autoderefs == 0 && !skip {
1993 pick.item.ident(self.tcx).span,
1994 &format!("the method is available for `{}` here", rcvr_ty),
1999 Err(MethodError::Ambiguity(_)) => {
2000 // If the method is defined (but ambiguous) for the receiver we have, it is also
2001 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2002 // the receiver, then it might disambiguate this method, but I think these
2003 // suggestions are generally misleading (see #94218).
2009 for (rcvr_ty, pre) in &[
2010 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2011 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2012 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2013 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2015 if let Some(new_rcvr_t) = *rcvr_ty
2016 && let Ok(pick) = self.lookup_probe(
2021 ProbeScope::AllTraits,
2024 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2025 let did = Some(pick.item.container_id(self.tcx));
2026 // We don't want to suggest a container type when the missing
2027 // method is `.clone()` or `.deref()` otherwise we'd suggest
2028 // `Arc::new(foo).clone()`, which is far from what the user wants.
2029 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2030 // implement the `AsRef` trait.
2031 let skip = skippable.contains(&did)
2032 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2033 || 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);
2034 // Make sure the method is defined for the *actual* receiver: we don't
2035 // want to treat `Box<Self>` as a receiver if it only works because of
2036 // an autoderef to `&self`
2037 if pick.autoderefs == 0 && !skip {
2039 pick.item.ident(self.tcx).span,
2040 &format!("the method is available for `{}` here", new_rcvr_t),
2042 err.multipart_suggestion(
2043 "consider wrapping the receiver expression with the \
2046 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2047 (rcvr.span.shrink_to_hi(), ")".to_string()),
2049 Applicability::MaybeIncorrect,
2051 // We don't care about the other suggestions.
2052 alt_rcvr_sugg = true;
2058 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2062 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2064 let mut arbitrary_rcvr = vec![];
2065 // There are no traits implemented, so lets suggest some traits to
2066 // implement, by finding ones that have the item name, and are
2067 // legal to implement.
2068 let mut candidates = all_traits(self.tcx)
2070 // Don't issue suggestions for unstable traits since they're
2071 // unlikely to be implementable anyway
2072 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2073 Some(attr) => attr.level.is_stable(),
2077 // Static candidates are already implemented, and known not to work
2078 // Do not suggest them again
2079 static_candidates.iter().all(|sc| match *sc {
2080 CandidateSource::Trait(def_id) => def_id != info.def_id,
2081 CandidateSource::Impl(def_id) => {
2082 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2087 // We approximate the coherence rules to only suggest
2088 // traits that are legal to implement by requiring that
2089 // either the type or trait is local. Multi-dispatch means
2090 // this isn't perfect (that is, there are cases when
2091 // implementing a trait would be legal but is rejected
2093 unsatisfied_predicates.iter().all(|(p, _, _)| {
2094 match p.kind().skip_binder() {
2095 // Hide traits if they are present in predicates as they can be fixed without
2096 // having to implement them.
2097 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
2098 ty::PredicateKind::Projection(p) => {
2099 p.projection_ty.item_def_id == info.def_id
2103 }) && (type_is_local || info.def_id.is_local())
2105 .associated_value(info.def_id, item_name)
2107 if let ty::AssocKind::Fn = item.kind {
2111 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2112 if let Some(hir::Node::TraitItem(hir::TraitItem {
2113 kind: hir::TraitItemKind::Fn(fn_sig, method),
2115 })) = id.map(|id| self.tcx.hir().get(id))
2117 let self_first_arg = match method {
2118 hir::TraitFn::Required([ident, ..]) => {
2119 ident.name == kw::SelfLower
2121 hir::TraitFn::Provided(body_id) => {
2122 self.tcx.hir().body(*body_id).params.first().map_or(
2127 hir::PatKind::Binding(_, _, ident, _)
2128 if ident.name == kw::SelfLower
2136 if !fn_sig.decl.implicit_self.has_implicit_self()
2139 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2140 arbitrary_rcvr.push(ty.span);
2146 // We only want to suggest public or local traits (#45781).
2147 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2151 .collect::<Vec<_>>();
2152 for span in &arbitrary_rcvr {
2155 "the method might not be found because of this arbitrary self type",
2162 if !candidates.is_empty() {
2163 // Sort from most relevant to least relevant.
2164 candidates.sort_by(|a, b| a.cmp(b).reverse());
2167 let param_type = match rcvr_ty.kind() {
2168 ty::Param(param) => Some(param),
2169 ty::Ref(_, ty, _) => match ty.kind() {
2170 ty::Param(param) => Some(param),
2175 err.help(if param_type.is_some() {
2176 "items from traits can only be used if the type parameter is bounded by the trait"
2178 "items from traits can only be used if the trait is implemented and in scope"
2180 let candidates_len = candidates.len();
2181 let message = |action| {
2183 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2186 if candidates_len == 1 { "trait defines" } else { "traits define" },
2188 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2192 // Obtain the span for `param` and use it for a structured suggestion.
2193 if let Some(param) = param_type {
2194 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2195 let type_param = generics.type_param(param, self.tcx);
2196 let hir = self.tcx.hir();
2197 if let Some(def_id) = type_param.def_id.as_local() {
2198 let id = hir.local_def_id_to_hir_id(def_id);
2199 // Get the `hir::Param` to verify whether it already has any bounds.
2200 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2201 // instead we suggest `T: Foo + Bar` in that case.
2203 Node::GenericParam(param) => {
2209 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2210 let (sp, mut introducer) = if let Some(span) =
2211 ast_generics.bounds_span_for_suggestions(def_id)
2213 (span, Introducer::Plus)
2214 } else if let Some(colon_span) = param.colon_span {
2215 (colon_span.shrink_to_hi(), Introducer::Nothing)
2217 (param.span.shrink_to_hi(), Introducer::Colon)
2221 hir::GenericParamKind::Type { synthetic: true, .. },
2223 introducer = Introducer::Plus
2225 let trait_def_ids: FxHashSet<DefId> = ast_generics
2226 .bounds_for_param(def_id)
2227 .flat_map(|bp| bp.bounds.iter())
2228 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2230 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2231 err.span_suggestions(
2234 "restrict type parameter `{}` with",
2237 candidates.iter().map(|t| {
2241 Introducer::Plus => " +",
2242 Introducer::Colon => ":",
2243 Introducer::Nothing => "",
2245 self.tcx.def_path_str(t.def_id),
2248 Applicability::MaybeIncorrect,
2253 Node::Item(hir::Item {
2254 kind: hir::ItemKind::Trait(.., bounds, _),
2258 let (sp, sep, article) = if bounds.is_empty() {
2259 (ident.span.shrink_to_hi(), ":", "a")
2261 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2263 err.span_suggestions(
2265 &message(format!("add {} supertrait for", article)),
2266 candidates.iter().map(|t| {
2267 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2269 Applicability::MaybeIncorrect,
2278 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2279 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2280 // cases where a positive bound implies a negative impl.
2281 (candidates, Vec::new())
2282 } else if let Some(simp_rcvr_ty) =
2283 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2285 let mut potential_candidates = Vec::new();
2286 let mut explicitly_negative = Vec::new();
2287 for candidate in candidates {
2288 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2291 .all_impls(candidate.def_id)
2293 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2296 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2298 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2299 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2302 explicitly_negative.push(candidate);
2304 potential_candidates.push(candidate);
2307 (potential_candidates, explicitly_negative)
2309 // We don't know enough about `recv_ty` to make proper suggestions.
2310 (candidates, Vec::new())
2313 let action = if let Some(param) = param_type {
2314 format!("restrict type parameter `{}` with", param)
2316 // FIXME: it might only need to be imported into scope, not implemented.
2317 "implement".to_string()
2319 match &potential_candidates[..] {
2321 [trait_info] if trait_info.def_id.is_local() => {
2323 self.tcx.def_span(trait_info.def_id),
2325 "`{}` defines an item `{}`, perhaps you need to {} it",
2326 self.tcx.def_path_str(trait_info.def_id),
2333 let mut msg = message(action);
2334 for (i, trait_info) in trait_infos.iter().enumerate() {
2335 msg.push_str(&format!(
2336 "\ncandidate #{}: `{}`",
2338 self.tcx.def_path_str(trait_info.def_id),
2344 match &explicitly_negative[..] {
2348 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2349 self.tcx.def_path_str(trait_info.def_id),
2355 let mut msg = format!(
2356 "the following traits define an item `{}`, but are explicitly unimplemented:",
2359 for trait_info in trait_infos {
2360 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2368 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2369 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2370 pub(crate) fn suggest_else_fn_with_closure(
2372 err: &mut Diagnostic,
2373 expr: &hir::Expr<'_>,
2377 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2378 else { return false; };
2380 if !self.can_coerce(output, expected) {
2384 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2385 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2386 let hir::ExprKind::MethodCall(
2387 hir::PathSegment { ident: method_name, .. },
2391 ) = call_expr.kind &&
2392 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2393 let new_name = Ident {
2394 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2395 span: method_name.span,
2397 let probe = self.lookup_probe(
2402 ProbeScope::TraitsInScope,
2405 // check the method arguments number
2406 if let Ok(pick) = probe &&
2407 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2408 let fn_args = fn_sig.skip_binder().inputs() &&
2409 fn_args.len() == args.len() + 1 {
2410 err.span_suggestion_verbose(
2411 method_name.span.shrink_to_hi(),
2412 &format!("try calling `{}` instead", new_name.name.as_str()),
2414 Applicability::MaybeIncorrect,
2422 /// Checks whether there is a local type somewhere in the chain of
2423 /// autoderefs of `rcvr_ty`.
2424 fn type_derefs_to_local(
2428 source: SelfSource<'tcx>,
2430 fn is_local(ty: Ty<'_>) -> bool {
2432 ty::Adt(def, _) => def.did().is_local(),
2433 ty::Foreign(did) => did.is_local(),
2434 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2435 ty::Param(_) => true,
2437 // Everything else (primitive types, etc.) is effectively
2438 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2439 // the noise from these sort of types is usually just really
2440 // annoying, rather than any sort of help).
2445 // This occurs for UFCS desugaring of `T::method`, where there is no
2446 // receiver expression for the method call, and thus no autoderef.
2447 if let SelfSource::QPath(_) = source {
2448 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2451 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2455 #[derive(Copy, Clone, Debug)]
2456 pub enum SelfSource<'a> {
2457 QPath(&'a hir::Ty<'a>),
2458 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2461 #[derive(Copy, Clone)]
2462 pub struct TraitInfo {
2466 impl PartialEq for TraitInfo {
2467 fn eq(&self, other: &TraitInfo) -> bool {
2468 self.cmp(other) == Ordering::Equal
2471 impl Eq for TraitInfo {}
2472 impl PartialOrd for TraitInfo {
2473 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2474 Some(self.cmp(other))
2477 impl Ord for TraitInfo {
2478 fn cmp(&self, other: &TraitInfo) -> Ordering {
2479 // Local crates are more important than remote ones (local:
2480 // `cnum == 0`), and otherwise we throw in the defid for totality.
2482 let lhs = (other.def_id.krate, other.def_id);
2483 let rhs = (self.def_id.krate, self.def_id);
2488 /// Retrieves all traits in this crate and any dependent crates,
2489 /// and wraps them into `TraitInfo` for custom sorting.
2490 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2491 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2494 fn print_disambiguation_help<'tcx>(
2496 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2497 err: &mut Diagnostic,
2500 kind: ty::AssocKind,
2503 candidate: Option<usize>,
2504 source_map: &source_map::SourceMap,
2505 fn_has_self_parameter: bool,
2507 let mut applicability = Applicability::MachineApplicable;
2508 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2511 if rcvr_ty.is_region_ptr() {
2512 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
2516 std::iter::once(receiver)
2518 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2519 applicability = Applicability::HasPlaceholders;
2522 .collect::<Vec<_>>()
2525 let trait_name = if !fn_has_self_parameter {
2526 format!("<{} as {}>", rcvr_ty, trait_name)
2530 (span, format!("{}::{}{}", trait_name, item_name, args))
2532 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2534 err.span_suggestion_verbose(
2537 "disambiguate the {} for {}",
2538 kind.as_def_kind().descr(def_id),
2539 if let Some(candidate) = candidate {
2540 format!("candidate #{}", candidate)
2542 "the candidate".to_string()