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 lev_candidate = no_match_data.lev_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.owner.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(
407 self.note_candidates_on_method_error(
416 } else if static_candidates.len() > 1 {
417 self.note_candidates_on_method_error(
428 let mut bound_spans = vec![];
429 let mut restrict_type_params = false;
430 let mut unsatisfied_bounds = false;
431 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
432 let msg = "consider using `len` instead";
433 if let SelfSource::MethodCall(_expr) = source {
434 err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
436 err.span_label(span, msg);
438 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
439 let iterator_trait = self.tcx.def_path_str(iterator_trait);
441 "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
444 } else if !unsatisfied_predicates.is_empty() {
445 let mut type_params = FxHashMap::default();
447 // Pick out the list of unimplemented traits on the receiver.
448 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
449 let mut unimplemented_traits = FxHashMap::default();
450 let mut unimplemented_traits_only = true;
451 for (predicate, _parent_pred, cause) in unsatisfied_predicates {
452 if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
453 (predicate.kind().skip_binder(), cause.as_ref())
455 if p.trait_ref.self_ty() != rcvr_ty {
456 // This is necessary, not just to keep the errors clean, but also
457 // because our derived obligations can wind up with a trait ref that
458 // requires a different param_env to be correctly compared.
461 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
462 predicate.kind().rebind(p.trait_ref),
464 cause: cause.clone(),
465 param_env: self.param_env,
466 predicate: *predicate,
473 // Make sure that, if any traits other than the found ones were involved,
474 // we don't don't report an unimplemented trait.
475 // We don't want to say that `iter::Cloned` is not an iterator, just
476 // because of some non-Clone item being iterated over.
477 for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
478 match predicate.kind().skip_binder() {
479 ty::PredicateKind::Clause(ty::Clause::Trait(p))
480 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
482 unimplemented_traits_only = false;
488 let mut collect_type_param_suggestions =
489 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
490 // We don't care about regions here, so it's fine to skip the binder here.
491 if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
492 (self_ty.kind(), parent_pred.kind().skip_binder())
494 let hir = self.tcx.hir();
495 let node = match p.trait_ref.self_ty().kind() {
497 // Account for `fn` items like in `issue-35677.rs` to
498 // suggest restricting its type params.
500 hir.body_owner(hir::BodyId { hir_id: self.body_id });
501 Some(hir.get(parent_body))
504 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
508 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
509 && let Some(g) = kind.generics()
512 g.tail_span_for_predicate_suggestion(),
513 g.add_where_or_trailing_comma(),
517 .or_insert_with(FxHashSet::default)
518 .insert(obligation.to_owned());
524 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
526 "doesn't satisfy `{}`",
527 if obligation.len() > 50 { quiet } else { obligation }
529 match &self_ty.kind() {
530 // Point at the type that couldn't satisfy the bound.
531 ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
532 // Point at the trait object that couldn't satisfy the bound.
533 ty::Dynamic(preds, _, _) => {
534 for pred in preds.iter() {
535 match pred.skip_binder() {
536 ty::ExistentialPredicate::Trait(tr) => {
537 bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
539 ty::ExistentialPredicate::Projection(_)
540 | ty::ExistentialPredicate::AutoTrait(_) => {}
544 // Point at the closure that couldn't satisfy the bound.
545 ty::Closure(def_id, _) => bound_spans
546 .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
550 let mut format_pred = |pred: ty::Predicate<'tcx>| {
551 let bound_predicate = pred.kind();
552 match bound_predicate.skip_binder() {
553 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
554 let pred = bound_predicate.rebind(pred);
555 // `<Foo as Iterator>::Item = String`.
556 let projection_ty = pred.skip_binder().projection_ty;
558 let substs_with_infer_self = tcx.mk_substs(
559 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
560 .chain(projection_ty.substs.iter().skip(1)),
563 let quiet_projection_ty =
564 tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
566 let term = pred.skip_binder().term;
568 let obligation = format!("{} = {}", projection_ty, term);
569 let quiet = with_forced_trimmed_paths!(format!(
571 quiet_projection_ty, term
574 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
575 Some((obligation, projection_ty.self_ty()))
577 ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
578 let p = poly_trait_ref.trait_ref;
579 let self_ty = p.self_ty();
580 let path = p.print_only_trait_path();
581 let obligation = format!("{}: {}", self_ty, path);
582 let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
583 bound_span_label(self_ty, &obligation, &quiet);
584 Some((obligation, self_ty))
590 // Find all the requirements that come from a local `impl` block.
591 let mut skip_list: FxHashSet<_> = Default::default();
592 let mut spanned_predicates = FxHashMap::default();
593 for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates
595 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
596 .filter_map(|(p, parent, c)| match c.code() {
597 ObligationCauseCode::ImplDerivedObligation(data)
598 if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
600 Some((p, parent, data.impl_def_id, data))
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.path.span.ctxt().outer_expn_data().kind),
616 Some(ExpnKind::Macro(MacroKind::Derive, _))
619 let span = self_ty.span.ctxt().outer_expn_data().call_site;
620 let entry = spanned_predicates.entry(span);
621 let entry = entry.or_insert_with(|| {
622 (FxHashSet::default(), FxHashSet::default(), Vec::new())
624 entry.0.insert(span);
627 "unsatisfied trait bound introduced in this `derive` macro",
633 // Unmet obligation coming from an `impl`.
634 Some(Node::Item(hir::Item {
635 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
640 unsatisfied_predicates.iter().any(|(pred, _, _)| {
641 match pred.kind().skip_binder() {
642 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
643 Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
644 && pred.polarity == ty::ImplPolarity::Positive
649 for param in generics.params {
650 if param.span == cause.span && sized_pred {
651 let (sp, sugg) = match param.colon_span {
652 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
653 None => (param.span.shrink_to_hi(), ": ?Sized"),
655 err.span_suggestion_verbose(
657 "consider relaxing the type parameter's implicit `Sized` bound",
659 Applicability::MachineApplicable,
663 if let Some(pred) = parent_p {
664 // Done to add the "doesn't satisfy" `span_label`.
665 let _ = format_pred(*pred);
668 let entry = spanned_predicates.entry(self_ty.span);
669 let entry = entry.or_insert_with(|| {
670 (FxHashSet::default(), FxHashSet::default(), Vec::new())
673 if cause.span != *item_span {
674 entry.0.insert(cause.span);
675 entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
677 if let Some(trait_ref) = of_trait {
678 entry.0.insert(trait_ref.path.span);
680 entry.0.insert(self_ty.span);
682 if let Some(trait_ref) = of_trait {
683 entry.1.insert((trait_ref.path.span, ""));
685 entry.1.insert((self_ty.span, ""));
687 Some(Node::Item(hir::Item {
688 kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
692 tcx.sess.delay_span_bug(
694 "auto trait is invoked with no method error, but no error reported?",
697 Some(Node::Item(hir::Item {
698 ident, kind: hir::ItemKind::Trait(..), ..
701 let entry = spanned_predicates.entry(ident.span);
702 let entry = entry.or_insert_with(|| {
703 (FxHashSet::default(), FxHashSet::default(), Vec::new())
705 entry.0.insert(cause.span);
706 entry.1.insert((ident.span, ""));
707 entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
710 Some(node) => unreachable!("encountered `{node:?}`"),
714 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
715 spanned_predicates.sort_by_key(|(span, _)| *span);
716 for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
717 let mut preds: Vec<_> = predicates
719 .filter_map(|pred| format_pred(**pred))
720 .map(|(p, _)| format!("`{}`", p))
724 let msg = if let [pred] = &preds[..] {
725 format!("trait bound {} was not satisfied", pred)
727 format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
729 let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
730 for (sp, label) in span_labels {
731 span.push_span_label(sp, label);
733 err.span_note(span, &msg);
734 unsatisfied_bounds = true;
737 let mut suggested_bounds = FxHashSet::default();
738 // The requirements that didn't have an `impl` span to show.
739 let mut bound_list = unsatisfied_predicates
741 .filter_map(|(pred, parent_pred, _cause)| {
742 let mut suggested = false;
743 format_pred(*pred).map(|(p, self_ty)| {
744 if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
745 // We don't suggest `PartialEq` when we already suggest `Eq`.
746 } else if !suggested_bounds.contains(pred) {
747 if collect_type_param_suggestions(self_ty, *pred, &p) {
749 suggested_bounds.insert(pred);
754 None => format!("`{}`", &p),
755 Some(parent_pred) => match format_pred(*parent_pred) {
756 None => format!("`{}`", &p),
757 Some((parent_p, _)) => {
759 && !suggested_bounds.contains(pred)
760 && !suggested_bounds.contains(parent_pred)
762 if collect_type_param_suggestions(
767 suggested_bounds.insert(pred);
770 format!("`{}`\nwhich is required by `{}`", p, parent_p)
778 .filter(|(_, pred)| !skip_list.contains(&pred))
781 .collect::<Vec<(usize, String)>>();
783 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
784 restrict_type_params = true;
785 // #74886: Sort here so that the output is always the same.
786 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
788 err.span_suggestion_verbose(
791 "consider restricting the type parameter{s} to satisfy the \
793 s = pluralize!(obligations.len())
795 format!("{} {}", add_where_or_comma, obligations.join(", ")),
796 Applicability::MaybeIncorrect,
800 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
801 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
802 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
804 if !bound_list.is_empty() || !skip_list.is_empty() {
806 bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
807 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
808 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
809 let (primary_message, label) = if unimplemented_traits.len() == 1
810 && unimplemented_traits_only
815 .map(|(_, (trait_ref, obligation))| {
816 if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
821 let OnUnimplementedNote { message, label, .. } =
822 self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
829 let primary_message = primary_message.unwrap_or_else(|| {
831 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
832 but its trait bounds were not satisfied"
835 err.set_primary_message(&primary_message);
836 if let Some(label) = label {
837 custom_span_label = true;
838 err.span_label(span, label);
840 if !bound_list.is_empty() {
842 "the following trait bounds were not satisfied:\n{bound_list}"
845 self.suggest_derive(&mut err, &unsatisfied_predicates);
847 unsatisfied_bounds = true;
851 let label_span_not_found = |err: &mut Diagnostic| {
852 if unsatisfied_predicates.is_empty() {
853 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
854 let is_string_or_ref_str = match rcvr_ty.kind() {
855 ty::Ref(_, ty, _) => {
859 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
862 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
865 if is_string_or_ref_str && item_name.name == sym::iter {
866 err.span_suggestion_verbose(
868 "because of the in-memory representation of `&str`, to obtain \
869 an `Iterator` over each of its codepoint use method `chars`",
871 Applicability::MachineApplicable,
874 if let ty::Adt(adt, _) = rcvr_ty.kind() {
875 let mut inherent_impls_candidate = self
877 .inherent_impls(adt.did())
881 if let Some(assoc) = self.associated_value(*def_id, item_name) {
882 // Check for both mode is the same so we avoid suggesting
883 // incorrect associated item.
884 match (mode, assoc.fn_has_self_parameter, source) {
885 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
886 // We check that the suggest type is actually
887 // different from the received one
888 // So we avoid suggestion method with Box<Self>
890 self.tcx.at(span).type_of(*def_id) != rcvr_ty
891 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
893 (Mode::Path, false, _) => true,
900 .collect::<Vec<_>>();
901 if !inherent_impls_candidate.is_empty() {
902 inherent_impls_candidate.sort();
903 inherent_impls_candidate.dedup();
905 // number of type to shows at most.
906 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
907 let type_candidates = inherent_impls_candidate
911 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
915 let additional_types = if inherent_impls_candidate.len() > limit {
916 format!("\nand {} more types", inherent_impls_candidate.len() - limit)
921 "the {item_kind} was found for\n{}{}",
922 type_candidates, additional_types
928 if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
931 format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
936 // If the method name is the name of a field with a function or closure type,
937 // give a helping note that it has to be called as `(x.f)(...)`.
938 if let SelfSource::MethodCall(expr) = source {
939 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
940 && lev_candidate.is_none()
941 && !custom_span_label
943 label_span_not_found(&mut err);
945 } else if !custom_span_label {
946 label_span_not_found(&mut err);
949 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
950 // can't be called due to `typeof(expr): Clone` not holding.
951 if unsatisfied_predicates.is_empty() {
952 self.suggest_calling_method_on_field(
958 expected.only_has_type(self),
962 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
966 for (span, msg) in bound_spans.into_iter() {
967 err.span_label(span, &msg);
970 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
972 self.suggest_traits_to_import(
977 args.map(|(_, args)| args.len() + 1),
979 no_match_data.out_of_scope_traits.clone(),
980 &unsatisfied_predicates,
983 expected.only_has_type(self),
987 // Don't emit a suggestion if we found an actual method
988 // that had unsatisfied trait bounds
989 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
990 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
991 if let Some(suggestion) = lev_distance::find_best_match_for_name(
992 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
998 "there is a variant with a similar name",
1000 Applicability::MaybeIncorrect,
1005 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
1006 let msg = "remove this method call";
1007 let mut fallback_span = true;
1008 if let SelfSource::MethodCall(expr) = source {
1009 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1010 if let Some(span) = call_expr.span.trim_start(expr.span) {
1011 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1012 fallback_span = false;
1016 err.span_label(span, msg);
1018 } else if let Some(lev_candidate) = lev_candidate {
1019 // Don't emit a suggestion if we found an actual method
1020 // that had unsatisfied trait bounds
1021 if unsatisfied_predicates.is_empty() {
1022 let def_kind = lev_candidate.kind.as_def_kind();
1023 // Methods are defined within the context of a struct and their first parameter is always self,
1024 // which represents the instance of the struct the method is being called on
1025 // Associated functions don’t take self as a parameter and
1026 // they are not methods because they don’t have an instance of the struct to work with.
1027 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
1028 err.span_suggestion(
1030 "there is a method with a similar name",
1032 Applicability::MaybeIncorrect,
1035 err.span_suggestion(
1038 "there is {} {} with a similar name",
1040 def_kind.descr(lev_candidate.def_id),
1043 Applicability::MaybeIncorrect,
1049 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name, expected);
1053 fn note_candidates_on_method_error(
1057 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1059 err: &mut Diagnostic,
1060 sources: &mut Vec<CandidateSource>,
1061 sugg_span: Option<Span>,
1065 // Dynamic limit to avoid hiding just one candidate, which is silly.
1066 let limit = if sources.len() == 5 { 5 } else { 4 };
1068 for (idx, source) in sources.iter().take(limit).enumerate() {
1070 CandidateSource::Impl(impl_did) => {
1071 // Provide the best span we can. Use the item, if local to crate, else
1072 // the impl, if local to crate (item may be defaulted), else nothing.
1073 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
1074 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
1075 self.associated_value(impl_trait_ref.skip_binder().def_id, item_name)
1080 let note_span = if item.def_id.is_local() {
1081 Some(self.tcx.def_span(item.def_id))
1082 } else if impl_did.is_local() {
1083 Some(self.tcx.def_span(impl_did))
1088 let impl_ty = self.tcx.at(span).type_of(impl_did);
1090 let insertion = match self.tcx.impl_trait_ref(impl_did) {
1091 None => String::new(),
1092 Some(trait_ref) => {
1094 " of the trait `{}`",
1095 self.tcx.def_path_str(trait_ref.skip_binder().def_id)
1100 let (note_str, idx) = if sources.len() > 1 {
1103 "candidate #{} is defined in an impl{} for the type `{}`",
1113 "the candidate is defined in an impl{} for the type `{}`",
1119 if let Some(note_span) = note_span {
1120 // We have a span pointing to the method. Show note with snippet.
1121 err.span_note(note_span, ¬e_str);
1123 err.note(¬e_str);
1125 if let Some(sugg_span) = sugg_span
1126 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
1127 let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
1129 let ty = match item.kind {
1130 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
1131 ty::AssocKind::Fn => self
1133 .fn_sig(item.def_id)
1137 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
1139 .unwrap_or(rcvr_ty),
1141 print_disambiguation_help(
1151 self.tcx.sess.source_map(),
1152 item.fn_has_self_parameter,
1156 CandidateSource::Trait(trait_did) => {
1157 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
1158 let item_span = self.tcx.def_span(item.def_id);
1159 let idx = if sources.len() > 1 {
1161 "candidate #{} is defined in the trait `{}`",
1163 self.tcx.def_path_str(trait_did)
1165 err.span_note(item_span, msg);
1169 "the candidate is defined in the trait `{}`",
1170 self.tcx.def_path_str(trait_did)
1172 err.span_note(item_span, msg);
1175 if let Some(sugg_span) = sugg_span {
1176 let path = self.tcx.def_path_str(trait_did);
1177 print_disambiguation_help(
1187 self.tcx.sess.source_map(),
1188 item.fn_has_self_parameter,
1194 if sources.len() > limit {
1195 err.note(&format!("and {} others", sources.len() - limit));
1199 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1200 /// doesn't take a `self` receiver.
1201 fn suggest_associated_call_syntax(
1203 err: &mut Diagnostic,
1204 static_candidates: &Vec<CandidateSource>,
1206 source: SelfSource<'tcx>,
1208 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1211 let mut has_unsuggestable_args = false;
1212 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1213 // When the "method" is resolved through dereferencing, we really want the
1214 // original type that has the associated function for accurate suggestions.
1216 let impl_ty = self.tcx.type_of(*impl_did);
1217 let target_ty = self
1218 .autoderef(sugg_span, rcvr_ty)
1219 .find(|(rcvr_ty, _)| {
1220 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1221 .types_may_unify(*rcvr_ty, impl_ty)
1223 .map_or(impl_ty, |(ty, _)| ty)
1225 if let ty::Adt(def, substs) = target_ty.kind() {
1226 // If there are any inferred arguments, (`{integer}`), we should replace
1227 // them with underscores to allow the compiler to infer them
1228 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1229 if !arg.is_suggestable(self.tcx, true) {
1230 has_unsuggestable_args = true;
1231 match arg.unpack() {
1232 GenericArgKind::Lifetime(_) => self
1233 .next_region_var(RegionVariableOrigin::MiscVariable(
1234 rustc_span::DUMMY_SP,
1237 GenericArgKind::Type(_) => self
1238 .next_ty_var(TypeVariableOrigin {
1239 span: rustc_span::DUMMY_SP,
1240 kind: TypeVariableOriginKind::MiscVariable,
1243 GenericArgKind::Const(arg) => self
1246 ConstVariableOrigin {
1247 span: rustc_span::DUMMY_SP,
1248 kind: ConstVariableOriginKind::MiscVariable,
1258 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1260 self.ty_to_value_string(target_ty)
1263 self.ty_to_value_string(rcvr_ty.peel_refs())
1265 if let SelfSource::MethodCall(_) = source {
1266 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1267 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1268 && assoc.kind == ty::AssocKind::Fn
1270 let sig = self.tcx.fn_sig(assoc.def_id);
1271 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1274 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1279 let mut applicability = Applicability::MachineApplicable;
1280 let args = if let Some((receiver, args)) = args {
1281 // The first arg is the same kind as the receiver
1282 let explicit_args = if first_arg.is_some() {
1283 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1285 // There is no `Self` kind to infer the arguments from
1286 if has_unsuggestable_args {
1287 applicability = Applicability::HasPlaceholders;
1289 args.iter().collect()
1293 first_arg.unwrap_or(""),
1300 .span_to_snippet(arg.span)
1301 .unwrap_or_else(|_| {
1302 applicability = Applicability::HasPlaceholders;
1305 .collect::<Vec<_>>()
1309 applicability = Applicability::HasPlaceholders;
1312 err.span_suggestion(
1314 "use associated function syntax instead",
1315 format!("{}::{}{}", ty_str, item_name, args),
1319 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1323 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1324 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1325 fn suggest_calling_field_as_fn(
1329 expr: &hir::Expr<'_>,
1331 err: &mut Diagnostic,
1334 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1335 ty::Adt(def, substs) if !def.is_enum() => {
1336 let variant = &def.non_enum_variant();
1337 tcx.find_field_index(item_name, variant).map(|index| {
1338 let field = &variant.fields[index];
1339 let field_ty = field.ty(tcx, substs);
1345 if let Some((field, field_ty)) = field_receiver {
1346 let scope = tcx.parent_module(self.body_id);
1347 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1350 if self.is_fn_ty(field_ty, span) {
1351 let expr_span = expr.span.to(item_name.span);
1352 err.multipart_suggestion(
1354 "to call the function stored in `{}`, \
1355 surround the field access with parentheses",
1359 (expr_span.shrink_to_lo(), '('.to_string()),
1360 (expr_span.shrink_to_hi(), ')'.to_string()),
1362 Applicability::MachineApplicable,
1365 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1367 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1368 err.span_suggestion(
1370 "remove the arguments",
1372 Applicability::MaybeIncorrect,
1378 let field_kind = if is_accessible { "field" } else { "private field" };
1379 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1385 /// Suggest possible range with adding parentheses, for example:
1386 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1387 fn suggest_wrapping_range_with_parens(
1391 source: SelfSource<'tcx>,
1396 if let SelfSource::MethodCall(expr) = source {
1397 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1398 if let Node::Expr(parent_expr) = parent {
1399 let lang_item = match parent_expr.kind {
1400 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1401 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1402 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1403 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1404 Some(LangItem::RangeToInclusive)
1408 ExprKind::Call(ref func, _) => match func.kind {
1409 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1410 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1411 Some(LangItem::RangeInclusiveStruct)
1418 if lang_item.is_none() {
1422 let span_included = match parent_expr.kind {
1423 hir::ExprKind::Struct(_, eps, _) => {
1424 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1426 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1427 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1435 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1437 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1439 let pick = self.lookup_probe_for_diagnostic(
1443 ProbeScope::AllTraits,
1447 let range_span = parent_expr.span.with_hi(expr.span.hi());
1448 tcx.sess.emit_err(errors::MissingParentheseInRange {
1450 ty_str: ty_str.to_string(),
1451 method_name: item_name.as_str().to_string(),
1452 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1453 func_name: item_name.name.as_str().to_string(),
1454 left: range_span.shrink_to_lo(),
1455 right: range_span.shrink_to_hi(),
1466 fn suggest_constraining_numerical_ty(
1470 source: SelfSource<'_>,
1476 let found_candidate = all_traits(self.tcx)
1478 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1479 let found_assoc = |ty: Ty<'tcx>| {
1480 simplify_type(tcx, ty, TreatParams::AsInfer)
1482 tcx.incoherent_impls(simp)
1484 .find_map(|&id| self.associated_value(id, item_name))
1488 let found_candidate = found_candidate
1489 || found_assoc(tcx.types.i8)
1490 || found_assoc(tcx.types.i16)
1491 || found_assoc(tcx.types.i32)
1492 || found_assoc(tcx.types.i64)
1493 || found_assoc(tcx.types.i128)
1494 || found_assoc(tcx.types.u8)
1495 || found_assoc(tcx.types.u16)
1496 || found_assoc(tcx.types.u32)
1497 || found_assoc(tcx.types.u64)
1498 || found_assoc(tcx.types.u128)
1499 || found_assoc(tcx.types.f32)
1500 || found_assoc(tcx.types.f32);
1502 && actual.is_numeric()
1503 && !actual.has_concrete_skeleton()
1504 && let SelfSource::MethodCall(expr) = source
1506 let mut err = struct_span_err!(
1510 "can't call {} `{}` on ambiguous numeric type `{}`",
1515 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1517 ExprKind::Lit(ref lit) => {
1522 .span_to_snippet(lit.span)
1523 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1525 // If this is a floating point literal that ends with '.',
1526 // get rid of it to stop this from becoming a member access.
1527 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1528 err.span_suggestion(
1531 "you must specify a concrete type for this numeric value, \
1535 format!("{snippet}_{concrete_type}"),
1536 Applicability::MaybeIncorrect,
1539 ExprKind::Path(QPath::Resolved(_, path)) => {
1541 if let hir::def::Res::Local(hir_id) = path.res {
1542 let span = tcx.hir().span(hir_id);
1543 let filename = tcx.sess.source_map().span_to_filename(span);
1546 self.tcx.hir().get_parent(hir_id);
1548 "you must specify a type for this binding, like `{}`",
1552 match (filename, parent_node) {
1555 Node::Local(hir::Local {
1556 source: hir::LocalSource::Normal,
1561 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1562 err.span_suggestion(
1563 // account for `let x: _ = 42;`
1567 format!(": {concrete_type}"),
1568 Applicability::MaybeIncorrect,
1572 err.span_label(span, msg);
1585 /// For code `rect::area(...)`,
1586 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1587 /// we try to suggest `rect.area()`
1588 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1589 debug!("suggest_assoc_method_call segs: {:?}", segs);
1590 let [seg1, seg2] = segs else { return; };
1591 let Some(mut diag) =
1592 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1595 let map = self.infcx.tcx.hir();
1596 let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
1597 struct LetVisitor<'a> {
1598 result: Option<&'a hir::Expr<'a>>,
1602 // FIXME: This really should be taking scoping, etc into account.
1603 impl<'v> Visitor<'v> for LetVisitor<'v> {
1604 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1605 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1606 && let Binding(_, _, ident, ..) = pat.kind
1607 && ident.name == self.ident_name
1609 self.result = *init;
1611 hir::intravisit::walk_stmt(self, ex);
1616 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1617 visitor.visit_body(&body);
1619 let parent = self.tcx.hir().parent_id(seg1.hir_id);
1620 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1621 && let Some(expr) = visitor.result
1622 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1624 let probe = self.lookup_probe_for_diagnostic(
1628 ProbeScope::TraitsInScope,
1632 let sm = self.infcx.tcx.sess.source_map();
1633 diag.span_suggestion_verbose(
1634 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1635 "you may have meant to call an instance method",
1637 Applicability::MaybeIncorrect,
1644 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1645 fn suggest_calling_method_on_field(
1647 err: &mut Diagnostic,
1648 source: SelfSource<'tcx>,
1652 return_type: Option<Ty<'tcx>>,
1654 if let SelfSource::MethodCall(expr) = source
1655 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1656 && let Some((fields, substs)) =
1657 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1659 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1661 let lang_items = self.tcx.lang_items();
1662 let never_mention_traits = [
1663 lang_items.clone_trait(),
1664 lang_items.deref_trait(),
1665 lang_items.deref_mut_trait(),
1666 self.tcx.get_diagnostic_item(sym::AsRef),
1667 self.tcx.get_diagnostic_item(sym::AsMut),
1668 self.tcx.get_diagnostic_item(sym::Borrow),
1669 self.tcx.get_diagnostic_item(sym::BorrowMut),
1671 let candidate_fields: Vec<_> = fields
1672 .filter_map(|candidate_field| {
1673 self.check_for_nested_field_satisfying(
1676 self.lookup_probe_for_diagnostic(
1680 ProbeScope::TraitsInScope,
1683 .map_or(false, |pick| {
1684 !never_mention_traits
1687 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1699 .map(|id| id.name.to_ident_string())
1700 .collect::<Vec<String>>()
1705 let len = candidate_fields.len();
1707 err.span_suggestions(
1708 item_name.span.shrink_to_lo(),
1710 "{} of the expressions' fields {} a method of the same name",
1711 if len > 1 { "some" } else { "one" },
1712 if len > 1 { "have" } else { "has" },
1714 candidate_fields.iter().map(|path| format!("{path}.")),
1715 Applicability::MaybeIncorrect,
1721 fn check_for_inner_self(
1723 err: &mut Diagnostic,
1724 source: SelfSource<'tcx>,
1729 let SelfSource::MethodCall(expr) = source else { return; };
1730 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1732 let ty::Adt(kind, substs) = actual.kind() else { return; };
1733 match kind.adt_kind() {
1734 ty::AdtKind::Enum => {
1735 let matching_variants: Vec<_> = kind
1738 .flat_map(|variant| {
1739 let [field] = &variant.fields[..] else { return None; };
1740 let field_ty = field.ty(tcx, substs);
1742 // Skip `_`, since that'll just lead to ambiguity.
1743 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1747 self.lookup_probe_for_diagnostic(
1751 ProbeScope::TraitsInScope,
1755 .map(|pick| (variant, field, pick))
1759 let ret_ty_matches = |diagnostic_item| {
1760 if let Some(ret_ty) = self
1763 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1764 && let ty::Adt(kind, _) = ret_ty.kind()
1765 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1773 match &matching_variants[..] {
1774 [(_, field, pick)] => {
1775 let self_ty = field.ty(tcx, substs);
1777 tcx.def_span(pick.item.def_id),
1778 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1780 let (article, kind, variant, question) =
1781 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1782 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1783 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1784 ("an", "Option", "None", ret_ty_matches(sym::Option))
1789 err.span_suggestion_verbose(
1790 expr.span.shrink_to_hi(),
1792 "use the `?` operator to extract the `{self_ty}` value, propagating \
1793 {article} `{kind}::{variant}` value to the caller"
1796 Applicability::MachineApplicable,
1799 err.span_suggestion_verbose(
1800 expr.span.shrink_to_hi(),
1802 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1803 panicking if the value is {article} `{kind}::{variant}`"
1805 ".expect(\"REASON\")",
1806 Applicability::HasPlaceholders,
1810 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1814 // Target wrapper types - types that wrap or pretend to wrap another type,
1815 // perhaps this inner type is meant to be called?
1816 ty::AdtKind::Struct | ty::AdtKind::Union => {
1817 let [first] = ***substs else { return; };
1818 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1819 let Ok(pick) = self.lookup_probe_for_diagnostic(
1823 ProbeScope::TraitsInScope,
1827 let name = self.ty_to_value_string(actual);
1828 let inner_id = kind.did();
1829 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1830 pick.autoref_or_ptr_adjustment
1837 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1838 err.help("use `with` or `try_with` to access thread local storage");
1839 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1841 "if this `{name}` has been initialized, \
1842 use one of the `assume_init` methods to access the inner value"
1844 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1845 let (suggestion, borrow_kind, panic_if) = match mutable {
1846 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1847 Some(Mutability::Mut) => {
1848 (".borrow_mut()", "mutably borrow", "any borrows exist")
1852 err.span_suggestion_verbose(
1853 expr.span.shrink_to_hi(),
1855 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1856 panicking if {panic_if}"
1859 Applicability::MaybeIncorrect,
1861 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1862 err.span_suggestion_verbose(
1863 expr.span.shrink_to_hi(),
1865 "use `.lock().unwrap()` to borrow the `{ty}`, \
1866 blocking the current thread until it can be acquired"
1869 Applicability::MaybeIncorrect,
1871 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1872 let (suggestion, borrow_kind) = match mutable {
1873 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1874 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1877 err.span_suggestion_verbose(
1878 expr.span.shrink_to_hi(),
1880 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1881 blocking the current thread until it can be acquired"
1884 Applicability::MaybeIncorrect,
1891 tcx.def_span(pick.item.def_id),
1892 &format!("the method `{item_name}` exists on the type `{ty}`"),
1898 pub(crate) fn note_unmet_impls_on_type(
1900 err: &mut Diagnostic,
1901 errors: Vec<FulfillmentError<'tcx>>,
1903 let all_local_types_needing_impls =
1904 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1905 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1906 ty::Adt(def, _) => def.did().is_local(),
1911 let mut preds: Vec<_> = errors
1913 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1914 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1918 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1921 .filter_map(|pred| match pred.self_ty().kind() {
1922 ty::Adt(def, _) => Some(def.did()),
1925 .collect::<FxHashSet<_>>();
1926 let mut spans: MultiSpan = def_ids
1928 .filter_map(|def_id| {
1929 let span = self.tcx.def_span(*def_id);
1930 if span.is_dummy() { None } else { Some(span) }
1932 .collect::<Vec<_>>()
1935 for pred in &preds {
1936 match pred.self_ty().kind() {
1937 ty::Adt(def, _) if def.did().is_local() => {
1938 spans.push_span_label(
1939 self.tcx.def_span(def.did()),
1940 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1947 if all_local_types_needing_impls && spans.primary_span().is_some() {
1948 let msg = if preds.len() == 1 {
1950 "an implementation of `{}` might be missing for `{}`",
1951 preds[0].trait_ref.print_only_trait_path(),
1956 "the following type{} would have to `impl` {} required trait{} for this \
1957 operation to be valid",
1958 pluralize!(def_ids.len()),
1959 if def_ids.len() == 1 { "its" } else { "their" },
1960 pluralize!(preds.len()),
1963 err.span_note(spans, &msg);
1966 let preds: Vec<_> = errors
1968 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1970 self.suggest_derive(err, &preds);
1973 pub fn suggest_derive(
1975 err: &mut Diagnostic,
1976 unsatisfied_predicates: &[(
1977 ty::Predicate<'tcx>,
1978 Option<ty::Predicate<'tcx>>,
1979 Option<ObligationCause<'tcx>>,
1982 let mut derives = Vec::<(String, Span, Symbol)>::new();
1983 let mut traits = Vec::new();
1984 for (pred, _, _) in unsatisfied_predicates {
1985 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1986 let adt = match trait_pred.self_ty().ty_adt_def() {
1987 Some(adt) if adt.did().is_local() => adt,
1990 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1991 let can_derive = match diagnostic_name {
1992 sym::Default => !adt.is_enum(),
2000 | sym::Debug => true,
2004 let self_name = trait_pred.self_ty().to_string();
2005 let self_span = self.tcx.def_span(adt.did());
2006 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
2007 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
2009 if let Some(parent_diagnostic_name) =
2010 self.tcx.get_diagnostic_name(super_trait.def_id())
2015 parent_diagnostic_name,
2020 derives.push((self_name, self_span, diagnostic_name));
2022 traits.push(trait_pred.def_id());
2025 traits.push(trait_pred.def_id());
2034 let mut derives_grouped = Vec::<(String, Span, String)>::new();
2035 for (self_name, self_span, trait_name) in derives.into_iter() {
2036 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2038 if last_self_name == &self_name {
2039 last_trait_names.push_str(format!(", {}", trait_name).as_str());
2043 derives_grouped.push((self_name, self_span, trait_name.to_string()));
2046 let len = traits.len();
2049 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
2050 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
2051 for (i, &did) in traits.iter().enumerate().skip(1) {
2053 names.push_str(", ");
2056 names.push_str(" and ");
2059 names.push_str(&self.tcx.def_path_str(did));
2064 &format!("the trait{} {} must be implemented", pluralize!(len), names),
2068 for (self_name, self_span, traits) in &derives_grouped {
2069 err.span_suggestion_verbose(
2070 self_span.shrink_to_lo(),
2071 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
2072 format!("#[derive({})]\n", traits),
2073 Applicability::MaybeIncorrect,
2078 fn check_for_deref_method(
2080 err: &mut Diagnostic,
2081 self_source: SelfSource<'tcx>,
2084 expected: Expectation<'tcx>,
2086 let SelfSource::QPath(ty) = self_source else { return; };
2087 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
2088 if let Ok(pick) = self.probe_for_name(
2091 expected.only_has_type(self),
2095 ProbeScope::TraitsInScope,
2097 if deref_ty.is_suggestable(self.tcx, true)
2098 // If this method receives `&self`, then the provided
2099 // argument _should_ coerce, so it's valid to suggest
2100 // just changing the path.
2101 && pick.item.fn_has_self_parameter
2102 && let Some(self_ty) =
2103 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
2106 let suggested_path = match deref_ty.kind() {
2114 | ty::Alias(ty::Projection, _)
2115 | ty::Param(_) => format!("{deref_ty}"),
2116 // we need to test something like <&[_]>::len or <(&[u32])>::len
2117 // and Vec::function();
2118 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2119 // but for Adt type like Vec::function()
2120 // we would suggest <[_]>::function();
2121 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
2122 _ => format!("<{deref_ty}>"),
2124 err.span_suggestion_verbose(
2126 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2128 Applicability::MaybeIncorrect,
2133 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2141 /// Print out the type for use in value namespace.
2142 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2144 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2145 _ => self.ty_to_string(ty),
2149 fn suggest_await_before_method(
2151 err: &mut Diagnostic,
2154 call: &hir::Expr<'_>,
2156 return_type: Option<Ty<'tcx>>,
2158 let output_ty = match self.get_impl_future_output_ty(ty) {
2159 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2163 self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
2164 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2166 err.span_suggestion_verbose(
2167 span.shrink_to_lo(),
2168 "consider `await`ing on the `Future` and calling the method on its `Output`",
2170 Applicability::MaybeIncorrect,
2175 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2176 let parent_map = self.tcx.visible_parent_map(());
2178 // Separate out candidates that must be imported with a glob, because they are named `_`
2179 // and cannot be referred with their identifier.
2180 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2181 if let Some(parent_did) = parent_map.get(trait_did) {
2182 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2183 if *parent_did != self.tcx.parent(*trait_did)
2186 .module_children(*parent_did)
2188 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2189 .all(|child| child.ident.name == kw::Underscore)
2198 let module_did = self.tcx.parent_module(self.body_id);
2199 let (module, _, _) = self.tcx.hir().get_module(module_did);
2200 let span = module.spans.inject_use_span;
2202 let path_strings = candidates.iter().map(|trait_did| {
2203 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2206 let glob_path_strings = globs.iter().map(|trait_did| {
2207 let parent_did = parent_map.get(trait_did).unwrap();
2209 "use {}::*; // trait {}\n",
2210 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2211 self.tcx.item_name(*trait_did),
2215 err.span_suggestions(
2218 path_strings.chain(glob_path_strings),
2219 Applicability::MaybeIncorrect,
2223 fn suggest_valid_traits(
2225 err: &mut Diagnostic,
2226 valid_out_of_scope_traits: Vec<DefId>,
2228 if !valid_out_of_scope_traits.is_empty() {
2229 let mut candidates = valid_out_of_scope_traits;
2233 // `TryFrom` and `FromIterator` have no methods
2234 let edition_fix = candidates
2236 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2239 err.help("items from traits can only be used if the trait is in scope");
2241 "the following {traits_are} implemented but not in scope; \
2242 perhaps add a `use` for {one_of_them}:",
2243 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2244 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2247 self.suggest_use_candidates(err, msg, candidates);
2248 if let Some(did) = edition_fix {
2250 "'{}' is included in the prelude starting in Edition 2021",
2251 with_crate_prefix!(self.tcx.def_path_str(did))
2261 fn suggest_traits_to_import(
2263 err: &mut Diagnostic,
2267 inputs_len: Option<usize>,
2268 source: SelfSource<'tcx>,
2269 valid_out_of_scope_traits: Vec<DefId>,
2270 unsatisfied_predicates: &[(
2271 ty::Predicate<'tcx>,
2272 Option<ty::Predicate<'tcx>>,
2273 Option<ObligationCause<'tcx>>,
2275 static_candidates: &[CandidateSource],
2276 unsatisfied_bounds: bool,
2277 return_type: Option<Ty<'tcx>>,
2279 let mut alt_rcvr_sugg = false;
2280 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2282 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2283 span, item_name, rcvr_ty, rcvr
2286 self.tcx.lang_items().clone_trait(),
2287 self.tcx.lang_items().deref_trait(),
2288 self.tcx.lang_items().deref_mut_trait(),
2289 self.tcx.lang_items().drop_trait(),
2290 self.tcx.get_diagnostic_item(sym::AsRef),
2292 // Try alternative arbitrary self types that could fulfill this call.
2293 // FIXME: probe for all types that *could* be arbitrary self-types, not
2295 for (rcvr_ty, post) in &[
2297 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2298 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2300 match self.lookup_probe_for_diagnostic(
2304 ProbeScope::AllTraits,
2308 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2309 // We point at the method, but we just skip the rest of the check for arbitrary
2310 // self types and rely on the suggestion to `use` the trait from
2311 // `suggest_valid_traits`.
2312 let did = Some(pick.item.container_id(self.tcx));
2313 let skip = skippable.contains(&did);
2314 if pick.autoderefs == 0 && !skip {
2316 pick.item.ident(self.tcx).span,
2317 &format!("the method is available for `{}` here", rcvr_ty),
2322 Err(MethodError::Ambiguity(_)) => {
2323 // If the method is defined (but ambiguous) for the receiver we have, it is also
2324 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2325 // the receiver, then it might disambiguate this method, but I think these
2326 // suggestions are generally misleading (see #94218).
2332 for (rcvr_ty, pre) in &[
2333 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2334 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2335 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2336 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2338 if let Some(new_rcvr_t) = *rcvr_ty
2339 && let Ok(pick) = self.lookup_probe_for_diagnostic(
2343 ProbeScope::AllTraits,
2347 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2348 let did = Some(pick.item.container_id(self.tcx));
2349 // We don't want to suggest a container type when the missing
2350 // method is `.clone()` or `.deref()` otherwise we'd suggest
2351 // `Arc::new(foo).clone()`, which is far from what the user wants.
2352 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2353 // implement the `AsRef` trait.
2354 let skip = skippable.contains(&did)
2355 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2356 || 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);
2357 // Make sure the method is defined for the *actual* receiver: we don't
2358 // want to treat `Box<Self>` as a receiver if it only works because of
2359 // an autoderef to `&self`
2360 if pick.autoderefs == 0 && !skip {
2362 pick.item.ident(self.tcx).span,
2363 &format!("the method is available for `{}` here", new_rcvr_t),
2365 err.multipart_suggestion(
2366 "consider wrapping the receiver expression with the \
2369 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2370 (rcvr.span.shrink_to_hi(), ")".to_string()),
2372 Applicability::MaybeIncorrect,
2374 // We don't care about the other suggestions.
2375 alt_rcvr_sugg = true;
2381 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2385 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2387 let mut arbitrary_rcvr = vec![];
2388 // There are no traits implemented, so lets suggest some traits to
2389 // implement, by finding ones that have the item name, and are
2390 // legal to implement.
2391 let mut candidates = all_traits(self.tcx)
2393 // Don't issue suggestions for unstable traits since they're
2394 // unlikely to be implementable anyway
2395 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2396 Some(attr) => attr.level.is_stable(),
2400 // Static candidates are already implemented, and known not to work
2401 // Do not suggest them again
2402 static_candidates.iter().all(|sc| match *sc {
2403 CandidateSource::Trait(def_id) => def_id != info.def_id,
2404 CandidateSource::Impl(def_id) => {
2405 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2410 // We approximate the coherence rules to only suggest
2411 // traits that are legal to implement by requiring that
2412 // either the type or trait is local. Multi-dispatch means
2413 // this isn't perfect (that is, there are cases when
2414 // implementing a trait would be legal but is rejected
2416 unsatisfied_predicates.iter().all(|(p, _, _)| {
2417 match p.kind().skip_binder() {
2418 // Hide traits if they are present in predicates as they can be fixed without
2419 // having to implement them.
2420 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2421 t.def_id() == info.def_id
2423 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2424 p.projection_ty.def_id == info.def_id
2428 }) && (type_is_local || info.def_id.is_local())
2429 && !self.tcx.trait_is_auto(info.def_id)
2431 .associated_value(info.def_id, item_name)
2433 if let ty::AssocKind::Fn = item.kind {
2437 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2438 if let Some(hir::Node::TraitItem(hir::TraitItem {
2439 kind: hir::TraitItemKind::Fn(fn_sig, method),
2441 })) = id.map(|id| self.tcx.hir().get(id))
2443 let self_first_arg = match method {
2444 hir::TraitFn::Required([ident, ..]) => {
2445 ident.name == kw::SelfLower
2447 hir::TraitFn::Provided(body_id) => {
2448 self.tcx.hir().body(*body_id).params.first().map_or(
2453 hir::PatKind::Binding(_, _, ident, _)
2454 if ident.name == kw::SelfLower
2462 if !fn_sig.decl.implicit_self.has_implicit_self()
2465 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2466 arbitrary_rcvr.push(ty.span);
2472 // We only want to suggest public or local traits (#45781).
2473 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2477 .collect::<Vec<_>>();
2478 for span in &arbitrary_rcvr {
2481 "the method might not be found because of this arbitrary self type",
2488 if !candidates.is_empty() {
2489 // Sort from most relevant to least relevant.
2490 candidates.sort_by(|a, b| a.cmp(b).reverse());
2493 let param_type = match rcvr_ty.kind() {
2494 ty::Param(param) => Some(param),
2495 ty::Ref(_, ty, _) => match ty.kind() {
2496 ty::Param(param) => Some(param),
2501 err.help(if param_type.is_some() {
2502 "items from traits can only be used if the type parameter is bounded by the trait"
2504 "items from traits can only be used if the trait is implemented and in scope"
2506 let candidates_len = candidates.len();
2507 let message = |action| {
2509 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2512 if candidates_len == 1 { "trait defines" } else { "traits define" },
2514 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2518 // Obtain the span for `param` and use it for a structured suggestion.
2519 if let Some(param) = param_type {
2520 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2521 let type_param = generics.type_param(param, self.tcx);
2522 let hir = self.tcx.hir();
2523 if let Some(def_id) = type_param.def_id.as_local() {
2524 let id = hir.local_def_id_to_hir_id(def_id);
2525 // Get the `hir::Param` to verify whether it already has any bounds.
2526 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2527 // instead we suggest `T: Foo + Bar` in that case.
2529 Node::GenericParam(param) => {
2535 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2536 let (sp, mut introducer) = if let Some(span) =
2537 ast_generics.bounds_span_for_suggestions(def_id)
2539 (span, Introducer::Plus)
2540 } else if let Some(colon_span) = param.colon_span {
2541 (colon_span.shrink_to_hi(), Introducer::Nothing)
2543 (param.span.shrink_to_hi(), Introducer::Colon)
2547 hir::GenericParamKind::Type { synthetic: true, .. },
2549 introducer = Introducer::Plus
2551 let trait_def_ids: FxHashSet<DefId> = ast_generics
2552 .bounds_for_param(def_id)
2553 .flat_map(|bp| bp.bounds.iter())
2554 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2556 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2557 err.span_suggestions(
2560 "restrict type parameter `{}` with",
2563 candidates.iter().map(|t| {
2567 Introducer::Plus => " +",
2568 Introducer::Colon => ":",
2569 Introducer::Nothing => "",
2571 self.tcx.def_path_str(t.def_id),
2574 Applicability::MaybeIncorrect,
2579 Node::Item(hir::Item {
2580 kind: hir::ItemKind::Trait(.., bounds, _),
2584 let (sp, sep, article) = if bounds.is_empty() {
2585 (ident.span.shrink_to_hi(), ":", "a")
2587 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2589 err.span_suggestions(
2591 &message(format!("add {} supertrait for", article)),
2592 candidates.iter().map(|t| {
2593 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2595 Applicability::MaybeIncorrect,
2604 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2605 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2606 // cases where a positive bound implies a negative impl.
2607 (candidates, Vec::new())
2608 } else if let Some(simp_rcvr_ty) =
2609 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2611 let mut potential_candidates = Vec::new();
2612 let mut explicitly_negative = Vec::new();
2613 for candidate in candidates {
2614 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2617 .all_impls(candidate.def_id)
2619 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2622 let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
2624 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2625 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2628 explicitly_negative.push(candidate);
2630 potential_candidates.push(candidate);
2633 (potential_candidates, explicitly_negative)
2635 // We don't know enough about `recv_ty` to make proper suggestions.
2636 (candidates, Vec::new())
2639 let action = if let Some(param) = param_type {
2640 format!("restrict type parameter `{}` with", param)
2642 // FIXME: it might only need to be imported into scope, not implemented.
2643 "implement".to_string()
2645 match &potential_candidates[..] {
2647 [trait_info] if trait_info.def_id.is_local() => {
2649 self.tcx.def_span(trait_info.def_id),
2651 "`{}` defines an item `{}`, perhaps you need to {} it",
2652 self.tcx.def_path_str(trait_info.def_id),
2659 let mut msg = message(action);
2660 for (i, trait_info) in trait_infos.iter().enumerate() {
2661 msg.push_str(&format!(
2662 "\ncandidate #{}: `{}`",
2664 self.tcx.def_path_str(trait_info.def_id),
2670 match &explicitly_negative[..] {
2674 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2675 self.tcx.def_path_str(trait_info.def_id),
2681 let mut msg = format!(
2682 "the following traits define an item `{}`, but are explicitly unimplemented:",
2685 for trait_info in trait_infos {
2686 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2694 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2695 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2696 pub(crate) fn suggest_else_fn_with_closure(
2698 err: &mut Diagnostic,
2699 expr: &hir::Expr<'_>,
2703 let Some((_def_id_or_name, output, _inputs)) =
2704 self.extract_callable_info(found) else {
2708 if !self.can_coerce(output, expected) {
2712 let parent = self.tcx.hir().parent_id(expr.hir_id);
2713 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2714 let hir::ExprKind::MethodCall(
2715 hir::PathSegment { ident: method_name, .. },
2719 ) = call_expr.kind &&
2720 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2721 let new_name = Ident {
2722 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2723 span: method_name.span,
2725 let probe = self.lookup_probe_for_diagnostic(
2729 ProbeScope::TraitsInScope,
2733 // check the method arguments number
2734 if let Ok(pick) = probe &&
2735 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2736 let fn_args = fn_sig.skip_binder().inputs() &&
2737 fn_args.len() == args.len() + 1 {
2738 err.span_suggestion_verbose(
2739 method_name.span.shrink_to_hi(),
2740 &format!("try calling `{}` instead", new_name.name.as_str()),
2742 Applicability::MaybeIncorrect,
2750 /// Checks whether there is a local type somewhere in the chain of
2751 /// autoderefs of `rcvr_ty`.
2752 fn type_derefs_to_local(
2756 source: SelfSource<'tcx>,
2758 fn is_local(ty: Ty<'_>) -> bool {
2760 ty::Adt(def, _) => def.did().is_local(),
2761 ty::Foreign(did) => did.is_local(),
2762 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2763 ty::Param(_) => true,
2765 // Everything else (primitive types, etc.) is effectively
2766 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2767 // the noise from these sort of types is usually just really
2768 // annoying, rather than any sort of help).
2773 // This occurs for UFCS desugaring of `T::method`, where there is no
2774 // receiver expression for the method call, and thus no autoderef.
2775 if let SelfSource::QPath(_) = source {
2776 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2779 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2783 #[derive(Copy, Clone, Debug)]
2784 pub enum SelfSource<'a> {
2785 QPath(&'a hir::Ty<'a>),
2786 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2789 #[derive(Copy, Clone)]
2790 pub struct TraitInfo {
2794 impl PartialEq for TraitInfo {
2795 fn eq(&self, other: &TraitInfo) -> bool {
2796 self.cmp(other) == Ordering::Equal
2799 impl Eq for TraitInfo {}
2800 impl PartialOrd for TraitInfo {
2801 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2802 Some(self.cmp(other))
2805 impl Ord for TraitInfo {
2806 fn cmp(&self, other: &TraitInfo) -> Ordering {
2807 // Local crates are more important than remote ones (local:
2808 // `cnum == 0`), and otherwise we throw in the defid for totality.
2810 let lhs = (other.def_id.krate, other.def_id);
2811 let rhs = (self.def_id.krate, self.def_id);
2816 /// Retrieves all traits in this crate and any dependent crates,
2817 /// and wraps them into `TraitInfo` for custom sorting.
2818 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2819 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2822 fn print_disambiguation_help<'tcx>(
2824 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2825 err: &mut Diagnostic,
2828 kind: ty::AssocKind,
2831 candidate: Option<usize>,
2832 source_map: &source_map::SourceMap,
2833 fn_has_self_parameter: bool,
2835 let mut applicability = Applicability::MachineApplicable;
2836 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2839 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2840 std::iter::once(receiver)
2842 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2843 applicability = Applicability::HasPlaceholders;
2846 .collect::<Vec<_>>()
2849 let trait_name = if !fn_has_self_parameter {
2850 format!("<{} as {}>", rcvr_ty, trait_name)
2854 (span, format!("{}::{}{}", trait_name, item_name, args))
2856 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2858 err.span_suggestion_verbose(
2861 "disambiguate the {} for {}",
2862 kind.as_def_kind().descr(def_id),
2863 if let Some(candidate) = candidate {
2864 format!("candidate #{}", candidate)
2866 "the candidate".to_string()