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