1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
5 use crate::Expectation;
7 use rustc_ast::ast::Mutability;
8 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9 use rustc_errors::StashKey;
11 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
15 use rustc_hir::def::DefKind;
16 use rustc_hir::def_id::DefId;
17 use rustc_hir::lang_items::LangItem;
18 use rustc_hir::PatKind::Binding;
19 use rustc_hir::PathSegment;
20 use rustc_hir::{ExprKind, Node, QPath};
21 use rustc_infer::infer::{
22 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
25 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
26 use rustc_middle::traits::util::supertraits;
27 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
28 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
29 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
30 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
31 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
32 use rustc_span::symbol::{kw, sym, Ident};
33 use rustc_span::Symbol;
34 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
35 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
36 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
37 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
38 use rustc_trait_selection::traits::{
39 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
42 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
43 use super::{CandidateSource, MethodError, NoMatchData};
44 use rustc_hir::intravisit::Visitor;
45 use std::cmp::Ordering;
48 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
49 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
52 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
53 // so we look for these beforehand.
54 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
55 // If it's not a simple function, look for things which implement `FnOnce`.
57 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
61 // This conditional prevents us from asking to call errors and unresolved types.
62 // It might seem that we can use `predicate_must_hold_modulo_regions`,
63 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
64 // type resolution always gives a "maybe" here.
65 if self.autoderef(span, ty).any(|(ty, _)| {
66 info!("check deref {:?} error", ty);
67 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
72 self.autoderef(span, ty).any(|(ty, _)| {
73 info!("check deref {:?} impl FnOnce", ty);
75 let trait_ref = tcx.mk_trait_ref(
79 self.next_ty_var(TypeVariableOrigin {
80 kind: TypeVariableOriginKind::MiscVariable,
85 let poly_trait_ref = ty::Binder::dummy(trait_ref);
86 let obligation = Obligation::misc(
91 poly_trait_ref.without_const(),
93 self.predicate_may_hold(&obligation)
100 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
101 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
104 #[instrument(level = "debug", skip(self))]
105 pub fn report_method_error(
110 source: SelfSource<'tcx>,
111 error: MethodError<'tcx>,
112 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
113 expected: Expectation<'tcx>,
114 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
115 // Avoid suggestions when we don't know what's going on.
116 if rcvr_ty.references_error() {
120 let sugg_span = if let SelfSource::MethodCall(expr) = source {
121 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
122 self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)).span
128 MethodError::NoMatch(mut no_match_data) => {
129 return self.report_no_match_method_error(
141 MethodError::Ambiguity(mut sources) => {
142 let mut err = struct_span_err!(
146 "multiple applicable items in scope"
148 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
150 self.note_candidates_on_method_error(
162 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
163 let kind = kind.descr(def_id);
164 let mut err = struct_span_err!(
168 "{} `{}` is private",
172 err.span_label(item_name.span, &format!("private {}", kind));
176 .span_if_local(def_id)
177 .unwrap_or_else(|| self.tcx.def_span(def_id));
178 err.span_label(sp, &format!("private {} defined here", kind));
179 self.suggest_valid_traits(&mut err, out_of_scope_traits);
183 MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
184 let msg = if needs_mut {
185 with_forced_trimmed_paths!(format!(
186 "the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
189 format!("the `{item_name}` method cannot be invoked on a trait object")
191 let mut err = self.sess().struct_span_err(span, &msg);
193 err.span_label(bound_span, "this has a `Sized` requirement");
195 if !candidates.is_empty() {
197 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
198 add a `use` for {one_of_them}:",
199 an = if candidates.len() == 1 { "an" } else { "" },
200 s = pluralize!(candidates.len()),
201 were = pluralize!("was", candidates.len()),
202 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
204 self.suggest_use_candidates(&mut err, help, candidates);
206 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
208 let trait_type = self.tcx.mk_ref(
210 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
212 let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
213 let mut kind = &self_expr.kind;
214 while let hir::ExprKind::AddrOf(_, _, expr)
215 | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
219 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
220 && let hir::def::Res::Local(hir_id) = path.res
221 && let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
222 && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
223 && let Some(node) = self.tcx.hir().find_parent(p.hir_id)
224 && let Some(decl) = node.fn_decl()
225 && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
226 && let hir::TyKind::Ref(_, mut_ty) = &ty.kind
227 && let hir::Mutability::Not = mut_ty.mutbl
229 err.span_suggestion_verbose(
230 mut_ty.ty.span.shrink_to_lo(),
233 Applicability::MachineApplicable,
243 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
248 pub fn report_no_match_method_error(
253 source: SelfSource<'tcx>,
254 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
256 no_match_data: &mut NoMatchData<'tcx>,
257 expected: Expectation<'tcx>,
258 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
259 let mode = no_match_data.mode;
261 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
262 let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
263 let is_method = mode == Mode::MethodCall;
264 let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
265 let similar_candidate = no_match_data.similar_candidate;
266 let item_kind = if is_method {
268 } else if rcvr_ty.is_enum() {
269 "variant or associated item"
271 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
272 (Some(name), false) if name.is_lowercase() => "function or associated item",
273 (Some(_), false) => "associated item",
274 (Some(_), true) | (None, false) => "variant or associated item",
275 (None, true) => "variant",
279 if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
280 || self.suggest_constraining_numerical_ty(
281 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
286 span = item_name.span;
288 // Don't show generic arguments when the method can't be found in any implementation (#81576).
289 let mut ty_str_reported = ty_str.clone();
290 if let ty::Adt(_, generics) = rcvr_ty.kind() {
291 if generics.len() > 0 {
292 let mut autoderef = self.autoderef(span, rcvr_ty);
293 let candidate_found = autoderef.any(|(ty, _)| {
294 if let ty::Adt(adt_def, _) = ty.kind() {
296 .inherent_impls(adt_def.did())
298 .any(|def_id| self.associated_value(*def_id, item_name).is_some())
303 let has_deref = autoderef.step_count() > 0;
304 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
305 if let Some((path_string, _)) = ty_str.split_once('<') {
306 ty_str_reported = path_string.to_string();
312 let mut err = struct_span_err!(
316 "no {} named `{}` found for {} `{}` in the current scope",
319 rcvr_ty.prefix_string(self.tcx),
322 if rcvr_ty.references_error() {
323 err.downgrade_to_delayed_bug();
326 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
327 self.suggest_await_before_method(
328 &mut err, item_name, rcvr_ty, cal, span, expected.only_has_type(self),
332 tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
336 "you are looking for the module in `std`, not the primitive type",
338 Applicability::MachineApplicable,
341 if let ty::RawPtr(_) = &rcvr_ty.kind() {
343 "try using `<*const T>::as_ref()` to get a reference to the \
344 type behind the pointer: https://doc.rust-lang.org/std/\
345 primitive.pointer.html#method.as_ref",
348 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
349 to invalid or uninitialized memory is undefined behavior",
353 let ty_span = match rcvr_ty.kind() {
354 ty::Param(param_type) => {
355 Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
357 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
360 if let Some(span) = ty_span {
364 "{item_kind} `{item_name}` not found for this {}",
365 rcvr_ty.prefix_string(self.tcx)
370 if let SelfSource::MethodCall(rcvr_expr) = source {
371 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
373 self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id));
374 let probe = self.lookup_probe_for_diagnostic(
378 ProbeScope::AllTraits,
379 expected.only_has_type(self),
385 let mut custom_span_label = false;
387 let static_candidates = &mut no_match_data.static_candidates;
388 if !static_candidates.is_empty() {
390 "found the following associated functions; to be used as methods, \
391 functions must have a `self` parameter",
393 err.span_label(span, "this is an associated function, not a method");
394 custom_span_label = true;
396 if static_candidates.len() == 1 {
397 self.suggest_associated_call_syntax(
406 self.note_candidates_on_method_error(
415 } else if static_candidates.len() > 1 {
416 self.note_candidates_on_method_error(
427 let mut bound_spans = vec![];
428 let mut restrict_type_params = false;
429 let mut unsatisfied_bounds = false;
430 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
431 let msg = "consider using `len` instead";
432 if let SelfSource::MethodCall(_expr) = source {
433 err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
435 err.span_label(span, msg);
437 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
438 let iterator_trait = self.tcx.def_path_str(iterator_trait);
440 "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
443 } else if !unsatisfied_predicates.is_empty() {
444 let mut type_params = FxHashMap::default();
446 // Pick out the list of unimplemented traits on the receiver.
447 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
448 let mut unimplemented_traits = FxHashMap::default();
449 let mut unimplemented_traits_only = true;
450 for (predicate, _parent_pred, cause) in unsatisfied_predicates {
451 if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
452 (predicate.kind().skip_binder(), cause.as_ref())
454 if p.trait_ref.self_ty() != rcvr_ty {
455 // This is necessary, not just to keep the errors clean, but also
456 // because our derived obligations can wind up with a trait ref that
457 // requires a different param_env to be correctly compared.
460 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
461 predicate.kind().rebind(p.trait_ref),
463 cause: cause.clone(),
464 param_env: self.param_env,
465 predicate: *predicate,
472 // Make sure that, if any traits other than the found ones were involved,
473 // we don't don't report an unimplemented trait.
474 // We don't want to say that `iter::Cloned` is not an iterator, just
475 // because of some non-Clone item being iterated over.
476 for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
477 match predicate.kind().skip_binder() {
478 ty::PredicateKind::Clause(ty::Clause::Trait(p))
479 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
481 unimplemented_traits_only = false;
487 let mut collect_type_param_suggestions =
488 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
489 // We don't care about regions here, so it's fine to skip the binder here.
490 if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
491 (self_ty.kind(), parent_pred.kind().skip_binder())
493 let hir = self.tcx.hir();
494 let node = match p.trait_ref.self_ty().kind() {
496 // Account for `fn` items like in `issue-35677.rs` to
497 // suggest restricting its type params.
498 Some(hir.get_by_def_id(self.body_id))
501 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
505 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
506 && let Some(g) = kind.generics()
509 g.tail_span_for_predicate_suggestion(),
510 g.add_where_or_trailing_comma(),
514 .or_insert_with(FxHashSet::default)
515 .insert(obligation.to_owned());
521 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
523 "doesn't satisfy `{}`",
524 if obligation.len() > 50 { quiet } else { obligation }
526 match &self_ty.kind() {
527 // Point at the type that couldn't satisfy the bound.
528 ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
529 // Point at the trait object that couldn't satisfy the bound.
530 ty::Dynamic(preds, _, _) => {
531 for pred in preds.iter() {
532 match pred.skip_binder() {
533 ty::ExistentialPredicate::Trait(tr) => {
534 bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
536 ty::ExistentialPredicate::Projection(_)
537 | ty::ExistentialPredicate::AutoTrait(_) => {}
541 // Point at the closure that couldn't satisfy the bound.
542 ty::Closure(def_id, _) => bound_spans
543 .push((tcx.def_span(*def_id), 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::default();
590 for (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 if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
597 Some((p, parent, data.impl_def_id, data))
602 match self.tcx.hir().get_if_local(impl_def_id) {
603 // Unmet obligation comes from a `derive` macro, point at it once to
604 // avoid multiple span labels pointing at the same place.
605 Some(Node::Item(hir::Item {
606 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
609 self_ty.span.ctxt().outer_expn_data().kind,
610 ExpnKind::Macro(MacroKind::Derive, _)
612 of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
613 Some(ExpnKind::Macro(MacroKind::Derive, _))
616 let span = self_ty.span.ctxt().outer_expn_data().call_site;
617 let entry = spanned_predicates.entry(span);
618 let entry = entry.or_insert_with(|| {
619 (FxHashSet::default(), FxHashSet::default(), Vec::new())
621 entry.0.insert(span);
624 "unsatisfied trait bound introduced in this `derive` macro",
630 // Unmet obligation coming from an `impl`.
631 Some(Node::Item(hir::Item {
632 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
637 unsatisfied_predicates.iter().any(|(pred, _, _)| {
638 match pred.kind().skip_binder() {
639 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
640 Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
641 && pred.polarity == ty::ImplPolarity::Positive
646 for param in generics.params {
647 if param.span == cause.span && sized_pred {
648 let (sp, sugg) = match param.colon_span {
649 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
650 None => (param.span.shrink_to_hi(), ": ?Sized"),
652 err.span_suggestion_verbose(
654 "consider relaxing the type parameter's implicit `Sized` bound",
656 Applicability::MachineApplicable,
660 if let Some(pred) = parent_p {
661 // Done to add the "doesn't satisfy" `span_label`.
662 let _ = format_pred(*pred);
665 let entry = spanned_predicates.entry(self_ty.span);
666 let entry = entry.or_insert_with(|| {
667 (FxHashSet::default(), FxHashSet::default(), Vec::new())
670 if cause.span != *item_span {
671 entry.0.insert(cause.span);
672 entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
674 if let Some(trait_ref) = of_trait {
675 entry.0.insert(trait_ref.path.span);
677 entry.0.insert(self_ty.span);
679 if let Some(trait_ref) = of_trait {
680 entry.1.insert((trait_ref.path.span, ""));
682 entry.1.insert((self_ty.span, ""));
684 Some(Node::Item(hir::Item {
685 kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
689 tcx.sess.delay_span_bug(
691 "auto trait is invoked with no method error, but no error reported?",
694 Some(Node::Item(hir::Item {
695 ident, kind: hir::ItemKind::Trait(..), ..
698 let entry = spanned_predicates.entry(ident.span);
699 let entry = entry.or_insert_with(|| {
700 (FxHashSet::default(), FxHashSet::default(), Vec::new())
702 entry.0.insert(cause.span);
703 entry.1.insert((ident.span, ""));
704 entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
707 Some(node) => unreachable!("encountered `{node:?}`"),
711 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
712 spanned_predicates.sort_by_key(|(span, _)| *span);
713 for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
714 let mut preds: Vec<_> = predicates
716 .filter_map(|pred| format_pred(**pred))
717 .map(|(p, _)| format!("`{}`", p))
721 let msg = if let [pred] = &preds[..] {
722 format!("trait bound {} was not satisfied", pred)
724 format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
726 let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
727 for (sp, label) in span_labels {
728 span.push_span_label(sp, label);
730 err.span_note(span, &msg);
731 unsatisfied_bounds = true;
734 let mut suggested_bounds = FxHashSet::default();
735 // The requirements that didn't have an `impl` span to show.
736 let mut bound_list = unsatisfied_predicates
738 .filter_map(|(pred, parent_pred, _cause)| {
739 let mut suggested = false;
740 format_pred(*pred).map(|(p, self_ty)| {
741 if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
742 // We don't suggest `PartialEq` when we already suggest `Eq`.
743 } else if !suggested_bounds.contains(pred) {
744 if collect_type_param_suggestions(self_ty, *pred, &p) {
746 suggested_bounds.insert(pred);
751 None => format!("`{}`", &p),
752 Some(parent_pred) => match format_pred(*parent_pred) {
753 None => format!("`{}`", &p),
754 Some((parent_p, _)) => {
756 && !suggested_bounds.contains(pred)
757 && !suggested_bounds.contains(parent_pred)
759 if collect_type_param_suggestions(
764 suggested_bounds.insert(pred);
767 format!("`{}`\nwhich is required by `{}`", p, parent_p)
775 .filter(|(_, pred)| !skip_list.contains(&pred))
778 .collect::<Vec<(usize, String)>>();
780 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
781 restrict_type_params = true;
782 // #74886: Sort here so that the output is always the same.
783 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
785 err.span_suggestion_verbose(
788 "consider restricting the type parameter{s} to satisfy the \
790 s = pluralize!(obligations.len())
792 format!("{} {}", add_where_or_comma, obligations.join(", ")),
793 Applicability::MaybeIncorrect,
797 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
798 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
799 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
801 if !bound_list.is_empty() || !skip_list.is_empty() {
803 bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
804 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
805 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
806 let (primary_message, label) = if unimplemented_traits.len() == 1
807 && unimplemented_traits_only
812 .map(|(_, (trait_ref, obligation))| {
813 if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
818 let OnUnimplementedNote { message, label, .. } =
819 self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
826 let primary_message = primary_message.unwrap_or_else(|| {
828 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
829 but its trait bounds were not satisfied"
832 err.set_primary_message(&primary_message);
833 if let Some(label) = label {
834 custom_span_label = true;
835 err.span_label(span, label);
837 if !bound_list.is_empty() {
839 "the following trait bounds were not satisfied:\n{bound_list}"
842 self.suggest_derive(&mut err, &unsatisfied_predicates);
844 unsatisfied_bounds = true;
848 let label_span_not_found = |err: &mut Diagnostic| {
849 if unsatisfied_predicates.is_empty() {
850 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
851 let is_string_or_ref_str = match rcvr_ty.kind() {
852 ty::Ref(_, ty, _) => {
856 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
859 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
862 if is_string_or_ref_str && item_name.name == sym::iter {
863 err.span_suggestion_verbose(
865 "because of the in-memory representation of `&str`, to obtain \
866 an `Iterator` over each of its codepoint use method `chars`",
868 Applicability::MachineApplicable,
871 if let ty::Adt(adt, _) = rcvr_ty.kind() {
872 let mut inherent_impls_candidate = self
874 .inherent_impls(adt.did())
878 if let Some(assoc) = self.associated_value(*def_id, item_name) {
879 // Check for both mode is the same so we avoid suggesting
880 // incorrect associated item.
881 match (mode, assoc.fn_has_self_parameter, source) {
882 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
883 // We check that the suggest type is actually
884 // different from the received one
885 // So we avoid suggestion method with Box<Self>
887 self.tcx.at(span).type_of(*def_id) != rcvr_ty
888 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
890 (Mode::Path, false, _) => true,
897 .collect::<Vec<_>>();
898 if !inherent_impls_candidate.is_empty() {
899 inherent_impls_candidate.sort();
900 inherent_impls_candidate.dedup();
902 // number of type to shows at most.
903 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
904 let type_candidates = inherent_impls_candidate
908 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
912 let additional_types = if inherent_impls_candidate.len() > limit {
913 format!("\nand {} more types", inherent_impls_candidate.len() - limit)
918 "the {item_kind} was found for\n{}{}",
919 type_candidates, additional_types
925 if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
928 format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
933 // If the method name is the name of a field with a function or closure type,
934 // give a helping note that it has to be called as `(x.f)(...)`.
935 if let SelfSource::MethodCall(expr) = source {
936 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
937 && similar_candidate.is_none()
938 && !custom_span_label
940 label_span_not_found(&mut err);
942 } else if !custom_span_label {
943 label_span_not_found(&mut err);
946 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
947 // can't be called due to `typeof(expr): Clone` not holding.
948 if unsatisfied_predicates.is_empty() {
949 self.suggest_calling_method_on_field(
955 expected.only_has_type(self),
959 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
963 for (span, msg) in bound_spans.into_iter() {
964 err.span_label(span, &msg);
967 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
969 self.suggest_traits_to_import(
974 args.map(|(_, args)| args.len() + 1),
976 no_match_data.out_of_scope_traits.clone(),
977 &unsatisfied_predicates,
980 expected.only_has_type(self),
984 // Don't emit a suggestion if we found an actual method
985 // that had unsatisfied trait bounds
986 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
987 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
988 if let Some(suggestion) = lev_distance::find_best_match_for_name(
989 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
995 "there is a variant with a similar name",
997 Applicability::MaybeIncorrect,
1002 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
1003 let msg = "remove this method call";
1004 let mut fallback_span = true;
1005 if let SelfSource::MethodCall(expr) = source {
1006 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1007 if let Some(span) = call_expr.span.trim_start(expr.span) {
1008 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1009 fallback_span = false;
1013 err.span_label(span, msg);
1015 } else if let Some(similar_candidate) = similar_candidate {
1016 // Don't emit a suggestion if we found an actual method
1017 // that had unsatisfied trait bounds
1018 if unsatisfied_predicates.is_empty() {
1019 let def_kind = similar_candidate.kind.as_def_kind();
1020 // Methods are defined within the context of a struct and their first parameter is always self,
1021 // which represents the instance of the struct the method is being called on
1022 // Associated functions don’t take self as a parameter and
1023 // they are not methods because they don’t have an instance of the struct to work with.
1024 if def_kind == DefKind::AssocFn && similar_candidate.fn_has_self_parameter {
1025 err.span_suggestion(
1027 "there is a method with a similar name",
1028 similar_candidate.name,
1029 Applicability::MaybeIncorrect,
1032 err.span_suggestion(
1035 "there is {} {} with a similar name",
1037 def_kind.descr(similar_candidate.def_id),
1039 similar_candidate.name,
1040 Applicability::MaybeIncorrect,
1046 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name, expected);
1050 fn note_candidates_on_method_error(
1054 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1056 err: &mut Diagnostic,
1057 sources: &mut Vec<CandidateSource>,
1058 sugg_span: Option<Span>,
1062 // Dynamic limit to avoid hiding just one candidate, which is silly.
1063 let limit = if sources.len() == 5 { 5 } else { 4 };
1065 for (idx, source) in sources.iter().take(limit).enumerate() {
1067 CandidateSource::Impl(impl_did) => {
1068 // Provide the best span we can. Use the item, if local to crate, else
1069 // the impl, if local to crate (item may be defaulted), else nothing.
1070 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
1071 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
1072 self.associated_value(impl_trait_ref.skip_binder().def_id, item_name)
1077 let note_span = if item.def_id.is_local() {
1078 Some(self.tcx.def_span(item.def_id))
1079 } else if impl_did.is_local() {
1080 Some(self.tcx.def_span(impl_did))
1085 let impl_ty = self.tcx.at(span).type_of(impl_did);
1087 let insertion = match self.tcx.impl_trait_ref(impl_did) {
1088 None => String::new(),
1089 Some(trait_ref) => {
1091 " of the trait `{}`",
1092 self.tcx.def_path_str(trait_ref.skip_binder().def_id)
1097 let (note_str, idx) = if sources.len() > 1 {
1100 "candidate #{} is defined in an impl{} for the type `{}`",
1110 "the candidate is defined in an impl{} for the type `{}`",
1116 if let Some(note_span) = note_span {
1117 // We have a span pointing to the method. Show note with snippet.
1118 err.span_note(note_span, ¬e_str);
1120 err.note(¬e_str);
1122 if let Some(sugg_span) = sugg_span
1123 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
1124 let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
1126 let ty = match item.kind {
1127 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
1128 ty::AssocKind::Fn => self
1130 .fn_sig(item.def_id)
1135 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
1137 .unwrap_or(rcvr_ty),
1139 print_disambiguation_help(
1149 self.tcx.sess.source_map(),
1150 item.fn_has_self_parameter,
1154 CandidateSource::Trait(trait_did) => {
1155 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
1156 let item_span = self.tcx.def_span(item.def_id);
1157 let idx = if sources.len() > 1 {
1159 "candidate #{} is defined in the trait `{}`",
1161 self.tcx.def_path_str(trait_did)
1163 err.span_note(item_span, msg);
1167 "the candidate is defined in the trait `{}`",
1168 self.tcx.def_path_str(trait_did)
1170 err.span_note(item_span, msg);
1173 if let Some(sugg_span) = sugg_span {
1174 let path = self.tcx.def_path_str(trait_did);
1175 print_disambiguation_help(
1185 self.tcx.sess.source_map(),
1186 item.fn_has_self_parameter,
1192 if sources.len() > limit {
1193 err.note(&format!("and {} others", sources.len() - limit));
1197 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1198 /// doesn't take a `self` receiver.
1199 fn suggest_associated_call_syntax(
1201 err: &mut Diagnostic,
1202 static_candidates: &Vec<CandidateSource>,
1204 source: SelfSource<'tcx>,
1206 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1209 let mut has_unsuggestable_args = false;
1210 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1211 // When the "method" is resolved through dereferencing, we really want the
1212 // original type that has the associated function for accurate suggestions.
1214 let impl_ty = self.tcx.type_of(*impl_did);
1215 let target_ty = self
1216 .autoderef(sugg_span, rcvr_ty)
1217 .find(|(rcvr_ty, _)| {
1218 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1219 .types_may_unify(*rcvr_ty, impl_ty)
1221 .map_or(impl_ty, |(ty, _)| ty)
1223 if let ty::Adt(def, substs) = target_ty.kind() {
1224 // If there are any inferred arguments, (`{integer}`), we should replace
1225 // them with underscores to allow the compiler to infer them
1226 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1227 if !arg.is_suggestable(self.tcx, true) {
1228 has_unsuggestable_args = true;
1229 match arg.unpack() {
1230 GenericArgKind::Lifetime(_) => self
1231 .next_region_var(RegionVariableOrigin::MiscVariable(
1232 rustc_span::DUMMY_SP,
1235 GenericArgKind::Type(_) => self
1236 .next_ty_var(TypeVariableOrigin {
1237 span: rustc_span::DUMMY_SP,
1238 kind: TypeVariableOriginKind::MiscVariable,
1241 GenericArgKind::Const(arg) => self
1244 ConstVariableOrigin {
1245 span: rustc_span::DUMMY_SP,
1246 kind: ConstVariableOriginKind::MiscVariable,
1256 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1258 self.ty_to_value_string(target_ty)
1261 self.ty_to_value_string(rcvr_ty.peel_refs())
1263 if let SelfSource::MethodCall(_) = source {
1264 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1265 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1266 && assoc.kind == ty::AssocKind::Fn
1268 let sig = self.tcx.fn_sig(assoc.def_id).subst_identity();
1269 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1272 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1277 let mut applicability = Applicability::MachineApplicable;
1278 let args = if let Some((receiver, args)) = args {
1279 // The first arg is the same kind as the receiver
1280 let explicit_args = if first_arg.is_some() {
1281 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1283 // There is no `Self` kind to infer the arguments from
1284 if has_unsuggestable_args {
1285 applicability = Applicability::HasPlaceholders;
1287 args.iter().collect()
1291 first_arg.unwrap_or(""),
1298 .span_to_snippet(arg.span)
1299 .unwrap_or_else(|_| {
1300 applicability = Applicability::HasPlaceholders;
1303 .collect::<Vec<_>>()
1307 applicability = Applicability::HasPlaceholders;
1310 err.span_suggestion(
1312 "use associated function syntax instead",
1313 format!("{}::{}{}", ty_str, item_name, args),
1317 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1321 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1322 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1323 fn suggest_calling_field_as_fn(
1327 expr: &hir::Expr<'_>,
1329 err: &mut Diagnostic,
1332 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1333 ty::Adt(def, substs) if !def.is_enum() => {
1334 let variant = &def.non_enum_variant();
1335 tcx.find_field_index(item_name, variant).map(|index| {
1336 let field = &variant.fields[index];
1337 let field_ty = field.ty(tcx, substs);
1343 if let Some((field, field_ty)) = field_receiver {
1344 let scope = tcx.parent_module_from_def_id(self.body_id);
1345 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1348 if self.is_fn_ty(field_ty, span) {
1349 let expr_span = expr.span.to(item_name.span);
1350 err.multipart_suggestion(
1352 "to call the function stored in `{}`, \
1353 surround the field access with parentheses",
1357 (expr_span.shrink_to_lo(), '('.to_string()),
1358 (expr_span.shrink_to_hi(), ')'.to_string()),
1360 Applicability::MachineApplicable,
1363 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1365 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1366 err.span_suggestion(
1368 "remove the arguments",
1370 Applicability::MaybeIncorrect,
1376 let field_kind = if is_accessible { "field" } else { "private field" };
1377 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1383 /// Suggest possible range with adding parentheses, for example:
1384 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1385 fn suggest_wrapping_range_with_parens(
1389 source: SelfSource<'tcx>,
1394 if let SelfSource::MethodCall(expr) = source {
1395 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1396 if let Node::Expr(parent_expr) = parent {
1397 let lang_item = match parent_expr.kind {
1398 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1399 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1400 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1401 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1402 Some(LangItem::RangeToInclusive)
1406 ExprKind::Call(ref func, _) => match func.kind {
1407 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1408 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1409 Some(LangItem::RangeInclusiveStruct)
1416 if lang_item.is_none() {
1420 let span_included = match parent_expr.kind {
1421 hir::ExprKind::Struct(_, eps, _) => {
1422 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1424 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1425 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1433 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1435 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1437 let pick = self.lookup_probe_for_diagnostic(
1441 ProbeScope::AllTraits,
1445 let range_span = parent_expr.span.with_hi(expr.span.hi());
1446 tcx.sess.emit_err(errors::MissingParentheseInRange {
1448 ty_str: ty_str.to_string(),
1449 method_name: item_name.as_str().to_string(),
1450 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1451 func_name: item_name.name.as_str().to_string(),
1452 left: range_span.shrink_to_lo(),
1453 right: range_span.shrink_to_hi(),
1464 fn suggest_constraining_numerical_ty(
1468 source: SelfSource<'_>,
1474 let found_candidate = all_traits(self.tcx)
1476 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1477 let found_assoc = |ty: Ty<'tcx>| {
1478 simplify_type(tcx, ty, TreatParams::AsInfer)
1480 tcx.incoherent_impls(simp)
1482 .find_map(|&id| self.associated_value(id, item_name))
1486 let found_candidate = found_candidate
1487 || found_assoc(tcx.types.i8)
1488 || found_assoc(tcx.types.i16)
1489 || found_assoc(tcx.types.i32)
1490 || found_assoc(tcx.types.i64)
1491 || found_assoc(tcx.types.i128)
1492 || found_assoc(tcx.types.u8)
1493 || found_assoc(tcx.types.u16)
1494 || found_assoc(tcx.types.u32)
1495 || found_assoc(tcx.types.u64)
1496 || found_assoc(tcx.types.u128)
1497 || found_assoc(tcx.types.f32)
1498 || found_assoc(tcx.types.f32);
1500 && actual.is_numeric()
1501 && !actual.has_concrete_skeleton()
1502 && let SelfSource::MethodCall(expr) = source
1504 let mut err = struct_span_err!(
1508 "can't call {} `{}` on ambiguous numeric type `{}`",
1513 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1515 ExprKind::Lit(ref lit) => {
1520 .span_to_snippet(lit.span)
1521 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1523 // If this is a floating point literal that ends with '.',
1524 // get rid of it to stop this from becoming a member access.
1525 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1526 err.span_suggestion(
1529 "you must specify a concrete type for this numeric value, \
1533 format!("{snippet}_{concrete_type}"),
1534 Applicability::MaybeIncorrect,
1537 ExprKind::Path(QPath::Resolved(_, path)) => {
1539 if let hir::def::Res::Local(hir_id) = path.res {
1540 let span = tcx.hir().span(hir_id);
1541 let filename = tcx.sess.source_map().span_to_filename(span);
1544 self.tcx.hir().get_parent(hir_id);
1546 "you must specify a type for this binding, like `{}`",
1550 match (filename, parent_node) {
1553 Node::Local(hir::Local {
1554 source: hir::LocalSource::Normal,
1559 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1560 err.span_suggestion(
1561 // account for `let x: _ = 42;`
1565 format!(": {concrete_type}"),
1566 Applicability::MaybeIncorrect,
1570 err.span_label(span, msg);
1583 /// For code `rect::area(...)`,
1584 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1585 /// we try to suggest `rect.area()`
1586 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1587 debug!("suggest_assoc_method_call segs: {:?}", segs);
1588 let [seg1, seg2] = segs else { return; };
1589 let Some(mut diag) =
1590 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1593 let map = self.infcx.tcx.hir();
1594 let body_id = self.tcx.hir().body_owned_by(self.body_id);
1595 let body = map.body(body_id);
1596 struct LetVisitor<'a> {
1597 result: Option<&'a hir::Expr<'a>>,
1601 // FIXME: This really should be taking scoping, etc into account.
1602 impl<'v> Visitor<'v> for LetVisitor<'v> {
1603 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1604 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1605 && let Binding(_, _, ident, ..) = pat.kind
1606 && ident.name == self.ident_name
1608 self.result = *init;
1610 hir::intravisit::walk_stmt(self, ex);
1615 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1616 visitor.visit_body(&body);
1618 let parent = self.tcx.hir().parent_id(seg1.hir_id);
1619 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1620 && let Some(expr) = visitor.result
1621 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1623 let probe = self.lookup_probe_for_diagnostic(
1627 ProbeScope::TraitsInScope,
1631 let sm = self.infcx.tcx.sess.source_map();
1632 diag.span_suggestion_verbose(
1633 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1634 "you may have meant to call an instance method",
1636 Applicability::MaybeIncorrect,
1643 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1644 fn suggest_calling_method_on_field(
1646 err: &mut Diagnostic,
1647 source: SelfSource<'tcx>,
1651 return_type: Option<Ty<'tcx>>,
1653 if let SelfSource::MethodCall(expr) = source
1654 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1655 && let Some((fields, substs)) =
1656 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1658 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1660 let lang_items = self.tcx.lang_items();
1661 let never_mention_traits = [
1662 lang_items.clone_trait(),
1663 lang_items.deref_trait(),
1664 lang_items.deref_mut_trait(),
1665 self.tcx.get_diagnostic_item(sym::AsRef),
1666 self.tcx.get_diagnostic_item(sym::AsMut),
1667 self.tcx.get_diagnostic_item(sym::Borrow),
1668 self.tcx.get_diagnostic_item(sym::BorrowMut),
1670 let candidate_fields: Vec<_> = fields
1671 .filter_map(|candidate_field| {
1672 self.check_for_nested_field_satisfying(
1675 self.lookup_probe_for_diagnostic(
1679 ProbeScope::TraitsInScope,
1682 .map_or(false, |pick| {
1683 !never_mention_traits
1686 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1698 .map(|id| id.name.to_ident_string())
1699 .collect::<Vec<String>>()
1704 let len = candidate_fields.len();
1706 err.span_suggestions(
1707 item_name.span.shrink_to_lo(),
1709 "{} of the expressions' fields {} a method of the same name",
1710 if len > 1 { "some" } else { "one" },
1711 if len > 1 { "have" } else { "has" },
1713 candidate_fields.iter().map(|path| format!("{path}.")),
1714 Applicability::MaybeIncorrect,
1720 fn check_for_inner_self(
1722 err: &mut Diagnostic,
1723 source: SelfSource<'tcx>,
1728 let SelfSource::MethodCall(expr) = source else { return; };
1729 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1731 let ty::Adt(kind, substs) = actual.kind() else { return; };
1732 match kind.adt_kind() {
1733 ty::AdtKind::Enum => {
1734 let matching_variants: Vec<_> = kind
1737 .flat_map(|variant| {
1738 let [field] = &variant.fields[..] else { return None; };
1739 let field_ty = field.ty(tcx, substs);
1741 // Skip `_`, since that'll just lead to ambiguity.
1742 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1746 self.lookup_probe_for_diagnostic(
1750 ProbeScope::TraitsInScope,
1754 .map(|pick| (variant, field, pick))
1758 let ret_ty_matches = |diagnostic_item| {
1759 if let Some(ret_ty) = self
1762 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1763 && let ty::Adt(kind, _) = ret_ty.kind()
1764 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1772 match &matching_variants[..] {
1773 [(_, field, pick)] => {
1774 let self_ty = field.ty(tcx, substs);
1776 tcx.def_span(pick.item.def_id),
1777 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1779 let (article, kind, variant, question) =
1780 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1781 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1782 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1783 ("an", "Option", "None", ret_ty_matches(sym::Option))
1788 err.span_suggestion_verbose(
1789 expr.span.shrink_to_hi(),
1791 "use the `?` operator to extract the `{self_ty}` value, propagating \
1792 {article} `{kind}::{variant}` value to the caller"
1795 Applicability::MachineApplicable,
1798 err.span_suggestion_verbose(
1799 expr.span.shrink_to_hi(),
1801 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1802 panicking if the value is {article} `{kind}::{variant}`"
1804 ".expect(\"REASON\")",
1805 Applicability::HasPlaceholders,
1809 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1813 // Target wrapper types - types that wrap or pretend to wrap another type,
1814 // perhaps this inner type is meant to be called?
1815 ty::AdtKind::Struct | ty::AdtKind::Union => {
1816 let [first] = ***substs else { return; };
1817 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1818 let Ok(pick) = self.lookup_probe_for_diagnostic(
1822 ProbeScope::TraitsInScope,
1826 let name = self.ty_to_value_string(actual);
1827 let inner_id = kind.did();
1828 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1829 pick.autoref_or_ptr_adjustment
1836 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1837 err.help("use `with` or `try_with` to access thread local storage");
1838 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1840 "if this `{name}` has been initialized, \
1841 use one of the `assume_init` methods to access the inner value"
1843 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1844 let (suggestion, borrow_kind, panic_if) = match mutable {
1845 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1846 Some(Mutability::Mut) => {
1847 (".borrow_mut()", "mutably borrow", "any borrows exist")
1851 err.span_suggestion_verbose(
1852 expr.span.shrink_to_hi(),
1854 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1855 panicking if {panic_if}"
1858 Applicability::MaybeIncorrect,
1860 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1861 err.span_suggestion_verbose(
1862 expr.span.shrink_to_hi(),
1864 "use `.lock().unwrap()` to borrow the `{ty}`, \
1865 blocking the current thread until it can be acquired"
1868 Applicability::MaybeIncorrect,
1870 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1871 let (suggestion, borrow_kind) = match mutable {
1872 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1873 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1876 err.span_suggestion_verbose(
1877 expr.span.shrink_to_hi(),
1879 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1880 blocking the current thread until it can be acquired"
1883 Applicability::MaybeIncorrect,
1890 tcx.def_span(pick.item.def_id),
1891 &format!("the method `{item_name}` exists on the type `{ty}`"),
1897 pub(crate) fn note_unmet_impls_on_type(
1899 err: &mut Diagnostic,
1900 errors: Vec<FulfillmentError<'tcx>>,
1902 let all_local_types_needing_impls =
1903 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1904 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1905 ty::Adt(def, _) => def.did().is_local(),
1910 let mut preds: Vec<_> = errors
1912 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1913 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1917 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1920 .filter_map(|pred| match pred.self_ty().kind() {
1921 ty::Adt(def, _) => Some(def.did()),
1924 .collect::<FxHashSet<_>>();
1925 let mut spans: MultiSpan = def_ids
1927 .filter_map(|def_id| {
1928 let span = self.tcx.def_span(*def_id);
1929 if span.is_dummy() { None } else { Some(span) }
1931 .collect::<Vec<_>>()
1934 for pred in &preds {
1935 match pred.self_ty().kind() {
1936 ty::Adt(def, _) if def.did().is_local() => {
1937 spans.push_span_label(
1938 self.tcx.def_span(def.did()),
1939 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1946 if all_local_types_needing_impls && spans.primary_span().is_some() {
1947 let msg = if preds.len() == 1 {
1949 "an implementation of `{}` might be missing for `{}`",
1950 preds[0].trait_ref.print_only_trait_path(),
1955 "the following type{} would have to `impl` {} required trait{} for this \
1956 operation to be valid",
1957 pluralize!(def_ids.len()),
1958 if def_ids.len() == 1 { "its" } else { "their" },
1959 pluralize!(preds.len()),
1962 err.span_note(spans, &msg);
1965 let preds: Vec<_> = errors
1967 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1969 self.suggest_derive(err, &preds);
1972 pub fn suggest_derive(
1974 err: &mut Diagnostic,
1975 unsatisfied_predicates: &[(
1976 ty::Predicate<'tcx>,
1977 Option<ty::Predicate<'tcx>>,
1978 Option<ObligationCause<'tcx>>,
1981 let mut derives = Vec::<(String, Span, Symbol)>::new();
1982 let mut traits = Vec::new();
1983 for (pred, _, _) in unsatisfied_predicates {
1984 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1985 let adt = match trait_pred.self_ty().ty_adt_def() {
1986 Some(adt) if adt.did().is_local() => adt,
1989 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1990 let can_derive = match diagnostic_name {
1991 sym::Default => !adt.is_enum(),
1999 | sym::Debug => true,
2003 let self_name = trait_pred.self_ty().to_string();
2004 let self_span = self.tcx.def_span(adt.did());
2005 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
2006 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
2008 if let Some(parent_diagnostic_name) =
2009 self.tcx.get_diagnostic_name(super_trait.def_id())
2014 parent_diagnostic_name,
2019 derives.push((self_name, self_span, diagnostic_name));
2021 traits.push(trait_pred.def_id());
2024 traits.push(trait_pred.def_id());
2033 let mut derives_grouped = Vec::<(String, Span, String)>::new();
2034 for (self_name, self_span, trait_name) in derives.into_iter() {
2035 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2037 if last_self_name == &self_name {
2038 last_trait_names.push_str(format!(", {}", trait_name).as_str());
2042 derives_grouped.push((self_name, self_span, trait_name.to_string()));
2045 let len = traits.len();
2048 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
2049 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
2050 for (i, &did) in traits.iter().enumerate().skip(1) {
2052 names.push_str(", ");
2055 names.push_str(" and ");
2058 names.push_str(&self.tcx.def_path_str(did));
2063 &format!("the trait{} {} must be implemented", pluralize!(len), names),
2067 for (self_name, self_span, traits) in &derives_grouped {
2068 err.span_suggestion_verbose(
2069 self_span.shrink_to_lo(),
2070 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
2071 format!("#[derive({})]\n", traits),
2072 Applicability::MaybeIncorrect,
2077 fn check_for_deref_method(
2079 err: &mut Diagnostic,
2080 self_source: SelfSource<'tcx>,
2083 expected: Expectation<'tcx>,
2085 let SelfSource::QPath(ty) = self_source else { return; };
2086 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
2087 if let Ok(pick) = self.probe_for_name(
2090 expected.only_has_type(self),
2094 ProbeScope::TraitsInScope,
2096 if deref_ty.is_suggestable(self.tcx, true)
2097 // If this method receives `&self`, then the provided
2098 // argument _should_ coerce, so it's valid to suggest
2099 // just changing the path.
2100 && pick.item.fn_has_self_parameter
2101 && let Some(self_ty) =
2102 self.tcx.fn_sig(pick.item.def_id).subst_identity().inputs().skip_binder().get(0)
2105 let suggested_path = match deref_ty.kind() {
2113 | ty::Alias(ty::Projection, _)
2114 | ty::Param(_) => format!("{deref_ty}"),
2115 // we need to test something like <&[_]>::len or <(&[u32])>::len
2116 // and Vec::function();
2117 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2118 // but for Adt type like Vec::function()
2119 // we would suggest <[_]>::function();
2120 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
2121 _ => format!("<{deref_ty}>"),
2123 err.span_suggestion_verbose(
2125 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2127 Applicability::MaybeIncorrect,
2132 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2140 /// Print out the type for use in value namespace.
2141 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2143 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2144 _ => self.ty_to_string(ty),
2148 fn suggest_await_before_method(
2150 err: &mut Diagnostic,
2153 call: &hir::Expr<'_>,
2155 return_type: Option<Ty<'tcx>>,
2157 let output_ty = match self.get_impl_future_output_ty(ty) {
2158 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2162 self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
2163 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2165 err.span_suggestion_verbose(
2166 span.shrink_to_lo(),
2167 "consider `await`ing on the `Future` and calling the method on its `Output`",
2169 Applicability::MaybeIncorrect,
2174 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2175 let parent_map = self.tcx.visible_parent_map(());
2177 // Separate out candidates that must be imported with a glob, because they are named `_`
2178 // and cannot be referred with their identifier.
2179 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2180 if let Some(parent_did) = parent_map.get(trait_did) {
2181 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2182 if *parent_did != self.tcx.parent(*trait_did)
2185 .module_children(*parent_did)
2187 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2188 .all(|child| child.ident.name == kw::Underscore)
2197 let module_did = self.tcx.parent_module_from_def_id(self.body_id);
2198 let (module, _, _) = self.tcx.hir().get_module(module_did);
2199 let span = module.spans.inject_use_span;
2201 let path_strings = candidates.iter().map(|trait_did| {
2202 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2205 let glob_path_strings = globs.iter().map(|trait_did| {
2206 let parent_did = parent_map.get(trait_did).unwrap();
2208 "use {}::*; // trait {}\n",
2209 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2210 self.tcx.item_name(*trait_did),
2214 err.span_suggestions(
2217 path_strings.chain(glob_path_strings),
2218 Applicability::MaybeIncorrect,
2222 fn suggest_valid_traits(
2224 err: &mut Diagnostic,
2225 valid_out_of_scope_traits: Vec<DefId>,
2227 if !valid_out_of_scope_traits.is_empty() {
2228 let mut candidates = valid_out_of_scope_traits;
2232 // `TryFrom` and `FromIterator` have no methods
2233 let edition_fix = candidates
2235 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2238 err.help("items from traits can only be used if the trait is in scope");
2240 "the following {traits_are} implemented but not in scope; \
2241 perhaps add a `use` for {one_of_them}:",
2242 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2243 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2246 self.suggest_use_candidates(err, msg, candidates);
2247 if let Some(did) = edition_fix {
2249 "'{}' is included in the prelude starting in Edition 2021",
2250 with_crate_prefix!(self.tcx.def_path_str(did))
2260 fn suggest_traits_to_import(
2262 err: &mut Diagnostic,
2266 inputs_len: Option<usize>,
2267 source: SelfSource<'tcx>,
2268 valid_out_of_scope_traits: Vec<DefId>,
2269 unsatisfied_predicates: &[(
2270 ty::Predicate<'tcx>,
2271 Option<ty::Predicate<'tcx>>,
2272 Option<ObligationCause<'tcx>>,
2274 static_candidates: &[CandidateSource],
2275 unsatisfied_bounds: bool,
2276 return_type: Option<Ty<'tcx>>,
2278 let mut alt_rcvr_sugg = false;
2279 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2281 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2282 span, item_name, rcvr_ty, rcvr
2285 self.tcx.lang_items().clone_trait(),
2286 self.tcx.lang_items().deref_trait(),
2287 self.tcx.lang_items().deref_mut_trait(),
2288 self.tcx.lang_items().drop_trait(),
2289 self.tcx.get_diagnostic_item(sym::AsRef),
2291 // Try alternative arbitrary self types that could fulfill this call.
2292 // FIXME: probe for all types that *could* be arbitrary self-types, not
2294 for (rcvr_ty, post) in &[
2296 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2297 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2299 match self.lookup_probe_for_diagnostic(
2303 ProbeScope::AllTraits,
2307 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2308 // We point at the method, but we just skip the rest of the check for arbitrary
2309 // self types and rely on the suggestion to `use` the trait from
2310 // `suggest_valid_traits`.
2311 let did = Some(pick.item.container_id(self.tcx));
2312 let skip = skippable.contains(&did);
2313 if pick.autoderefs == 0 && !skip {
2315 pick.item.ident(self.tcx).span,
2316 &format!("the method is available for `{}` here", rcvr_ty),
2321 Err(MethodError::Ambiguity(_)) => {
2322 // If the method is defined (but ambiguous) for the receiver we have, it is also
2323 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2324 // the receiver, then it might disambiguate this method, but I think these
2325 // suggestions are generally misleading (see #94218).
2331 for (rcvr_ty, pre) in &[
2332 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2333 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2334 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2335 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2337 if let Some(new_rcvr_t) = *rcvr_ty
2338 && let Ok(pick) = self.lookup_probe_for_diagnostic(
2342 ProbeScope::AllTraits,
2346 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2347 let did = Some(pick.item.container_id(self.tcx));
2348 // We don't want to suggest a container type when the missing
2349 // method is `.clone()` or `.deref()` otherwise we'd suggest
2350 // `Arc::new(foo).clone()`, which is far from what the user wants.
2351 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2352 // implement the `AsRef` trait.
2353 let skip = skippable.contains(&did)
2354 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2355 || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
2356 // Make sure the method is defined for the *actual* receiver: we don't
2357 // want to treat `Box<Self>` as a receiver if it only works because of
2358 // an autoderef to `&self`
2359 if pick.autoderefs == 0 && !skip {
2361 pick.item.ident(self.tcx).span,
2362 &format!("the method is available for `{}` here", new_rcvr_t),
2364 err.multipart_suggestion(
2365 "consider wrapping the receiver expression with the \
2368 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2369 (rcvr.span.shrink_to_hi(), ")".to_string()),
2371 Applicability::MaybeIncorrect,
2373 // We don't care about the other suggestions.
2374 alt_rcvr_sugg = true;
2380 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2384 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2386 let mut arbitrary_rcvr = vec![];
2387 // There are no traits implemented, so lets suggest some traits to
2388 // implement, by finding ones that have the item name, and are
2389 // legal to implement.
2390 let mut candidates = all_traits(self.tcx)
2392 // Don't issue suggestions for unstable traits since they're
2393 // unlikely to be implementable anyway
2394 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2395 Some(attr) => attr.level.is_stable(),
2399 // Static candidates are already implemented, and known not to work
2400 // Do not suggest them again
2401 static_candidates.iter().all(|sc| match *sc {
2402 CandidateSource::Trait(def_id) => def_id != info.def_id,
2403 CandidateSource::Impl(def_id) => {
2404 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2409 // We approximate the coherence rules to only suggest
2410 // traits that are legal to implement by requiring that
2411 // either the type or trait is local. Multi-dispatch means
2412 // this isn't perfect (that is, there are cases when
2413 // implementing a trait would be legal but is rejected
2415 unsatisfied_predicates.iter().all(|(p, _, _)| {
2416 match p.kind().skip_binder() {
2417 // Hide traits if they are present in predicates as they can be fixed without
2418 // having to implement them.
2419 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2420 t.def_id() == info.def_id
2422 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2423 p.projection_ty.def_id == info.def_id
2427 }) && (type_is_local || info.def_id.is_local())
2428 && !self.tcx.trait_is_auto(info.def_id)
2430 .associated_value(info.def_id, item_name)
2432 if let ty::AssocKind::Fn = item.kind {
2436 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2437 if let Some(hir::Node::TraitItem(hir::TraitItem {
2438 kind: hir::TraitItemKind::Fn(fn_sig, method),
2440 })) = id.map(|id| self.tcx.hir().get(id))
2442 let self_first_arg = match method {
2443 hir::TraitFn::Required([ident, ..]) => {
2444 ident.name == kw::SelfLower
2446 hir::TraitFn::Provided(body_id) => {
2447 self.tcx.hir().body(*body_id).params.first().map_or(
2452 hir::PatKind::Binding(_, _, ident, _)
2453 if ident.name == kw::SelfLower
2461 if !fn_sig.decl.implicit_self.has_implicit_self()
2464 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2465 arbitrary_rcvr.push(ty.span);
2471 // We only want to suggest public or local traits (#45781).
2472 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2476 .collect::<Vec<_>>();
2477 for span in &arbitrary_rcvr {
2480 "the method might not be found because of this arbitrary self type",
2487 if !candidates.is_empty() {
2488 // Sort from most relevant to least relevant.
2489 candidates.sort_by(|a, b| a.cmp(b).reverse());
2492 let param_type = match rcvr_ty.kind() {
2493 ty::Param(param) => Some(param),
2494 ty::Ref(_, ty, _) => match ty.kind() {
2495 ty::Param(param) => Some(param),
2500 err.help(if param_type.is_some() {
2501 "items from traits can only be used if the type parameter is bounded by the trait"
2503 "items from traits can only be used if the trait is implemented and in scope"
2505 let candidates_len = candidates.len();
2506 let message = |action| {
2508 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2511 if candidates_len == 1 { "trait defines" } else { "traits define" },
2513 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2517 // Obtain the span for `param` and use it for a structured suggestion.
2518 if let Some(param) = param_type {
2519 let generics = self.tcx.generics_of(self.body_id.to_def_id());
2520 let type_param = generics.type_param(param, self.tcx);
2521 let hir = self.tcx.hir();
2522 if let Some(def_id) = type_param.def_id.as_local() {
2523 let id = hir.local_def_id_to_hir_id(def_id);
2524 // Get the `hir::Param` to verify whether it already has any bounds.
2525 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2526 // instead we suggest `T: Foo + Bar` in that case.
2528 Node::GenericParam(param) => {
2534 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2535 let (sp, mut introducer) = if let Some(span) =
2536 ast_generics.bounds_span_for_suggestions(def_id)
2538 (span, Introducer::Plus)
2539 } else if let Some(colon_span) = param.colon_span {
2540 (colon_span.shrink_to_hi(), Introducer::Nothing)
2542 (param.span.shrink_to_hi(), Introducer::Colon)
2546 hir::GenericParamKind::Type { synthetic: true, .. },
2548 introducer = Introducer::Plus
2550 let trait_def_ids: FxHashSet<DefId> = ast_generics
2551 .bounds_for_param(def_id)
2552 .flat_map(|bp| bp.bounds.iter())
2553 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2555 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2556 err.span_suggestions(
2559 "restrict type parameter `{}` with",
2562 candidates.iter().map(|t| {
2566 Introducer::Plus => " +",
2567 Introducer::Colon => ":",
2568 Introducer::Nothing => "",
2570 self.tcx.def_path_str(t.def_id),
2573 Applicability::MaybeIncorrect,
2578 Node::Item(hir::Item {
2579 kind: hir::ItemKind::Trait(.., bounds, _),
2583 let (sp, sep, article) = if bounds.is_empty() {
2584 (ident.span.shrink_to_hi(), ":", "a")
2586 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2588 err.span_suggestions(
2590 &message(format!("add {} supertrait for", article)),
2591 candidates.iter().map(|t| {
2592 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2594 Applicability::MaybeIncorrect,
2603 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2604 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2605 // cases where a positive bound implies a negative impl.
2606 (candidates, Vec::new())
2607 } else if let Some(simp_rcvr_ty) =
2608 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2610 let mut potential_candidates = Vec::new();
2611 let mut explicitly_negative = Vec::new();
2612 for candidate in candidates {
2613 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2616 .all_impls(candidate.def_id)
2618 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2621 let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
2623 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2624 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2627 explicitly_negative.push(candidate);
2629 potential_candidates.push(candidate);
2632 (potential_candidates, explicitly_negative)
2634 // We don't know enough about `recv_ty` to make proper suggestions.
2635 (candidates, Vec::new())
2638 let action = if let Some(param) = param_type {
2639 format!("restrict type parameter `{}` with", param)
2641 // FIXME: it might only need to be imported into scope, not implemented.
2642 "implement".to_string()
2644 match &potential_candidates[..] {
2646 [trait_info] if trait_info.def_id.is_local() => {
2648 self.tcx.def_span(trait_info.def_id),
2650 "`{}` defines an item `{}`, perhaps you need to {} it",
2651 self.tcx.def_path_str(trait_info.def_id),
2658 let mut msg = message(action);
2659 for (i, trait_info) in trait_infos.iter().enumerate() {
2660 msg.push_str(&format!(
2661 "\ncandidate #{}: `{}`",
2663 self.tcx.def_path_str(trait_info.def_id),
2669 match &explicitly_negative[..] {
2673 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2674 self.tcx.def_path_str(trait_info.def_id),
2680 let mut msg = format!(
2681 "the following traits define an item `{}`, but are explicitly unimplemented:",
2684 for trait_info in trait_infos {
2685 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2693 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2694 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2695 pub(crate) fn suggest_else_fn_with_closure(
2697 err: &mut Diagnostic,
2698 expr: &hir::Expr<'_>,
2702 let Some((_def_id_or_name, output, _inputs)) =
2703 self.extract_callable_info(found) else {
2707 if !self.can_coerce(output, expected) {
2711 let parent = self.tcx.hir().parent_id(expr.hir_id);
2712 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2713 let hir::ExprKind::MethodCall(
2714 hir::PathSegment { ident: method_name, .. },
2718 ) = call_expr.kind &&
2719 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2720 let new_name = Ident {
2721 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2722 span: method_name.span,
2724 let probe = self.lookup_probe_for_diagnostic(
2728 ProbeScope::TraitsInScope,
2732 // check the method arguments number
2733 if let Ok(pick) = probe &&
2734 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2735 let fn_args = fn_sig.skip_binder().skip_binder().inputs() &&
2736 fn_args.len() == args.len() + 1 {
2737 err.span_suggestion_verbose(
2738 method_name.span.shrink_to_hi(),
2739 &format!("try calling `{}` instead", new_name.name.as_str()),
2741 Applicability::MaybeIncorrect,
2749 /// Checks whether there is a local type somewhere in the chain of
2750 /// autoderefs of `rcvr_ty`.
2751 fn type_derefs_to_local(
2755 source: SelfSource<'tcx>,
2757 fn is_local(ty: Ty<'_>) -> bool {
2759 ty::Adt(def, _) => def.did().is_local(),
2760 ty::Foreign(did) => did.is_local(),
2761 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2762 ty::Param(_) => true,
2764 // Everything else (primitive types, etc.) is effectively
2765 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2766 // the noise from these sort of types is usually just really
2767 // annoying, rather than any sort of help).
2772 // This occurs for UFCS desugaring of `T::method`, where there is no
2773 // receiver expression for the method call, and thus no autoderef.
2774 if let SelfSource::QPath(_) = source {
2775 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2778 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2782 #[derive(Copy, Clone, Debug)]
2783 pub enum SelfSource<'a> {
2784 QPath(&'a hir::Ty<'a>),
2785 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2788 #[derive(Copy, Clone)]
2789 pub struct TraitInfo {
2793 impl PartialEq for TraitInfo {
2794 fn eq(&self, other: &TraitInfo) -> bool {
2795 self.cmp(other) == Ordering::Equal
2798 impl Eq for TraitInfo {}
2799 impl PartialOrd for TraitInfo {
2800 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2801 Some(self.cmp(other))
2804 impl Ord for TraitInfo {
2805 fn cmp(&self, other: &TraitInfo) -> Ordering {
2806 // Local crates are more important than remote ones (local:
2807 // `cnum == 0`), and otherwise we throw in the defid for totality.
2809 let lhs = (other.def_id.krate, other.def_id);
2810 let rhs = (self.def_id.krate, self.def_id);
2815 /// Retrieves all traits in this crate and any dependent crates,
2816 /// and wraps them into `TraitInfo` for custom sorting.
2817 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2818 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2821 fn print_disambiguation_help<'tcx>(
2823 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2824 err: &mut Diagnostic,
2827 kind: ty::AssocKind,
2830 candidate: Option<usize>,
2831 source_map: &source_map::SourceMap,
2832 fn_has_self_parameter: bool,
2834 let mut applicability = Applicability::MachineApplicable;
2835 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2838 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2839 std::iter::once(receiver)
2841 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2842 applicability = Applicability::HasPlaceholders;
2845 .collect::<Vec<_>>()
2848 let trait_name = if !fn_has_self_parameter {
2849 format!("<{} as {}>", rcvr_ty, trait_name)
2853 (span, format!("{}::{}{}", trait_name, item_name, args))
2855 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2857 err.span_suggestion_verbose(
2860 "disambiguate the {} for {}",
2861 kind.as_def_kind().descr(def_id),
2862 if let Some(candidate) = candidate {
2863 format!("candidate #{}", candidate)
2865 "the candidate".to_string()