1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8 use rustc_errors::StashKey;
10 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
14 use rustc_hir::def::DefKind;
15 use rustc_hir::def_id::DefId;
16 use rustc_hir::lang_items::LangItem;
17 use rustc_hir::PatKind::Binding;
18 use rustc_hir::PathSegment;
19 use rustc_hir::{ExprKind, Node, QPath};
20 use rustc_infer::infer::{
21 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
24 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
25 use rustc_middle::traits::util::supertraits;
26 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
27 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
28 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
29 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
30 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
31 use rustc_span::symbol::{kw, sym, Ident};
32 use rustc_span::Symbol;
33 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
34 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
35 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
36 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
37 use rustc_trait_selection::traits::{
38 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
41 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
42 use super::{CandidateSource, MethodError, NoMatchData};
43 use rustc_hir::intravisit::Visitor;
44 use std::cmp::Ordering;
47 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
51 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
52 // so we look for these beforehand.
53 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
54 // If it's not a simple function, look for things which implement `FnOnce`.
56 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
60 // This conditional prevents us from asking to call errors and unresolved types.
61 // It might seem that we can use `predicate_must_hold_modulo_regions`,
62 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
63 // type resolution always gives a "maybe" here.
64 if self.autoderef(span, ty).any(|(ty, _)| {
65 info!("check deref {:?} error", ty);
66 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
71 self.autoderef(span, ty).any(|(ty, _)| {
72 info!("check deref {:?} impl FnOnce", ty);
74 let trait_ref = tcx.mk_trait_ref(
78 self.next_ty_var(TypeVariableOrigin {
79 kind: TypeVariableOriginKind::MiscVariable,
84 let poly_trait_ref = ty::Binder::dummy(trait_ref);
85 let obligation = Obligation::misc(
90 poly_trait_ref.without_const(),
92 self.predicate_may_hold(&obligation)
99 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
100 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
103 pub fn report_method_error(
108 source: SelfSource<'tcx>,
109 error: MethodError<'tcx>,
110 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
111 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
112 // Avoid suggestions when we don't know what's going on.
113 if rcvr_ty.references_error() {
117 let report_candidates = |span: Span,
118 err: &mut Diagnostic,
119 sources: &mut Vec<CandidateSource>,
120 sugg_span: Option<Span>| {
123 // Dynamic limit to avoid hiding just one candidate, which is silly.
124 let limit = if sources.len() == 5 { 5 } else { 4 };
126 for (idx, source) in sources.iter().take(limit).enumerate() {
128 CandidateSource::Impl(impl_did) => {
129 // Provide the best span we can. Use the item, if local to crate, else
130 // the impl, if local to crate (item may be defaulted), else nothing.
131 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
132 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
133 self.associated_value(impl_trait_ref.def_id, item_name)
138 let note_span = if item.def_id.is_local() {
139 Some(self.tcx.def_span(item.def_id))
140 } else if impl_did.is_local() {
141 Some(self.tcx.def_span(impl_did))
146 let impl_ty = self.tcx.at(span).type_of(impl_did);
148 let insertion = match self.tcx.impl_trait_ref(impl_did) {
149 None => String::new(),
150 Some(trait_ref) => format!(
151 " of the trait `{}`",
152 self.tcx.def_path_str(trait_ref.def_id)
156 let (note_str, idx) = if sources.len() > 1 {
159 "candidate #{} is defined in an impl{} for the type `{}`",
169 "the candidate is defined in an impl{} for the type `{}`",
175 if let Some(note_span) = note_span {
176 // We have a span pointing to the method. Show note with snippet.
177 err.span_note(note_span, ¬e_str);
181 if let Some(sugg_span) = sugg_span
182 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
183 let path = self.tcx.def_path_str(trait_ref.def_id);
185 let ty = match item.kind {
186 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
187 ty::AssocKind::Fn => self
193 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
197 print_disambiguation_help(
207 self.tcx.sess.source_map(),
208 item.fn_has_self_parameter,
212 CandidateSource::Trait(trait_did) => {
213 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
214 let item_span = self.tcx.def_span(item.def_id);
215 let idx = if sources.len() > 1 {
217 "candidate #{} is defined in the trait `{}`",
219 self.tcx.def_path_str(trait_did)
221 err.span_note(item_span, msg);
225 "the candidate is defined in the trait `{}`",
226 self.tcx.def_path_str(trait_did)
228 err.span_note(item_span, msg);
231 if let Some(sugg_span) = sugg_span {
232 let path = self.tcx.def_path_str(trait_did);
233 print_disambiguation_help(
243 self.tcx.sess.source_map(),
244 item.fn_has_self_parameter,
250 if sources.len() > limit {
251 err.note(&format!("and {} others", sources.len() - limit));
255 let sugg_span = if let SelfSource::MethodCall(expr) = source {
256 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
257 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
263 MethodError::NoMatch(NoMatchData {
264 mut static_candidates,
265 unsatisfied_predicates,
272 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
273 let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
274 let is_method = mode == Mode::MethodCall;
275 let item_kind = if is_method {
277 } else if rcvr_ty.is_enum() {
278 "variant or associated item"
280 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
281 (Some(name), false) if name.is_lowercase() => "function or associated item",
282 (Some(_), false) => "associated item",
283 (Some(_), true) | (None, false) => "variant or associated item",
284 (None, true) => "variant",
288 if self.suggest_wrapping_range_with_parens(
289 tcx, rcvr_ty, source, span, item_name, &ty_str,
290 ) || self.suggest_constraining_numerical_ty(
291 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
295 span = item_name.span;
297 // Don't show generic arguments when the method can't be found in any implementation (#81576).
298 let mut ty_str_reported = ty_str.clone();
299 if let ty::Adt(_, generics) = rcvr_ty.kind() {
300 if generics.len() > 0 {
301 let mut autoderef = self.autoderef(span, rcvr_ty);
302 let candidate_found = autoderef.any(|(ty, _)| {
303 if let ty::Adt(adt_def, _) = ty.kind() {
305 .inherent_impls(adt_def.did())
307 .filter_map(|def_id| self.associated_value(*def_id, item_name))
314 let has_deref = autoderef.step_count() > 0;
315 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
316 if let Some((path_string, _)) = ty_str.split_once('<') {
317 ty_str_reported = path_string.to_string();
323 let mut err = struct_span_err!(
327 "no {} named `{}` found for {} `{}` in the current scope",
330 rcvr_ty.prefix_string(self.tcx),
333 if rcvr_ty.references_error() {
334 err.downgrade_to_delayed_bug();
337 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
338 self.suggest_await_before_method(
339 &mut err, item_name, rcvr_ty, cal, span,
342 if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
345 "you are looking for the module in `std`, not the primitive type",
347 Applicability::MachineApplicable,
350 if let ty::RawPtr(_) = &rcvr_ty.kind() {
352 "try using `<*const T>::as_ref()` to get a reference to the \
353 type behind the pointer: https://doc.rust-lang.org/std/\
354 primitive.pointer.html#method.as_ref",
357 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
358 to invalid or uninitialized memory is undefined behavior",
362 let ty_span = match rcvr_ty.kind() {
363 ty::Param(param_type) => Some(
364 param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
366 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
369 if let Some(span) = ty_span {
373 "{item_kind} `{item_name}` not found for this {}",
374 rcvr_ty.prefix_string(self.tcx)
379 if let SelfSource::MethodCall(rcvr_expr) = source {
380 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
384 .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
385 let probe = self.lookup_probe(
389 ProbeScope::AllTraits,
395 let mut custom_span_label = false;
397 if !static_candidates.is_empty() {
399 "found the following associated functions; to be used as methods, \
400 functions must have a `self` parameter",
402 err.span_label(span, "this is an associated function, not a method");
403 custom_span_label = true;
405 if static_candidates.len() == 1 {
406 self.suggest_associated_call_syntax(
416 report_candidates(span, &mut err, &mut static_candidates, None);
417 } else if static_candidates.len() > 1 {
418 report_candidates(span, &mut err, &mut static_candidates, Some(sugg_span));
421 let mut bound_spans = vec![];
422 let mut restrict_type_params = false;
423 let mut unsatisfied_bounds = false;
424 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
425 let msg = "consider using `len` instead";
426 if let SelfSource::MethodCall(_expr) = source {
427 err.span_suggestion_short(
431 Applicability::MachineApplicable,
434 err.span_label(span, msg);
436 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
437 let iterator_trait = self.tcx.def_path_str(iterator_trait);
438 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
440 } else if !unsatisfied_predicates.is_empty() {
441 let mut type_params = FxHashMap::default();
443 // Pick out the list of unimplemented traits on the receiver.
444 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
445 let mut unimplemented_traits = FxHashMap::default();
446 let mut unimplemented_traits_only = true;
447 for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
448 if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
449 (predicate.kind().skip_binder(), cause.as_ref())
451 if p.trait_ref.self_ty() != rcvr_ty {
452 // This is necessary, not just to keep the errors clean, but also
453 // because our derived obligations can wind up with a trait ref that
454 // requires a different param_env to be correctly compared.
457 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
458 predicate.kind().rebind(p.trait_ref),
460 cause: cause.clone(),
461 param_env: self.param_env,
462 predicate: *predicate,
469 // Make sure that, if any traits other than the found ones were involved,
470 // we don't don't report an unimplemented trait.
471 // We don't want to say that `iter::Cloned` is not an iterator, just
472 // because of some non-Clone item being iterated over.
473 for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
474 match predicate.kind().skip_binder() {
475 ty::PredicateKind::Clause(ty::Clause::Trait(p))
476 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
478 unimplemented_traits_only = false;
484 let mut collect_type_param_suggestions =
485 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
486 // We don't care about regions here, so it's fine to skip the binder here.
487 if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
488 (self_ty.kind(), parent_pred.kind().skip_binder())
490 let hir = self.tcx.hir();
491 let node = match p.trait_ref.self_ty().kind() {
493 // Account for `fn` items like in `issue-35677.rs` to
494 // suggest restricting its type params.
496 hir.body_owner(hir::BodyId { hir_id: self.body_id });
497 Some(hir.get(parent_body))
500 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
504 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
505 if let Some(g) = kind.generics() {
507 g.tail_span_for_predicate_suggestion(),
508 g.add_where_or_trailing_comma(),
512 .or_insert_with(FxHashSet::default)
513 .insert(obligation.to_owned());
518 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
520 "doesn't satisfy `{}`",
521 if obligation.len() > 50 { quiet } else { obligation }
523 match &self_ty.kind() {
524 // Point at the type that couldn't satisfy the bound.
526 bound_spans.push((self.tcx.def_span(def.did()), msg))
528 // Point at the trait object that couldn't satisfy the bound.
529 ty::Dynamic(preds, _, _) => {
530 for pred in preds.iter() {
531 match pred.skip_binder() {
532 ty::ExistentialPredicate::Trait(tr) => bound_spans
533 .push((self.tcx.def_span(tr.def_id), msg.clone())),
534 ty::ExistentialPredicate::Projection(_)
535 | ty::ExistentialPredicate::AutoTrait(_) => {}
539 // Point at the closure that couldn't satisfy the bound.
540 ty::Closure(def_id, _) => bound_spans.push((
541 tcx.def_span(*def_id),
542 format!("doesn't satisfy `{}`", quiet),
547 let mut format_pred = |pred: ty::Predicate<'tcx>| {
548 let bound_predicate = pred.kind();
549 match bound_predicate.skip_binder() {
550 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
551 let pred = bound_predicate.rebind(pred);
552 // `<Foo as Iterator>::Item = String`.
553 let projection_ty = pred.skip_binder().projection_ty;
555 let substs_with_infer_self = tcx.mk_substs(
556 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
557 .chain(projection_ty.substs.iter().skip(1)),
560 let quiet_projection_ty =
561 tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
563 let term = pred.skip_binder().term;
565 let obligation = format!("{} = {}", projection_ty, term);
566 let quiet = with_forced_trimmed_paths!(format!(
568 quiet_projection_ty, term
571 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
572 Some((obligation, projection_ty.self_ty()))
574 ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
575 let p = poly_trait_ref.trait_ref;
576 let self_ty = p.self_ty();
577 let path = p.print_only_trait_path();
578 let obligation = format!("{}: {}", self_ty, path);
579 let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
580 bound_span_label(self_ty, &obligation, &quiet);
581 Some((obligation, self_ty))
587 // Find all the requirements that come from a local `impl` block.
588 let mut skip_list: FxHashSet<_> = Default::default();
589 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
590 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
592 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
593 .filter_map(|(p, parent, c)| match c.code() {
594 ObligationCauseCode::ImplDerivedObligation(data) => {
595 Some((&data.derived, p, parent, data.impl_def_id, data))
600 let parent_trait_ref = data.parent_trait_pred;
601 let path = parent_trait_ref.print_modifiers_and_trait_path();
602 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
603 let unsatisfied_msg = "unsatisfied trait bound introduced here";
605 "unsatisfied trait bound introduced in this `derive` macro";
606 match self.tcx.hir().get_if_local(impl_def_id) {
607 // Unmet obligation comes from a `derive` macro, point at it once to
608 // avoid multiple span labels pointing at the same place.
609 Some(Node::Item(hir::Item {
610 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
613 self_ty.span.ctxt().outer_expn_data().kind,
614 ExpnKind::Macro(MacroKind::Derive, _)
616 of_trait.as_ref().map(|t| t
622 Some(ExpnKind::Macro(MacroKind::Derive, _))
625 let span = self_ty.span.ctxt().outer_expn_data().call_site;
626 let mut spans: MultiSpan = span.into();
627 spans.push_span_label(span, derive_msg);
628 let entry = spanned_predicates.entry(spans);
629 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
632 // Unmet obligation coming from an `impl`.
633 Some(Node::Item(hir::Item {
635 hir::ItemKind::Impl(hir::Impl {
636 of_trait, self_ty, generics, ..
642 unsatisfied_predicates.iter().any(|(pred, _, _)| {
643 match pred.kind().skip_binder() {
644 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
646 == self.tcx.lang_items().sized_trait()
647 && pred.polarity == ty::ImplPolarity::Positive
652 for param in generics.params {
653 if param.span == cause.span && sized_pred {
654 let (sp, sugg) = match param.colon_span {
655 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
656 None => (param.span.shrink_to_hi(), ": ?Sized"),
658 err.span_suggestion_verbose(
660 "consider relaxing the type parameter's implicit \
663 Applicability::MachineApplicable,
667 if let Some(pred) = parent_p {
668 // Done to add the "doesn't satisfy" `span_label`.
669 let _ = format_pred(*pred);
672 let mut spans = if cause.span != *item_span {
673 let mut spans: MultiSpan = cause.span.into();
674 spans.push_span_label(cause.span, unsatisfied_msg);
677 let mut spans = Vec::with_capacity(2);
678 if let Some(trait_ref) = of_trait {
679 spans.push(trait_ref.path.span);
681 spans.push(self_ty.span);
684 if let Some(trait_ref) = of_trait {
685 spans.push_span_label(trait_ref.path.span, "");
687 spans.push_span_label(self_ty.span, "");
689 let entry = spanned_predicates.entry(spans);
690 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
692 Some(Node::Item(hir::Item {
693 kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
697 tcx.sess.delay_span_bug(
699 "auto trait is invoked with no method error, but no error reported?",
702 Some(_) => unreachable!(),
706 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
707 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
708 for (span, (_path, _self_ty, preds)) in spanned_predicates {
709 let mut preds: Vec<_> = preds
711 .filter_map(|pred| format_pred(*pred))
712 .map(|(p, _)| format!("`{}`", p))
716 let msg = if let [pred] = &preds[..] {
717 format!("trait bound {} was not satisfied", pred)
720 "the following trait bounds were not satisfied:\n{}",
724 err.span_note(span, &msg);
725 unsatisfied_bounds = true;
728 // The requirements that didn't have an `impl` span to show.
729 let mut bound_list = unsatisfied_predicates
731 .filter_map(|(pred, parent_pred, _cause)| {
732 format_pred(*pred).map(|(p, self_ty)| {
733 collect_type_param_suggestions(self_ty, *pred, &p);
736 None => format!("`{}`", &p),
737 Some(parent_pred) => match format_pred(*parent_pred) {
738 None => format!("`{}`", &p),
739 Some((parent_p, _)) => {
740 collect_type_param_suggestions(
746 "`{}`\nwhich is required by `{}`",
756 .filter(|(_, pred)| !skip_list.contains(&pred))
759 .collect::<Vec<(usize, String)>>();
761 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
762 restrict_type_params = true;
763 // #74886: Sort here so that the output is always the same.
764 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
766 err.span_suggestion_verbose(
769 "consider restricting the type parameter{s} to satisfy the \
771 s = pluralize!(obligations.len())
773 format!("{} {}", add_where_or_comma, obligations.join(", ")),
774 Applicability::MaybeIncorrect,
778 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
779 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
780 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
782 if !bound_list.is_empty() || !skip_list.is_empty() {
783 let bound_list = bound_list
785 .map(|(_, path)| path)
788 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
789 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
790 let (primary_message, label) =
791 if unimplemented_traits.len() == 1 && unimplemented_traits_only {
795 .map(|(_, (trait_ref, obligation))| {
796 if trait_ref.self_ty().references_error()
797 || rcvr_ty.references_error()
802 let OnUnimplementedNote { message, label, .. } = self
804 .on_unimplemented_note(trait_ref, &obligation);
811 let primary_message = primary_message.unwrap_or_else(|| format!(
812 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
813 but its trait bounds were not satisfied"
815 err.set_primary_message(&primary_message);
816 if let Some(label) = label {
817 custom_span_label = true;
818 err.span_label(span, label);
820 if !bound_list.is_empty() {
822 "the following trait bounds were not satisfied:\n{bound_list}"
825 self.suggest_derive(&mut err, &unsatisfied_predicates);
827 unsatisfied_bounds = true;
831 let label_span_not_found = |err: &mut Diagnostic| {
832 if unsatisfied_predicates.is_empty() {
833 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
834 let is_string_or_ref_str = match rcvr_ty.kind() {
835 ty::Ref(_, ty, _) => {
839 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
842 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
845 if is_string_or_ref_str && item_name.name == sym::iter {
846 err.span_suggestion_verbose(
848 "because of the in-memory representation of `&str`, to obtain \
849 an `Iterator` over each of its codepoint use method `chars`",
851 Applicability::MachineApplicable,
854 if let ty::Adt(adt, _) = rcvr_ty.kind() {
855 let mut inherent_impls_candidate = self
857 .inherent_impls(adt.did())
861 if let Some(assoc) = self.associated_value(*def_id, item_name) {
862 // Check for both mode is the same so we avoid suggesting
863 // incorrect associated item.
864 match (mode, assoc.fn_has_self_parameter, source) {
865 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
866 // We check that the suggest type is actually
867 // different from the received one
868 // So we avoid suggestion method with Box<Self>
870 self.tcx.at(span).type_of(*def_id) != rcvr_ty
871 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
873 (Mode::Path, false, _) => true,
880 .collect::<Vec<_>>();
881 if !inherent_impls_candidate.is_empty() {
882 inherent_impls_candidate.sort();
883 inherent_impls_candidate.dedup();
885 // number of type to shows at most.
886 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
887 let type_candidates = inherent_impls_candidate
891 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
895 let additional_types = if inherent_impls_candidate.len() > limit {
897 "\nand {} more types",
898 inherent_impls_candidate.len() - limit
904 "the {item_kind} was found for\n{}{}",
905 type_candidates, additional_types
910 let ty_str = if ty_str.len() > 50 {
913 format!("on `{ty_str}` ")
915 err.span_label(span, format!(
916 "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
921 // If the method name is the name of a field with a function or closure type,
922 // give a helping note that it has to be called as `(x.f)(...)`.
923 if let SelfSource::MethodCall(expr) = source {
924 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
925 && lev_candidate.is_none()
926 && !custom_span_label
928 label_span_not_found(&mut err);
930 } else if !custom_span_label {
931 label_span_not_found(&mut err);
934 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
935 // can't be called due to `typeof(expr): Clone` not holding.
936 if unsatisfied_predicates.is_empty() {
937 self.suggest_calling_method_on_field(
938 &mut err, source, span, rcvr_ty, item_name,
942 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
946 for (span, msg) in bound_spans.into_iter() {
947 err.span_label(span, &msg);
950 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
952 self.suggest_traits_to_import(
957 args.map(|(_, args)| args.len() + 1),
960 &unsatisfied_predicates,
966 // Don't emit a suggestion if we found an actual method
967 // that had unsatisfied trait bounds
968 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
969 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
970 if let Some(suggestion) = lev_distance::find_best_match_for_name(
971 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
977 "there is a variant with a similar name",
979 Applicability::MaybeIncorrect,
984 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
985 let msg = "remove this method call";
986 let mut fallback_span = true;
987 if let SelfSource::MethodCall(expr) = source {
989 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
990 if let Some(span) = call_expr.span.trim_start(expr.span) {
991 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
992 fallback_span = false;
996 err.span_label(span, msg);
998 } else if let Some(lev_candidate) = lev_candidate {
999 // Don't emit a suggestion if we found an actual method
1000 // that had unsatisfied trait bounds
1001 if unsatisfied_predicates.is_empty() {
1002 let def_kind = lev_candidate.kind.as_def_kind();
1003 // Methods are defined within the context of a struct and their first parameter is always self,
1004 // which represents the instance of the struct the method is being called on
1005 // Associated functions don’t take self as a parameter and
1006 // they are not methods because they don’t have an instance of the struct to work with.
1007 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1008 err.span_suggestion(
1010 "there is a method with a similar name",
1012 Applicability::MaybeIncorrect,
1015 err.span_suggestion(
1018 "there is {} {} with a similar name",
1020 def_kind.descr(lev_candidate.def_id),
1023 Applicability::MaybeIncorrect,
1029 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1034 MethodError::Ambiguity(mut sources) => {
1035 let mut err = struct_span_err!(
1039 "multiple applicable items in scope"
1041 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1043 report_candidates(span, &mut err, &mut sources, Some(sugg_span));
1047 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1048 let kind = kind.descr(def_id);
1049 let mut err = struct_span_err!(
1053 "{} `{}` is private",
1057 err.span_label(item_name.span, &format!("private {}", kind));
1061 .span_if_local(def_id)
1062 .unwrap_or_else(|| self.tcx.def_span(def_id));
1063 err.span_label(sp, &format!("private {} defined here", kind));
1064 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1068 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1069 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1070 let mut err = self.sess().struct_span_err(span, &msg);
1071 err.span_label(bound_span, "this has a `Sized` requirement");
1072 if !candidates.is_empty() {
1074 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1075 add a `use` for {one_of_them}:",
1076 an = if candidates.len() == 1 { "an" } else { "" },
1077 s = pluralize!(candidates.len()),
1078 were = pluralize!("was", candidates.len()),
1079 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1081 self.suggest_use_candidates(&mut err, help, candidates);
1083 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1085 let trait_type = self.tcx.mk_ref(
1087 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1089 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1095 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1100 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1101 /// doesn't take a `self` receiver.
1102 fn suggest_associated_call_syntax(
1104 err: &mut Diagnostic,
1105 static_candidates: &Vec<CandidateSource>,
1107 source: SelfSource<'tcx>,
1109 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1112 let mut has_unsuggestable_args = false;
1113 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1114 // When the "method" is resolved through dereferencing, we really want the
1115 // original type that has the associated function for accurate suggestions.
1117 let impl_ty = self.tcx.type_of(*impl_did);
1118 let target_ty = self
1119 .autoderef(sugg_span, rcvr_ty)
1120 .find(|(rcvr_ty, _)| {
1121 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1122 .types_may_unify(*rcvr_ty, impl_ty)
1124 .map_or(impl_ty, |(ty, _)| ty)
1126 if let ty::Adt(def, substs) = target_ty.kind() {
1127 // If there are any inferred arguments, (`{integer}`), we should replace
1128 // them with underscores to allow the compiler to infer them
1129 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1130 if !arg.is_suggestable(self.tcx, true) {
1131 has_unsuggestable_args = true;
1132 match arg.unpack() {
1133 GenericArgKind::Lifetime(_) => self
1134 .next_region_var(RegionVariableOrigin::MiscVariable(
1135 rustc_span::DUMMY_SP,
1138 GenericArgKind::Type(_) => self
1139 .next_ty_var(TypeVariableOrigin {
1140 span: rustc_span::DUMMY_SP,
1141 kind: TypeVariableOriginKind::MiscVariable,
1144 GenericArgKind::Const(arg) => self
1147 ConstVariableOrigin {
1148 span: rustc_span::DUMMY_SP,
1149 kind: ConstVariableOriginKind::MiscVariable,
1159 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1161 self.ty_to_value_string(target_ty)
1164 self.ty_to_value_string(rcvr_ty.peel_refs())
1166 if let SelfSource::MethodCall(_) = source {
1167 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1168 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1169 && assoc.kind == ty::AssocKind::Fn
1171 let sig = self.tcx.fn_sig(assoc.def_id);
1172 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1175 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1180 let mut applicability = Applicability::MachineApplicable;
1181 let args = if let Some((receiver, args)) = args {
1182 // The first arg is the same kind as the receiver
1183 let explicit_args = if first_arg.is_some() {
1184 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1186 // There is no `Self` kind to infer the arguments from
1187 if has_unsuggestable_args {
1188 applicability = Applicability::HasPlaceholders;
1190 args.iter().collect()
1194 first_arg.unwrap_or(""),
1201 .span_to_snippet(arg.span)
1202 .unwrap_or_else(|_| {
1203 applicability = Applicability::HasPlaceholders;
1206 .collect::<Vec<_>>()
1210 applicability = Applicability::HasPlaceholders;
1213 err.span_suggestion(
1215 "use associated function syntax instead",
1216 format!("{}::{}{}", ty_str, item_name, args),
1220 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1224 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1225 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1226 fn suggest_calling_field_as_fn(
1230 expr: &hir::Expr<'_>,
1232 err: &mut Diagnostic,
1235 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1236 ty::Adt(def, substs) if !def.is_enum() => {
1237 let variant = &def.non_enum_variant();
1238 tcx.find_field_index(item_name, variant).map(|index| {
1239 let field = &variant.fields[index];
1240 let field_ty = field.ty(tcx, substs);
1246 if let Some((field, field_ty)) = field_receiver {
1247 let scope = tcx.parent_module(self.body_id);
1248 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1251 if self.is_fn_ty(field_ty, span) {
1252 let expr_span = expr.span.to(item_name.span);
1253 err.multipart_suggestion(
1255 "to call the function stored in `{}`, \
1256 surround the field access with parentheses",
1260 (expr_span.shrink_to_lo(), '('.to_string()),
1261 (expr_span.shrink_to_hi(), ')'.to_string()),
1263 Applicability::MachineApplicable,
1266 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1268 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1269 err.span_suggestion(
1271 "remove the arguments",
1273 Applicability::MaybeIncorrect,
1279 let field_kind = if is_accessible { "field" } else { "private field" };
1280 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1286 /// Suggest possible range with adding parentheses, for example:
1287 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1288 fn suggest_wrapping_range_with_parens(
1292 source: SelfSource<'tcx>,
1297 if let SelfSource::MethodCall(expr) = source {
1298 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1299 if let Node::Expr(parent_expr) = parent {
1300 let lang_item = match parent_expr.kind {
1301 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1302 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1303 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1304 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1305 Some(LangItem::RangeToInclusive)
1309 ExprKind::Call(ref func, _) => match func.kind {
1310 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1311 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1312 Some(LangItem::RangeInclusiveStruct)
1319 if lang_item.is_none() {
1323 let span_included = match parent_expr.kind {
1324 hir::ExprKind::Struct(_, eps, _) => {
1325 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1327 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1328 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1336 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1338 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1340 let pick = self.probe_for_name(
1346 ProbeScope::AllTraits,
1349 let range_span = parent_expr.span.with_hi(expr.span.hi());
1350 tcx.sess.emit_err(errors::MissingParentheseInRange {
1352 ty_str: ty_str.to_string(),
1353 method_name: item_name.as_str().to_string(),
1354 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1355 func_name: item_name.name.as_str().to_string(),
1356 left: range_span.shrink_to_lo(),
1357 right: range_span.shrink_to_hi(),
1368 fn suggest_constraining_numerical_ty(
1372 source: SelfSource<'_>,
1378 let found_candidate = all_traits(self.tcx)
1380 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1381 let found_assoc = |ty: Ty<'tcx>| {
1382 simplify_type(tcx, ty, TreatParams::AsInfer)
1384 tcx.incoherent_impls(simp)
1386 .find_map(|&id| self.associated_value(id, item_name))
1390 let found_candidate = found_candidate
1391 || found_assoc(tcx.types.i8)
1392 || found_assoc(tcx.types.i16)
1393 || found_assoc(tcx.types.i32)
1394 || found_assoc(tcx.types.i64)
1395 || found_assoc(tcx.types.i128)
1396 || found_assoc(tcx.types.u8)
1397 || found_assoc(tcx.types.u16)
1398 || found_assoc(tcx.types.u32)
1399 || found_assoc(tcx.types.u64)
1400 || found_assoc(tcx.types.u128)
1401 || found_assoc(tcx.types.f32)
1402 || found_assoc(tcx.types.f32);
1404 && actual.is_numeric()
1405 && !actual.has_concrete_skeleton()
1406 && let SelfSource::MethodCall(expr) = source
1408 let mut err = struct_span_err!(
1412 "can't call {} `{}` on ambiguous numeric type `{}`",
1417 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1419 ExprKind::Lit(ref lit) => {
1424 .span_to_snippet(lit.span)
1425 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1427 // If this is a floating point literal that ends with '.',
1428 // get rid of it to stop this from becoming a member access.
1429 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1430 err.span_suggestion(
1433 "you must specify a concrete type for this numeric value, \
1437 format!("{snippet}_{concrete_type}"),
1438 Applicability::MaybeIncorrect,
1441 ExprKind::Path(QPath::Resolved(_, path)) => {
1443 if let hir::def::Res::Local(hir_id) = path.res {
1444 let span = tcx.hir().span(hir_id);
1445 let filename = tcx.sess.source_map().span_to_filename(span);
1448 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
1450 "you must specify a type for this binding, like `{}`",
1454 match (filename, parent_node) {
1457 Node::Local(hir::Local {
1458 source: hir::LocalSource::Normal,
1463 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1464 err.span_suggestion(
1465 // account for `let x: _ = 42;`
1469 format!(": {concrete_type}"),
1470 Applicability::MaybeIncorrect,
1474 err.span_label(span, msg);
1487 /// For code `rect::area(...)`,
1488 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1489 /// we try to suggest `rect.area()`
1490 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1491 debug!("suggest_assoc_method_call segs: {:?}", segs);
1492 let [seg1, seg2] = segs else { return; };
1493 let Some(mut diag) =
1494 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1497 let map = self.infcx.tcx.hir();
1498 let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
1499 struct LetVisitor<'a> {
1500 result: Option<&'a hir::Expr<'a>>,
1504 // FIXME: This really should be taking scoping, etc into account.
1505 impl<'v> Visitor<'v> for LetVisitor<'v> {
1506 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1507 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1508 && let Binding(_, _, ident, ..) = pat.kind
1509 && ident.name == self.ident_name
1511 self.result = *init;
1513 hir::intravisit::walk_stmt(self, ex);
1518 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1519 visitor.visit_body(&body);
1521 let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
1522 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1523 && let Some(expr) = visitor.result
1524 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1526 let probe = self.lookup_probe(
1530 ProbeScope::TraitsInScope,
1533 let sm = self.infcx.tcx.sess.source_map();
1534 diag.span_suggestion_verbose(
1535 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1536 "you may have meant to call an instance method",
1538 Applicability::MaybeIncorrect,
1545 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1546 fn suggest_calling_method_on_field(
1548 err: &mut Diagnostic,
1549 source: SelfSource<'tcx>,
1554 if let SelfSource::MethodCall(expr) = source
1555 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1556 && let Some((fields, substs)) =
1557 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1559 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1561 let lang_items = self.tcx.lang_items();
1562 let never_mention_traits = [
1563 lang_items.clone_trait(),
1564 lang_items.deref_trait(),
1565 lang_items.deref_mut_trait(),
1566 self.tcx.get_diagnostic_item(sym::AsRef),
1567 self.tcx.get_diagnostic_item(sym::AsMut),
1568 self.tcx.get_diagnostic_item(sym::Borrow),
1569 self.tcx.get_diagnostic_item(sym::BorrowMut),
1571 let candidate_fields: Vec<_> = fields
1572 .filter_map(|candidate_field| {
1573 self.check_for_nested_field_satisfying(
1580 ProbeScope::TraitsInScope,
1582 .map_or(false, |pick| {
1583 !never_mention_traits
1586 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1598 .map(|id| id.name.to_ident_string())
1599 .collect::<Vec<String>>()
1604 let len = candidate_fields.len();
1606 err.span_suggestions(
1607 item_name.span.shrink_to_lo(),
1609 "{} of the expressions' fields {} a method of the same name",
1610 if len > 1 { "some" } else { "one" },
1611 if len > 1 { "have" } else { "has" },
1613 candidate_fields.iter().map(|path| format!("{path}.")),
1614 Applicability::MaybeIncorrect,
1620 fn check_for_inner_self(
1622 err: &mut Diagnostic,
1623 source: SelfSource<'tcx>,
1628 let SelfSource::MethodCall(expr) = source else { return; };
1629 let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
1631 let ty::Adt(kind, substs) = actual.kind() else { return; };
1632 match kind.adt_kind() {
1633 ty::AdtKind::Enum => {
1634 let matching_variants: Vec<_> = kind
1637 .flat_map(|variant| {
1638 let [field] = &variant.fields[..] else { return None; };
1639 let field_ty = field.ty(tcx, substs);
1641 // Skip `_`, since that'll just lead to ambiguity.
1642 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1646 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1648 .map(|pick| (variant, field, pick))
1652 let ret_ty_matches = |diagnostic_item| {
1653 if let Some(ret_ty) = self
1656 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1657 && let ty::Adt(kind, _) = ret_ty.kind()
1658 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1666 match &matching_variants[..] {
1667 [(_, field, pick)] => {
1668 let self_ty = field.ty(tcx, substs);
1670 tcx.def_span(pick.item.def_id),
1671 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1673 let (article, kind, variant, question) =
1674 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1675 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1676 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1677 ("an", "Option", "None", ret_ty_matches(sym::Option))
1682 err.span_suggestion_verbose(
1683 expr.span.shrink_to_hi(),
1685 "use the `?` operator to extract the `{self_ty}` value, propagating \
1686 {article} `{kind}::{variant}` value to the caller"
1689 Applicability::MachineApplicable,
1692 err.span_suggestion_verbose(
1693 expr.span.shrink_to_hi(),
1695 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1696 panicking if the value is {article} `{kind}::{variant}`"
1698 ".expect(\"REASON\")",
1699 Applicability::HasPlaceholders,
1703 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1707 // Target wrapper types - types that wrap or pretend to wrap another type,
1708 // perhaps this inner type is meant to be called?
1709 ty::AdtKind::Struct | ty::AdtKind::Union => {
1710 let [first] = ***substs else { return; };
1711 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1712 let Ok(pick) = self.lookup_probe(
1716 ProbeScope::TraitsInScope,
1719 let name = self.ty_to_value_string(actual);
1720 let inner_id = kind.did();
1721 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1722 pick.autoref_or_ptr_adjustment
1729 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1730 err.help("use `with` or `try_with` to access thread local storage");
1731 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1733 "if this `{name}` has been initialized, \
1734 use one of the `assume_init` methods to access the inner value"
1736 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1737 let (suggestion, borrow_kind, panic_if) = match mutable {
1738 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1739 Some(Mutability::Mut) => {
1740 (".borrow_mut()", "mutably borrow", "any borrows exist")
1744 err.span_suggestion_verbose(
1745 expr.span.shrink_to_hi(),
1747 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1748 panicking if {panic_if}"
1751 Applicability::MaybeIncorrect,
1753 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1754 err.span_suggestion_verbose(
1755 expr.span.shrink_to_hi(),
1757 "use `.lock().unwrap()` to borrow the `{ty}`, \
1758 blocking the current thread until it can be acquired"
1761 Applicability::MaybeIncorrect,
1763 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1764 let (suggestion, borrow_kind) = match mutable {
1765 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1766 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1769 err.span_suggestion_verbose(
1770 expr.span.shrink_to_hi(),
1772 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1773 blocking the current thread until it can be acquired"
1776 Applicability::MaybeIncorrect,
1783 tcx.def_span(pick.item.def_id),
1784 &format!("the method `{item_name}` exists on the type `{ty}`"),
1790 pub(crate) fn note_unmet_impls_on_type(
1792 err: &mut Diagnostic,
1793 errors: Vec<FulfillmentError<'tcx>>,
1795 let all_local_types_needing_impls =
1796 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1797 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1798 ty::Adt(def, _) => def.did().is_local(),
1803 let mut preds: Vec<_> = errors
1805 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1806 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1810 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1813 .filter_map(|pred| match pred.self_ty().kind() {
1814 ty::Adt(def, _) => Some(def.did()),
1817 .collect::<FxHashSet<_>>();
1818 let mut spans: MultiSpan = def_ids
1820 .filter_map(|def_id| {
1821 let span = self.tcx.def_span(*def_id);
1822 if span.is_dummy() { None } else { Some(span) }
1824 .collect::<Vec<_>>()
1827 for pred in &preds {
1828 match pred.self_ty().kind() {
1829 ty::Adt(def, _) if def.did().is_local() => {
1830 spans.push_span_label(
1831 self.tcx.def_span(def.did()),
1832 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1839 if all_local_types_needing_impls && spans.primary_span().is_some() {
1840 let msg = if preds.len() == 1 {
1842 "an implementation of `{}` might be missing for `{}`",
1843 preds[0].trait_ref.print_only_trait_path(),
1848 "the following type{} would have to `impl` {} required trait{} for this \
1849 operation to be valid",
1850 pluralize!(def_ids.len()),
1851 if def_ids.len() == 1 { "its" } else { "their" },
1852 pluralize!(preds.len()),
1855 err.span_note(spans, &msg);
1858 let preds: Vec<_> = errors
1860 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1862 self.suggest_derive(err, &preds);
1865 pub fn suggest_derive(
1867 err: &mut Diagnostic,
1868 unsatisfied_predicates: &[(
1869 ty::Predicate<'tcx>,
1870 Option<ty::Predicate<'tcx>>,
1871 Option<ObligationCause<'tcx>>,
1874 let mut derives = Vec::<(String, Span, Symbol)>::new();
1875 let mut traits = Vec::new();
1876 for (pred, _, _) in unsatisfied_predicates {
1877 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1878 let adt = match trait_pred.self_ty().ty_adt_def() {
1879 Some(adt) if adt.did().is_local() => adt,
1882 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1883 let can_derive = match diagnostic_name {
1884 sym::Default => !adt.is_enum(),
1892 | sym::Debug => true,
1896 let self_name = trait_pred.self_ty().to_string();
1897 let self_span = self.tcx.def_span(adt.did());
1898 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1899 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1901 if let Some(parent_diagnostic_name) =
1902 self.tcx.get_diagnostic_name(super_trait.def_id())
1907 parent_diagnostic_name,
1912 derives.push((self_name, self_span, diagnostic_name));
1914 traits.push(trait_pred.def_id());
1917 traits.push(trait_pred.def_id());
1926 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1927 for (self_name, self_span, trait_name) in derives.into_iter() {
1928 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1930 if last_self_name == &self_name {
1931 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1935 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1938 let len = traits.len();
1941 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
1942 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
1943 for (i, &did) in traits.iter().enumerate().skip(1) {
1945 names.push_str(", ");
1948 names.push_str(" and ");
1951 names.push_str(&self.tcx.def_path_str(did));
1956 &format!("the trait{} {} must be implemented", pluralize!(len), names),
1960 for (self_name, self_span, traits) in &derives_grouped {
1961 err.span_suggestion_verbose(
1962 self_span.shrink_to_lo(),
1963 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1964 format!("#[derive({})]\n", traits),
1965 Applicability::MaybeIncorrect,
1970 fn check_for_deref_method(
1972 err: &mut Diagnostic,
1973 self_source: SelfSource<'tcx>,
1977 let SelfSource::QPath(ty) = self_source else { return; };
1978 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1979 if let Ok(pick) = self.probe_for_name(
1985 ProbeScope::TraitsInScope,
1987 if deref_ty.is_suggestable(self.tcx, true)
1988 // If this method receives `&self`, then the provided
1989 // argument _should_ coerce, so it's valid to suggest
1990 // just changing the path.
1991 && pick.item.fn_has_self_parameter
1992 && let Some(self_ty) =
1993 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1996 let suggested_path = match deref_ty.kind() {
2004 | ty::Alias(ty::Projection, _)
2005 | ty::Param(_) => format!("{deref_ty}"),
2006 // we need to test something like <&[_]>::len or <(&[u32])>::len
2007 // and Vec::function();
2008 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2009 // but for Adt type like Vec::function()
2010 // we would suggest <[_]>::function();
2011 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
2012 _ => format!("<{deref_ty}>"),
2014 err.span_suggestion_verbose(
2016 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2018 Applicability::MaybeIncorrect,
2023 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2031 /// Print out the type for use in value namespace.
2032 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2034 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2035 _ => self.ty_to_string(ty),
2039 fn suggest_await_before_method(
2041 err: &mut Diagnostic,
2044 call: &hir::Expr<'_>,
2047 let output_ty = match self.get_impl_future_output_ty(ty) {
2048 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2051 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
2052 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2054 err.span_suggestion_verbose(
2055 span.shrink_to_lo(),
2056 "consider `await`ing on the `Future` and calling the method on its `Output`",
2058 Applicability::MaybeIncorrect,
2063 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2064 let parent_map = self.tcx.visible_parent_map(());
2066 // Separate out candidates that must be imported with a glob, because they are named `_`
2067 // and cannot be referred with their identifier.
2068 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2069 if let Some(parent_did) = parent_map.get(trait_did) {
2070 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2071 if *parent_did != self.tcx.parent(*trait_did)
2074 .module_children(*parent_did)
2076 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2077 .all(|child| child.ident.name == kw::Underscore)
2086 let module_did = self.tcx.parent_module(self.body_id);
2087 let (module, _, _) = self.tcx.hir().get_module(module_did);
2088 let span = module.spans.inject_use_span;
2090 let path_strings = candidates.iter().map(|trait_did| {
2091 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2094 let glob_path_strings = globs.iter().map(|trait_did| {
2095 let parent_did = parent_map.get(trait_did).unwrap();
2097 "use {}::*; // trait {}\n",
2098 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2099 self.tcx.item_name(*trait_did),
2103 err.span_suggestions(
2106 path_strings.chain(glob_path_strings),
2107 Applicability::MaybeIncorrect,
2111 fn suggest_valid_traits(
2113 err: &mut Diagnostic,
2114 valid_out_of_scope_traits: Vec<DefId>,
2116 if !valid_out_of_scope_traits.is_empty() {
2117 let mut candidates = valid_out_of_scope_traits;
2121 // `TryFrom` and `FromIterator` have no methods
2122 let edition_fix = candidates
2124 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2127 err.help("items from traits can only be used if the trait is in scope");
2129 "the following {traits_are} implemented but not in scope; \
2130 perhaps add a `use` for {one_of_them}:",
2131 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2132 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2135 self.suggest_use_candidates(err, msg, candidates);
2136 if let Some(did) = edition_fix {
2138 "'{}' is included in the prelude starting in Edition 2021",
2139 with_crate_prefix!(self.tcx.def_path_str(did))
2149 fn suggest_traits_to_import(
2151 err: &mut Diagnostic,
2155 inputs_len: Option<usize>,
2156 source: SelfSource<'tcx>,
2157 valid_out_of_scope_traits: Vec<DefId>,
2158 unsatisfied_predicates: &[(
2159 ty::Predicate<'tcx>,
2160 Option<ty::Predicate<'tcx>>,
2161 Option<ObligationCause<'tcx>>,
2163 static_candidates: &[CandidateSource],
2164 unsatisfied_bounds: bool,
2166 let mut alt_rcvr_sugg = false;
2167 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2169 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2170 span, item_name, rcvr_ty, rcvr
2173 self.tcx.lang_items().clone_trait(),
2174 self.tcx.lang_items().deref_trait(),
2175 self.tcx.lang_items().deref_mut_trait(),
2176 self.tcx.lang_items().drop_trait(),
2177 self.tcx.get_diagnostic_item(sym::AsRef),
2179 // Try alternative arbitrary self types that could fulfill this call.
2180 // FIXME: probe for all types that *could* be arbitrary self-types, not
2182 for (rcvr_ty, post) in &[
2184 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2185 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2187 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2189 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2190 // We point at the method, but we just skip the rest of the check for arbitrary
2191 // self types and rely on the suggestion to `use` the trait from
2192 // `suggest_valid_traits`.
2193 let did = Some(pick.item.container_id(self.tcx));
2194 let skip = skippable.contains(&did);
2195 if pick.autoderefs == 0 && !skip {
2197 pick.item.ident(self.tcx).span,
2198 &format!("the method is available for `{}` here", rcvr_ty),
2203 Err(MethodError::Ambiguity(_)) => {
2204 // If the method is defined (but ambiguous) for the receiver we have, it is also
2205 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2206 // the receiver, then it might disambiguate this method, but I think these
2207 // suggestions are generally misleading (see #94218).
2213 for (rcvr_ty, pre) in &[
2214 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2215 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2216 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2217 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2219 if let Some(new_rcvr_t) = *rcvr_ty
2220 && let Ok(pick) = self.lookup_probe(
2224 ProbeScope::AllTraits,
2227 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2228 let did = Some(pick.item.container_id(self.tcx));
2229 // We don't want to suggest a container type when the missing
2230 // method is `.clone()` or `.deref()` otherwise we'd suggest
2231 // `Arc::new(foo).clone()`, which is far from what the user wants.
2232 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2233 // implement the `AsRef` trait.
2234 let skip = skippable.contains(&did)
2235 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2236 || 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);
2237 // Make sure the method is defined for the *actual* receiver: we don't
2238 // want to treat `Box<Self>` as a receiver if it only works because of
2239 // an autoderef to `&self`
2240 if pick.autoderefs == 0 && !skip {
2242 pick.item.ident(self.tcx).span,
2243 &format!("the method is available for `{}` here", new_rcvr_t),
2245 err.multipart_suggestion(
2246 "consider wrapping the receiver expression with the \
2249 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2250 (rcvr.span.shrink_to_hi(), ")".to_string()),
2252 Applicability::MaybeIncorrect,
2254 // We don't care about the other suggestions.
2255 alt_rcvr_sugg = true;
2261 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2265 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2267 let mut arbitrary_rcvr = vec![];
2268 // There are no traits implemented, so lets suggest some traits to
2269 // implement, by finding ones that have the item name, and are
2270 // legal to implement.
2271 let mut candidates = all_traits(self.tcx)
2273 // Don't issue suggestions for unstable traits since they're
2274 // unlikely to be implementable anyway
2275 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2276 Some(attr) => attr.level.is_stable(),
2280 // Static candidates are already implemented, and known not to work
2281 // Do not suggest them again
2282 static_candidates.iter().all(|sc| match *sc {
2283 CandidateSource::Trait(def_id) => def_id != info.def_id,
2284 CandidateSource::Impl(def_id) => {
2285 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2290 // We approximate the coherence rules to only suggest
2291 // traits that are legal to implement by requiring that
2292 // either the type or trait is local. Multi-dispatch means
2293 // this isn't perfect (that is, there are cases when
2294 // implementing a trait would be legal but is rejected
2296 unsatisfied_predicates.iter().all(|(p, _, _)| {
2297 match p.kind().skip_binder() {
2298 // Hide traits if they are present in predicates as they can be fixed without
2299 // having to implement them.
2300 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2301 t.def_id() == info.def_id
2303 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2304 p.projection_ty.def_id == info.def_id
2308 }) && (type_is_local || info.def_id.is_local())
2310 .associated_value(info.def_id, item_name)
2312 if let ty::AssocKind::Fn = item.kind {
2316 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2317 if let Some(hir::Node::TraitItem(hir::TraitItem {
2318 kind: hir::TraitItemKind::Fn(fn_sig, method),
2320 })) = id.map(|id| self.tcx.hir().get(id))
2322 let self_first_arg = match method {
2323 hir::TraitFn::Required([ident, ..]) => {
2324 ident.name == kw::SelfLower
2326 hir::TraitFn::Provided(body_id) => {
2327 self.tcx.hir().body(*body_id).params.first().map_or(
2332 hir::PatKind::Binding(_, _, ident, _)
2333 if ident.name == kw::SelfLower
2341 if !fn_sig.decl.implicit_self.has_implicit_self()
2344 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2345 arbitrary_rcvr.push(ty.span);
2351 // We only want to suggest public or local traits (#45781).
2352 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2356 .collect::<Vec<_>>();
2357 for span in &arbitrary_rcvr {
2360 "the method might not be found because of this arbitrary self type",
2367 if !candidates.is_empty() {
2368 // Sort from most relevant to least relevant.
2369 candidates.sort_by(|a, b| a.cmp(b).reverse());
2372 let param_type = match rcvr_ty.kind() {
2373 ty::Param(param) => Some(param),
2374 ty::Ref(_, ty, _) => match ty.kind() {
2375 ty::Param(param) => Some(param),
2380 err.help(if param_type.is_some() {
2381 "items from traits can only be used if the type parameter is bounded by the trait"
2383 "items from traits can only be used if the trait is implemented and in scope"
2385 let candidates_len = candidates.len();
2386 let message = |action| {
2388 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2391 if candidates_len == 1 { "trait defines" } else { "traits define" },
2393 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2397 // Obtain the span for `param` and use it for a structured suggestion.
2398 if let Some(param) = param_type {
2399 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2400 let type_param = generics.type_param(param, self.tcx);
2401 let hir = self.tcx.hir();
2402 if let Some(def_id) = type_param.def_id.as_local() {
2403 let id = hir.local_def_id_to_hir_id(def_id);
2404 // Get the `hir::Param` to verify whether it already has any bounds.
2405 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2406 // instead we suggest `T: Foo + Bar` in that case.
2408 Node::GenericParam(param) => {
2414 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2415 let (sp, mut introducer) = if let Some(span) =
2416 ast_generics.bounds_span_for_suggestions(def_id)
2418 (span, Introducer::Plus)
2419 } else if let Some(colon_span) = param.colon_span {
2420 (colon_span.shrink_to_hi(), Introducer::Nothing)
2422 (param.span.shrink_to_hi(), Introducer::Colon)
2426 hir::GenericParamKind::Type { synthetic: true, .. },
2428 introducer = Introducer::Plus
2430 let trait_def_ids: FxHashSet<DefId> = ast_generics
2431 .bounds_for_param(def_id)
2432 .flat_map(|bp| bp.bounds.iter())
2433 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2435 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2436 err.span_suggestions(
2439 "restrict type parameter `{}` with",
2442 candidates.iter().map(|t| {
2446 Introducer::Plus => " +",
2447 Introducer::Colon => ":",
2448 Introducer::Nothing => "",
2450 self.tcx.def_path_str(t.def_id),
2453 Applicability::MaybeIncorrect,
2458 Node::Item(hir::Item {
2459 kind: hir::ItemKind::Trait(.., bounds, _),
2463 let (sp, sep, article) = if bounds.is_empty() {
2464 (ident.span.shrink_to_hi(), ":", "a")
2466 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2468 err.span_suggestions(
2470 &message(format!("add {} supertrait for", article)),
2471 candidates.iter().map(|t| {
2472 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2474 Applicability::MaybeIncorrect,
2483 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2484 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2485 // cases where a positive bound implies a negative impl.
2486 (candidates, Vec::new())
2487 } else if let Some(simp_rcvr_ty) =
2488 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2490 let mut potential_candidates = Vec::new();
2491 let mut explicitly_negative = Vec::new();
2492 for candidate in candidates {
2493 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2496 .all_impls(candidate.def_id)
2498 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2501 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2503 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2504 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2507 explicitly_negative.push(candidate);
2509 potential_candidates.push(candidate);
2512 (potential_candidates, explicitly_negative)
2514 // We don't know enough about `recv_ty` to make proper suggestions.
2515 (candidates, Vec::new())
2518 let action = if let Some(param) = param_type {
2519 format!("restrict type parameter `{}` with", param)
2521 // FIXME: it might only need to be imported into scope, not implemented.
2522 "implement".to_string()
2524 match &potential_candidates[..] {
2526 [trait_info] if trait_info.def_id.is_local() => {
2528 self.tcx.def_span(trait_info.def_id),
2530 "`{}` defines an item `{}`, perhaps you need to {} it",
2531 self.tcx.def_path_str(trait_info.def_id),
2538 let mut msg = message(action);
2539 for (i, trait_info) in trait_infos.iter().enumerate() {
2540 msg.push_str(&format!(
2541 "\ncandidate #{}: `{}`",
2543 self.tcx.def_path_str(trait_info.def_id),
2549 match &explicitly_negative[..] {
2553 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2554 self.tcx.def_path_str(trait_info.def_id),
2560 let mut msg = format!(
2561 "the following traits define an item `{}`, but are explicitly unimplemented:",
2564 for trait_info in trait_infos {
2565 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2573 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2574 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2575 pub(crate) fn suggest_else_fn_with_closure(
2577 err: &mut Diagnostic,
2578 expr: &hir::Expr<'_>,
2582 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2583 else { return false; };
2585 if !self.can_coerce(output, expected) {
2589 let parent = self.tcx.hir().get_parent_node(expr.hir_id);
2590 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2591 let hir::ExprKind::MethodCall(
2592 hir::PathSegment { ident: method_name, .. },
2596 ) = call_expr.kind &&
2597 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2598 let new_name = Ident {
2599 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2600 span: method_name.span,
2602 let probe = self.lookup_probe(
2606 ProbeScope::TraitsInScope,
2609 // check the method arguments number
2610 if let Ok(pick) = probe &&
2611 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2612 let fn_args = fn_sig.skip_binder().inputs() &&
2613 fn_args.len() == args.len() + 1 {
2614 err.span_suggestion_verbose(
2615 method_name.span.shrink_to_hi(),
2616 &format!("try calling `{}` instead", new_name.name.as_str()),
2618 Applicability::MaybeIncorrect,
2626 /// Checks whether there is a local type somewhere in the chain of
2627 /// autoderefs of `rcvr_ty`.
2628 fn type_derefs_to_local(
2632 source: SelfSource<'tcx>,
2634 fn is_local(ty: Ty<'_>) -> bool {
2636 ty::Adt(def, _) => def.did().is_local(),
2637 ty::Foreign(did) => did.is_local(),
2638 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2639 ty::Param(_) => true,
2641 // Everything else (primitive types, etc.) is effectively
2642 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2643 // the noise from these sort of types is usually just really
2644 // annoying, rather than any sort of help).
2649 // This occurs for UFCS desugaring of `T::method`, where there is no
2650 // receiver expression for the method call, and thus no autoderef.
2651 if let SelfSource::QPath(_) = source {
2652 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2655 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2659 #[derive(Copy, Clone, Debug)]
2660 pub enum SelfSource<'a> {
2661 QPath(&'a hir::Ty<'a>),
2662 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2665 #[derive(Copy, Clone)]
2666 pub struct TraitInfo {
2670 impl PartialEq for TraitInfo {
2671 fn eq(&self, other: &TraitInfo) -> bool {
2672 self.cmp(other) == Ordering::Equal
2675 impl Eq for TraitInfo {}
2676 impl PartialOrd for TraitInfo {
2677 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2678 Some(self.cmp(other))
2681 impl Ord for TraitInfo {
2682 fn cmp(&self, other: &TraitInfo) -> Ordering {
2683 // Local crates are more important than remote ones (local:
2684 // `cnum == 0`), and otherwise we throw in the defid for totality.
2686 let lhs = (other.def_id.krate, other.def_id);
2687 let rhs = (self.def_id.krate, self.def_id);
2692 /// Retrieves all traits in this crate and any dependent crates,
2693 /// and wraps them into `TraitInfo` for custom sorting.
2694 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2695 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2698 fn print_disambiguation_help<'tcx>(
2700 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2701 err: &mut Diagnostic,
2704 kind: ty::AssocKind,
2707 candidate: Option<usize>,
2708 source_map: &source_map::SourceMap,
2709 fn_has_self_parameter: bool,
2711 let mut applicability = Applicability::MachineApplicable;
2712 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2715 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2716 std::iter::once(receiver)
2718 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2719 applicability = Applicability::HasPlaceholders;
2722 .collect::<Vec<_>>()
2725 let trait_name = if !fn_has_self_parameter {
2726 format!("<{} as {}>", rcvr_ty, trait_name)
2730 (span, format!("{}::{}{}", trait_name, item_name, args))
2732 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2734 err.span_suggestion_verbose(
2737 "disambiguate the {} for {}",
2738 kind.as_def_kind().descr(def_id),
2739 if let Some(candidate) = candidate {
2740 format!("candidate #{}", candidate)
2742 "the candidate".to_string()