1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
6 use rustc_ast::ast::Mutability;
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8 use rustc_errors::StashKey;
10 pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
14 use rustc_hir::def::DefKind;
15 use rustc_hir::def_id::DefId;
16 use rustc_hir::lang_items::LangItem;
17 use rustc_hir::PatKind::Binding;
18 use rustc_hir::PathSegment;
19 use rustc_hir::{ExprKind, Node, QPath};
20 use rustc_infer::infer::{
21 type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
24 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
25 use rustc_middle::traits::util::supertraits;
26 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
27 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
28 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
29 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
30 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
31 use rustc_span::symbol::{kw, sym, Ident};
32 use rustc_span::Symbol;
33 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
34 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
35 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
36 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
37 use rustc_trait_selection::traits::{
38 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
41 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
42 use super::{CandidateSource, MethodError, NoMatchData};
43 use rustc_hir::intravisit::Visitor;
44 use std::cmp::Ordering;
47 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
51 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
52 // so we look for these beforehand.
53 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
54 // If it's not a simple function, look for things which implement `FnOnce`.
56 let Some(fn_once) = tcx.lang_items().fn_once_trait() else {
60 // This conditional prevents us from asking to call errors and unresolved types.
61 // It might seem that we can use `predicate_must_hold_modulo_regions`,
62 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
63 // type resolution always gives a "maybe" here.
64 if self.autoderef(span, ty).any(|(ty, _)| {
65 info!("check deref {:?} error", ty);
66 matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
71 self.autoderef(span, ty).any(|(ty, _)| {
72 info!("check deref {:?} impl FnOnce", ty);
74 let trait_ref = tcx.mk_trait_ref(
78 self.next_ty_var(TypeVariableOrigin {
79 kind: TypeVariableOriginKind::MiscVariable,
84 let poly_trait_ref = ty::Binder::dummy(trait_ref);
85 let obligation = Obligation::misc(
90 poly_trait_ref.without_const(),
92 self.predicate_may_hold(&obligation)
99 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
100 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
103 pub fn report_method_error(
108 source: SelfSource<'tcx>,
109 error: MethodError<'tcx>,
110 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
111 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
112 // Avoid suggestions when we don't know what's going on.
113 if rcvr_ty.references_error() {
117 let sugg_span = if let SelfSource::MethodCall(expr) = source {
118 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
119 self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)).span
125 MethodError::NoMatch(mut no_match_data) => {
126 return self.report_no_match_method_error(
137 MethodError::Ambiguity(mut sources) => {
138 let mut err = struct_span_err!(
142 "multiple applicable items in scope"
144 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
146 self.note_candidates_on_method_error(
158 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
159 let kind = kind.descr(def_id);
160 let mut err = struct_span_err!(
164 "{} `{}` is private",
168 err.span_label(item_name.span, &format!("private {}", kind));
172 .span_if_local(def_id)
173 .unwrap_or_else(|| self.tcx.def_span(def_id));
174 err.span_label(sp, &format!("private {} defined here", kind));
175 self.suggest_valid_traits(&mut err, out_of_scope_traits);
179 MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
180 let msg = if needs_mut {
181 with_forced_trimmed_paths!(format!(
182 "the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
185 format!("the `{item_name}` method cannot be invoked on a trait object")
187 let mut err = self.sess().struct_span_err(span, &msg);
189 err.span_label(bound_span, "this has a `Sized` requirement");
191 if !candidates.is_empty() {
193 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
194 add a `use` for {one_of_them}:",
195 an = if candidates.len() == 1 { "an" } else { "" },
196 s = pluralize!(candidates.len()),
197 were = pluralize!("was", candidates.len()),
198 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
200 self.suggest_use_candidates(&mut err, help, candidates);
202 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
204 let trait_type = self.tcx.mk_ref(
206 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
208 let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
209 let mut kind = &self_expr.kind;
210 while let hir::ExprKind::AddrOf(_, _, expr)
211 | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
215 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
216 && let hir::def::Res::Local(hir_id) = path.res
217 && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id)
218 && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
219 && let Some(hir::Node::Param(param)) = self.tcx.hir().find(parent_hir_id)
220 && let parent_hir_id = self.tcx.hir().get_parent_node(param.hir_id)
221 && let Some(node) = self.tcx.hir().find(parent_hir_id)
222 && let Some(decl) = node.fn_decl()
223 && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == param.ty_span)
224 && let hir::TyKind::Ref(_, mut_ty) = &ty.kind
225 && let hir::Mutability::Not = mut_ty.mutbl
227 err.span_suggestion_verbose(
228 mut_ty.ty.span.shrink_to_lo(),
231 Applicability::MachineApplicable,
241 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
246 pub fn report_no_match_method_error(
251 source: SelfSource<'tcx>,
252 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
254 no_match_data: &mut NoMatchData<'tcx>,
255 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
256 let mode = no_match_data.mode;
258 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
259 let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
260 let is_method = mode == Mode::MethodCall;
261 let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
262 let lev_candidate = no_match_data.lev_candidate;
263 let item_kind = if is_method {
265 } else if rcvr_ty.is_enum() {
266 "variant or associated item"
268 match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
269 (Some(name), false) if name.is_lowercase() => "function or associated item",
270 (Some(_), false) => "associated item",
271 (Some(_), true) | (None, false) => "variant or associated item",
272 (None, true) => "variant",
276 if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
277 || self.suggest_constraining_numerical_ty(
278 tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
283 span = item_name.span;
285 // Don't show generic arguments when the method can't be found in any implementation (#81576).
286 let mut ty_str_reported = ty_str.clone();
287 if let ty::Adt(_, generics) = rcvr_ty.kind() {
288 if generics.len() > 0 {
289 let mut autoderef = self.autoderef(span, rcvr_ty);
290 let candidate_found = autoderef.any(|(ty, _)| {
291 if let ty::Adt(adt_def, _) = ty.kind() {
293 .inherent_impls(adt_def.did())
295 .any(|def_id| self.associated_value(*def_id, item_name).is_some())
300 let has_deref = autoderef.step_count() > 0;
301 if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
302 if let Some((path_string, _)) = ty_str.split_once('<') {
303 ty_str_reported = path_string.to_string();
309 let mut err = struct_span_err!(
313 "no {} named `{}` found for {} `{}` in the current scope",
316 rcvr_ty.prefix_string(self.tcx),
319 if rcvr_ty.references_error() {
320 err.downgrade_to_delayed_bug();
323 if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
324 self.suggest_await_before_method(
325 &mut err, item_name, rcvr_ty, cal, span,
329 tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
333 "you are looking for the module in `std`, not the primitive type",
335 Applicability::MachineApplicable,
338 if let ty::RawPtr(_) = &rcvr_ty.kind() {
340 "try using `<*const T>::as_ref()` to get a reference to the \
341 type behind the pointer: https://doc.rust-lang.org/std/\
342 primitive.pointer.html#method.as_ref",
345 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
346 to invalid or uninitialized memory is undefined behavior",
350 let ty_span = match rcvr_ty.kind() {
351 ty::Param(param_type) => {
352 Some(param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()))
354 ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
357 if let Some(span) = ty_span {
361 "{item_kind} `{item_name}` not found for this {}",
362 rcvr_ty.prefix_string(self.tcx)
367 if let SelfSource::MethodCall(rcvr_expr) = source {
368 self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
370 self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id));
372 self.lookup_probe(item_name, output_ty, call_expr, ProbeScope::AllTraits);
377 let mut custom_span_label = false;
379 let static_candidates = &mut no_match_data.static_candidates;
380 if !static_candidates.is_empty() {
382 "found the following associated functions; to be used as methods, \
383 functions must have a `self` parameter",
385 err.span_label(span, "this is an associated function, not a method");
386 custom_span_label = true;
388 if static_candidates.len() == 1 {
389 self.suggest_associated_call_syntax(
399 self.note_candidates_on_method_error(
408 } else if static_candidates.len() > 1 {
409 self.note_candidates_on_method_error(
420 let mut bound_spans = vec![];
421 let mut restrict_type_params = false;
422 let mut unsatisfied_bounds = false;
423 if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
424 let msg = "consider using `len` instead";
425 if let SelfSource::MethodCall(_expr) = source {
426 err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
428 err.span_label(span, msg);
430 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
431 let iterator_trait = self.tcx.def_path_str(iterator_trait);
433 "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
436 } else if !unsatisfied_predicates.is_empty() {
437 let mut type_params = FxHashMap::default();
439 // Pick out the list of unimplemented traits on the receiver.
440 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
441 let mut unimplemented_traits = FxHashMap::default();
442 let mut unimplemented_traits_only = true;
443 for (predicate, _parent_pred, cause) in unsatisfied_predicates {
444 if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
445 (predicate.kind().skip_binder(), cause.as_ref())
447 if p.trait_ref.self_ty() != rcvr_ty {
448 // This is necessary, not just to keep the errors clean, but also
449 // because our derived obligations can wind up with a trait ref that
450 // requires a different param_env to be correctly compared.
453 unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
454 predicate.kind().rebind(p.trait_ref),
456 cause: cause.clone(),
457 param_env: self.param_env,
458 predicate: *predicate,
465 // Make sure that, if any traits other than the found ones were involved,
466 // we don't don't report an unimplemented trait.
467 // We don't want to say that `iter::Cloned` is not an iterator, just
468 // because of some non-Clone item being iterated over.
469 for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
470 match predicate.kind().skip_binder() {
471 ty::PredicateKind::Clause(ty::Clause::Trait(p))
472 if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
474 unimplemented_traits_only = false;
480 let mut collect_type_param_suggestions =
481 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
482 // We don't care about regions here, so it's fine to skip the binder here.
483 if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
484 (self_ty.kind(), parent_pred.kind().skip_binder())
486 let hir = self.tcx.hir();
487 let node = match p.trait_ref.self_ty().kind() {
489 // Account for `fn` items like in `issue-35677.rs` to
490 // suggest restricting its type params.
492 hir.body_owner(hir::BodyId { hir_id: self.body_id });
493 Some(hir.get(parent_body))
496 def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
500 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
501 if let Some(g) = kind.generics() {
503 g.tail_span_for_predicate_suggestion(),
504 g.add_where_or_trailing_comma(),
508 .or_insert_with(FxHashSet::default)
509 .insert(obligation.to_owned());
514 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
516 "doesn't satisfy `{}`",
517 if obligation.len() > 50 { quiet } else { obligation }
519 match &self_ty.kind() {
520 // Point at the type that couldn't satisfy the bound.
521 ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
522 // Point at the trait object that couldn't satisfy the bound.
523 ty::Dynamic(preds, _, _) => {
524 for pred in preds.iter() {
525 match pred.skip_binder() {
526 ty::ExistentialPredicate::Trait(tr) => {
527 bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
529 ty::ExistentialPredicate::Projection(_)
530 | ty::ExistentialPredicate::AutoTrait(_) => {}
534 // Point at the closure that couldn't satisfy the bound.
535 ty::Closure(def_id, _) => bound_spans
536 .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
540 let mut format_pred = |pred: ty::Predicate<'tcx>| {
541 let bound_predicate = pred.kind();
542 match bound_predicate.skip_binder() {
543 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
544 let pred = bound_predicate.rebind(pred);
545 // `<Foo as Iterator>::Item = String`.
546 let projection_ty = pred.skip_binder().projection_ty;
548 let substs_with_infer_self = tcx.mk_substs(
549 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
550 .chain(projection_ty.substs.iter().skip(1)),
553 let quiet_projection_ty =
554 tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
556 let term = pred.skip_binder().term;
558 let obligation = format!("{} = {}", projection_ty, term);
559 let quiet = with_forced_trimmed_paths!(format!(
561 quiet_projection_ty, term
564 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
565 Some((obligation, projection_ty.self_ty()))
567 ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
568 let p = poly_trait_ref.trait_ref;
569 let self_ty = p.self_ty();
570 let path = p.print_only_trait_path();
571 let obligation = format!("{}: {}", self_ty, path);
572 let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
573 bound_span_label(self_ty, &obligation, &quiet);
574 Some((obligation, self_ty))
580 // Find all the requirements that come from a local `impl` block.
581 let mut skip_list: FxHashSet<_> = Default::default();
582 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
583 for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
585 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
586 .filter_map(|(p, parent, c)| match c.code() {
587 ObligationCauseCode::ImplDerivedObligation(data) => {
588 Some((&data.derived, p, parent, data.impl_def_id, data))
593 let parent_trait_ref = data.parent_trait_pred;
594 let path = parent_trait_ref.print_modifiers_and_trait_path();
595 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
596 let unsatisfied_msg = "unsatisfied trait bound introduced here";
597 let derive_msg = "unsatisfied trait bound introduced in this `derive` macro";
598 match self.tcx.hir().get_if_local(impl_def_id) {
599 // Unmet obligation comes from a `derive` macro, point at it once to
600 // avoid multiple span labels pointing at the same place.
601 Some(Node::Item(hir::Item {
602 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
605 self_ty.span.ctxt().outer_expn_data().kind,
606 ExpnKind::Macro(MacroKind::Derive, _)
608 of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
609 Some(ExpnKind::Macro(MacroKind::Derive, _))
612 let span = self_ty.span.ctxt().outer_expn_data().call_site;
613 let mut spans: MultiSpan = span.into();
614 spans.push_span_label(span, derive_msg);
615 let entry = spanned_predicates.entry(spans);
616 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
619 // Unmet obligation coming from an `impl`.
620 Some(Node::Item(hir::Item {
621 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
626 unsatisfied_predicates.iter().any(|(pred, _, _)| {
627 match pred.kind().skip_binder() {
628 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
629 Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
630 && pred.polarity == ty::ImplPolarity::Positive
635 for param in generics.params {
636 if param.span == cause.span && sized_pred {
637 let (sp, sugg) = match param.colon_span {
638 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
639 None => (param.span.shrink_to_hi(), ": ?Sized"),
641 err.span_suggestion_verbose(
643 "consider relaxing the type parameter's implicit \
646 Applicability::MachineApplicable,
650 if let Some(pred) = parent_p {
651 // Done to add the "doesn't satisfy" `span_label`.
652 let _ = format_pred(*pred);
655 let mut spans = if cause.span != *item_span {
656 let mut spans: MultiSpan = cause.span.into();
657 spans.push_span_label(cause.span, unsatisfied_msg);
660 let mut spans = Vec::with_capacity(2);
661 if let Some(trait_ref) = of_trait {
662 spans.push(trait_ref.path.span);
664 spans.push(self_ty.span);
667 if let Some(trait_ref) = of_trait {
668 spans.push_span_label(trait_ref.path.span, "");
670 spans.push_span_label(self_ty.span, "");
672 let entry = spanned_predicates.entry(spans);
673 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
675 Some(Node::Item(hir::Item {
676 kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
680 tcx.sess.delay_span_bug(
682 "auto trait is invoked with no method error, but no error reported?",
685 Some(_) => unreachable!(),
689 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
690 spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
691 for (span, (_path, _self_ty, preds)) in spanned_predicates {
692 let mut preds: Vec<_> = preds
694 .filter_map(|pred| format_pred(*pred))
695 .map(|(p, _)| format!("`{}`", p))
699 let msg = if let [pred] = &preds[..] {
700 format!("trait bound {} was not satisfied", pred)
702 format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
704 err.span_note(span, &msg);
705 unsatisfied_bounds = true;
708 // The requirements that didn't have an `impl` span to show.
709 let mut bound_list = unsatisfied_predicates
711 .filter_map(|(pred, parent_pred, _cause)| {
712 format_pred(*pred).map(|(p, self_ty)| {
713 collect_type_param_suggestions(self_ty, *pred, &p);
716 None => format!("`{}`", &p),
717 Some(parent_pred) => match format_pred(*parent_pred) {
718 None => format!("`{}`", &p),
719 Some((parent_p, _)) => {
720 collect_type_param_suggestions(self_ty, *parent_pred, &p);
721 format!("`{}`\nwhich is required by `{}`", p, parent_p)
729 .filter(|(_, pred)| !skip_list.contains(&pred))
732 .collect::<Vec<(usize, String)>>();
734 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
735 restrict_type_params = true;
736 // #74886: Sort here so that the output is always the same.
737 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
739 err.span_suggestion_verbose(
742 "consider restricting the type parameter{s} to satisfy the \
744 s = pluralize!(obligations.len())
746 format!("{} {}", add_where_or_comma, obligations.join(", ")),
747 Applicability::MaybeIncorrect,
751 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
752 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
753 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
755 if !bound_list.is_empty() || !skip_list.is_empty() {
757 bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
758 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
759 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
760 let (primary_message, label) = if unimplemented_traits.len() == 1
761 && unimplemented_traits_only
766 .map(|(_, (trait_ref, obligation))| {
767 if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
772 let OnUnimplementedNote { message, label, .. } =
773 self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
780 let primary_message = primary_message.unwrap_or_else(|| {
782 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
783 but its trait bounds were not satisfied"
786 err.set_primary_message(&primary_message);
787 if let Some(label) = label {
788 custom_span_label = true;
789 err.span_label(span, label);
791 if !bound_list.is_empty() {
793 "the following trait bounds were not satisfied:\n{bound_list}"
796 self.suggest_derive(&mut err, &unsatisfied_predicates);
798 unsatisfied_bounds = true;
802 let label_span_not_found = |err: &mut Diagnostic| {
803 if unsatisfied_predicates.is_empty() {
804 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
805 let is_string_or_ref_str = match rcvr_ty.kind() {
806 ty::Ref(_, ty, _) => {
810 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
813 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
816 if is_string_or_ref_str && item_name.name == sym::iter {
817 err.span_suggestion_verbose(
819 "because of the in-memory representation of `&str`, to obtain \
820 an `Iterator` over each of its codepoint use method `chars`",
822 Applicability::MachineApplicable,
825 if let ty::Adt(adt, _) = rcvr_ty.kind() {
826 let mut inherent_impls_candidate = self
828 .inherent_impls(adt.did())
832 if let Some(assoc) = self.associated_value(*def_id, item_name) {
833 // Check for both mode is the same so we avoid suggesting
834 // incorrect associated item.
835 match (mode, assoc.fn_has_self_parameter, source) {
836 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
837 // We check that the suggest type is actually
838 // different from the received one
839 // So we avoid suggestion method with Box<Self>
841 self.tcx.at(span).type_of(*def_id) != rcvr_ty
842 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
844 (Mode::Path, false, _) => true,
851 .collect::<Vec<_>>();
852 if !inherent_impls_candidate.is_empty() {
853 inherent_impls_candidate.sort();
854 inherent_impls_candidate.dedup();
856 // number of type to shows at most.
857 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
858 let type_candidates = inherent_impls_candidate
862 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
866 let additional_types = if inherent_impls_candidate.len() > limit {
867 format!("\nand {} more types", inherent_impls_candidate.len() - limit)
872 "the {item_kind} was found for\n{}{}",
873 type_candidates, additional_types
879 if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
882 format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
887 // If the method name is the name of a field with a function or closure type,
888 // give a helping note that it has to be called as `(x.f)(...)`.
889 if let SelfSource::MethodCall(expr) = source {
890 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
891 && lev_candidate.is_none()
892 && !custom_span_label
894 label_span_not_found(&mut err);
896 } else if !custom_span_label {
897 label_span_not_found(&mut err);
900 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
901 // can't be called due to `typeof(expr): Clone` not holding.
902 if unsatisfied_predicates.is_empty() {
903 self.suggest_calling_method_on_field(&mut err, source, span, rcvr_ty, item_name);
906 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
910 for (span, msg) in bound_spans.into_iter() {
911 err.span_label(span, &msg);
914 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
916 self.suggest_traits_to_import(
921 args.map(|(_, args)| args.len() + 1),
923 no_match_data.out_of_scope_traits.clone(),
924 &unsatisfied_predicates,
930 // Don't emit a suggestion if we found an actual method
931 // that had unsatisfied trait bounds
932 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
933 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
934 if let Some(suggestion) = lev_distance::find_best_match_for_name(
935 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
941 "there is a variant with a similar name",
943 Applicability::MaybeIncorrect,
948 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
949 let msg = "remove this method call";
950 let mut fallback_span = true;
951 if let SelfSource::MethodCall(expr) = source {
952 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
953 if let Some(span) = call_expr.span.trim_start(expr.span) {
954 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
955 fallback_span = false;
959 err.span_label(span, msg);
961 } else if let Some(lev_candidate) = lev_candidate {
962 // Don't emit a suggestion if we found an actual method
963 // that had unsatisfied trait bounds
964 if unsatisfied_predicates.is_empty() {
965 let def_kind = lev_candidate.kind.as_def_kind();
966 // Methods are defined within the context of a struct and their first parameter is always self,
967 // which represents the instance of the struct the method is being called on
968 // Associated functions don’t take self as a parameter and
969 // they are not methods because they don’t have an instance of the struct to work with.
970 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
973 "there is a method with a similar name",
975 Applicability::MaybeIncorrect,
981 "there is {} {} with a similar name",
983 def_kind.descr(lev_candidate.def_id),
986 Applicability::MaybeIncorrect,
992 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
996 fn note_candidates_on_method_error(
1000 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1002 err: &mut Diagnostic,
1003 sources: &mut Vec<CandidateSource>,
1004 sugg_span: Option<Span>,
1008 // Dynamic limit to avoid hiding just one candidate, which is silly.
1009 let limit = if sources.len() == 5 { 5 } else { 4 };
1011 for (idx, source) in sources.iter().take(limit).enumerate() {
1013 CandidateSource::Impl(impl_did) => {
1014 // Provide the best span we can. Use the item, if local to crate, else
1015 // the impl, if local to crate (item may be defaulted), else nothing.
1016 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
1017 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
1018 self.associated_value(impl_trait_ref.def_id, item_name)
1023 let note_span = if item.def_id.is_local() {
1024 Some(self.tcx.def_span(item.def_id))
1025 } else if impl_did.is_local() {
1026 Some(self.tcx.def_span(impl_did))
1031 let impl_ty = self.tcx.at(span).type_of(impl_did);
1033 let insertion = match self.tcx.impl_trait_ref(impl_did) {
1034 None => String::new(),
1035 Some(trait_ref) => {
1036 format!(" of the trait `{}`", self.tcx.def_path_str(trait_ref.def_id))
1040 let (note_str, idx) = if sources.len() > 1 {
1043 "candidate #{} is defined in an impl{} for the type `{}`",
1053 "the candidate is defined in an impl{} for the type `{}`",
1059 if let Some(note_span) = note_span {
1060 // We have a span pointing to the method. Show note with snippet.
1061 err.span_note(note_span, ¬e_str);
1063 err.note(¬e_str);
1065 if let Some(sugg_span) = sugg_span
1066 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
1067 let path = self.tcx.def_path_str(trait_ref.def_id);
1069 let ty = match item.kind {
1070 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
1071 ty::AssocKind::Fn => self
1073 .fn_sig(item.def_id)
1077 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
1079 .unwrap_or(rcvr_ty),
1081 print_disambiguation_help(
1091 self.tcx.sess.source_map(),
1092 item.fn_has_self_parameter,
1096 CandidateSource::Trait(trait_did) => {
1097 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
1098 let item_span = self.tcx.def_span(item.def_id);
1099 let idx = if sources.len() > 1 {
1101 "candidate #{} is defined in the trait `{}`",
1103 self.tcx.def_path_str(trait_did)
1105 err.span_note(item_span, msg);
1109 "the candidate is defined in the trait `{}`",
1110 self.tcx.def_path_str(trait_did)
1112 err.span_note(item_span, msg);
1115 if let Some(sugg_span) = sugg_span {
1116 let path = self.tcx.def_path_str(trait_did);
1117 print_disambiguation_help(
1127 self.tcx.sess.source_map(),
1128 item.fn_has_self_parameter,
1134 if sources.len() > limit {
1135 err.note(&format!("and {} others", sources.len() - limit));
1139 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1140 /// doesn't take a `self` receiver.
1141 fn suggest_associated_call_syntax(
1143 err: &mut Diagnostic,
1144 static_candidates: &Vec<CandidateSource>,
1146 source: SelfSource<'tcx>,
1148 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1151 let mut has_unsuggestable_args = false;
1152 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1153 // When the "method" is resolved through dereferencing, we really want the
1154 // original type that has the associated function for accurate suggestions.
1156 let impl_ty = self.tcx.type_of(*impl_did);
1157 let target_ty = self
1158 .autoderef(sugg_span, rcvr_ty)
1159 .find(|(rcvr_ty, _)| {
1160 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1161 .types_may_unify(*rcvr_ty, impl_ty)
1163 .map_or(impl_ty, |(ty, _)| ty)
1165 if let ty::Adt(def, substs) = target_ty.kind() {
1166 // If there are any inferred arguments, (`{integer}`), we should replace
1167 // them with underscores to allow the compiler to infer them
1168 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1169 if !arg.is_suggestable(self.tcx, true) {
1170 has_unsuggestable_args = true;
1171 match arg.unpack() {
1172 GenericArgKind::Lifetime(_) => self
1173 .next_region_var(RegionVariableOrigin::MiscVariable(
1174 rustc_span::DUMMY_SP,
1177 GenericArgKind::Type(_) => self
1178 .next_ty_var(TypeVariableOrigin {
1179 span: rustc_span::DUMMY_SP,
1180 kind: TypeVariableOriginKind::MiscVariable,
1183 GenericArgKind::Const(arg) => self
1186 ConstVariableOrigin {
1187 span: rustc_span::DUMMY_SP,
1188 kind: ConstVariableOriginKind::MiscVariable,
1198 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1200 self.ty_to_value_string(target_ty)
1203 self.ty_to_value_string(rcvr_ty.peel_refs())
1205 if let SelfSource::MethodCall(_) = source {
1206 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1207 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1208 && assoc.kind == ty::AssocKind::Fn
1210 let sig = self.tcx.fn_sig(assoc.def_id);
1211 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1214 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1219 let mut applicability = Applicability::MachineApplicable;
1220 let args = if let Some((receiver, args)) = args {
1221 // The first arg is the same kind as the receiver
1222 let explicit_args = if first_arg.is_some() {
1223 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1225 // There is no `Self` kind to infer the arguments from
1226 if has_unsuggestable_args {
1227 applicability = Applicability::HasPlaceholders;
1229 args.iter().collect()
1233 first_arg.unwrap_or(""),
1240 .span_to_snippet(arg.span)
1241 .unwrap_or_else(|_| {
1242 applicability = Applicability::HasPlaceholders;
1245 .collect::<Vec<_>>()
1249 applicability = Applicability::HasPlaceholders;
1252 err.span_suggestion(
1254 "use associated function syntax instead",
1255 format!("{}::{}{}", ty_str, item_name, args),
1259 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1263 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1264 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1265 fn suggest_calling_field_as_fn(
1269 expr: &hir::Expr<'_>,
1271 err: &mut Diagnostic,
1274 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1275 ty::Adt(def, substs) if !def.is_enum() => {
1276 let variant = &def.non_enum_variant();
1277 tcx.find_field_index(item_name, variant).map(|index| {
1278 let field = &variant.fields[index];
1279 let field_ty = field.ty(tcx, substs);
1285 if let Some((field, field_ty)) = field_receiver {
1286 let scope = tcx.parent_module(self.body_id);
1287 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1290 if self.is_fn_ty(field_ty, span) {
1291 let expr_span = expr.span.to(item_name.span);
1292 err.multipart_suggestion(
1294 "to call the function stored in `{}`, \
1295 surround the field access with parentheses",
1299 (expr_span.shrink_to_lo(), '('.to_string()),
1300 (expr_span.shrink_to_hi(), ')'.to_string()),
1302 Applicability::MachineApplicable,
1305 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1307 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1308 err.span_suggestion(
1310 "remove the arguments",
1312 Applicability::MaybeIncorrect,
1318 let field_kind = if is_accessible { "field" } else { "private field" };
1319 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1325 /// Suggest possible range with adding parentheses, for example:
1326 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1327 fn suggest_wrapping_range_with_parens(
1331 source: SelfSource<'tcx>,
1336 if let SelfSource::MethodCall(expr) = source {
1337 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1338 if let Node::Expr(parent_expr) = parent {
1339 let lang_item = match parent_expr.kind {
1340 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1341 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1342 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1343 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1344 Some(LangItem::RangeToInclusive)
1348 ExprKind::Call(ref func, _) => match func.kind {
1349 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1350 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1351 Some(LangItem::RangeInclusiveStruct)
1358 if lang_item.is_none() {
1362 let span_included = match parent_expr.kind {
1363 hir::ExprKind::Struct(_, eps, _) => {
1364 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1366 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1367 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1375 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1377 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1379 let pick = self.probe_for_name(
1385 ProbeScope::AllTraits,
1388 let range_span = parent_expr.span.with_hi(expr.span.hi());
1389 tcx.sess.emit_err(errors::MissingParentheseInRange {
1391 ty_str: ty_str.to_string(),
1392 method_name: item_name.as_str().to_string(),
1393 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1394 func_name: item_name.name.as_str().to_string(),
1395 left: range_span.shrink_to_lo(),
1396 right: range_span.shrink_to_hi(),
1407 fn suggest_constraining_numerical_ty(
1411 source: SelfSource<'_>,
1417 let found_candidate = all_traits(self.tcx)
1419 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1420 let found_assoc = |ty: Ty<'tcx>| {
1421 simplify_type(tcx, ty, TreatParams::AsInfer)
1423 tcx.incoherent_impls(simp)
1425 .find_map(|&id| self.associated_value(id, item_name))
1429 let found_candidate = found_candidate
1430 || found_assoc(tcx.types.i8)
1431 || found_assoc(tcx.types.i16)
1432 || found_assoc(tcx.types.i32)
1433 || found_assoc(tcx.types.i64)
1434 || found_assoc(tcx.types.i128)
1435 || found_assoc(tcx.types.u8)
1436 || found_assoc(tcx.types.u16)
1437 || found_assoc(tcx.types.u32)
1438 || found_assoc(tcx.types.u64)
1439 || found_assoc(tcx.types.u128)
1440 || found_assoc(tcx.types.f32)
1441 || found_assoc(tcx.types.f32);
1443 && actual.is_numeric()
1444 && !actual.has_concrete_skeleton()
1445 && let SelfSource::MethodCall(expr) = source
1447 let mut err = struct_span_err!(
1451 "can't call {} `{}` on ambiguous numeric type `{}`",
1456 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1458 ExprKind::Lit(ref lit) => {
1463 .span_to_snippet(lit.span)
1464 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1466 // If this is a floating point literal that ends with '.',
1467 // get rid of it to stop this from becoming a member access.
1468 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1469 err.span_suggestion(
1472 "you must specify a concrete type for this numeric value, \
1476 format!("{snippet}_{concrete_type}"),
1477 Applicability::MaybeIncorrect,
1480 ExprKind::Path(QPath::Resolved(_, path)) => {
1482 if let hir::def::Res::Local(hir_id) = path.res {
1483 let span = tcx.hir().span(hir_id);
1484 let filename = tcx.sess.source_map().span_to_filename(span);
1487 self.tcx.hir().get_parent(hir_id);
1489 "you must specify a type for this binding, like `{}`",
1493 match (filename, parent_node) {
1496 Node::Local(hir::Local {
1497 source: hir::LocalSource::Normal,
1502 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1503 err.span_suggestion(
1504 // account for `let x: _ = 42;`
1508 format!(": {concrete_type}"),
1509 Applicability::MaybeIncorrect,
1513 err.span_label(span, msg);
1526 /// For code `rect::area(...)`,
1527 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1528 /// we try to suggest `rect.area()`
1529 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1530 debug!("suggest_assoc_method_call segs: {:?}", segs);
1531 let [seg1, seg2] = segs else { return; };
1532 let Some(mut diag) =
1533 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1536 let map = self.infcx.tcx.hir();
1537 let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
1538 struct LetVisitor<'a> {
1539 result: Option<&'a hir::Expr<'a>>,
1543 // FIXME: This really should be taking scoping, etc into account.
1544 impl<'v> Visitor<'v> for LetVisitor<'v> {
1545 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1546 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1547 && let Binding(_, _, ident, ..) = pat.kind
1548 && ident.name == self.ident_name
1550 self.result = *init;
1552 hir::intravisit::walk_stmt(self, ex);
1557 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1558 visitor.visit_body(&body);
1560 let parent = self.tcx.hir().parent_id(seg1.hir_id);
1561 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1562 && let Some(expr) = visitor.result
1563 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1565 let probe = self.lookup_probe(
1569 ProbeScope::TraitsInScope,
1572 let sm = self.infcx.tcx.sess.source_map();
1573 diag.span_suggestion_verbose(
1574 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1575 "you may have meant to call an instance method",
1577 Applicability::MaybeIncorrect,
1584 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1585 fn suggest_calling_method_on_field(
1587 err: &mut Diagnostic,
1588 source: SelfSource<'tcx>,
1593 if let SelfSource::MethodCall(expr) = source
1594 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1595 && let Some((fields, substs)) =
1596 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1598 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1600 let lang_items = self.tcx.lang_items();
1601 let never_mention_traits = [
1602 lang_items.clone_trait(),
1603 lang_items.deref_trait(),
1604 lang_items.deref_mut_trait(),
1605 self.tcx.get_diagnostic_item(sym::AsRef),
1606 self.tcx.get_diagnostic_item(sym::AsMut),
1607 self.tcx.get_diagnostic_item(sym::Borrow),
1608 self.tcx.get_diagnostic_item(sym::BorrowMut),
1610 let candidate_fields: Vec<_> = fields
1611 .filter_map(|candidate_field| {
1612 self.check_for_nested_field_satisfying(
1619 ProbeScope::TraitsInScope,
1621 .map_or(false, |pick| {
1622 !never_mention_traits
1625 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1637 .map(|id| id.name.to_ident_string())
1638 .collect::<Vec<String>>()
1643 let len = candidate_fields.len();
1645 err.span_suggestions(
1646 item_name.span.shrink_to_lo(),
1648 "{} of the expressions' fields {} a method of the same name",
1649 if len > 1 { "some" } else { "one" },
1650 if len > 1 { "have" } else { "has" },
1652 candidate_fields.iter().map(|path| format!("{path}.")),
1653 Applicability::MaybeIncorrect,
1659 fn check_for_inner_self(
1661 err: &mut Diagnostic,
1662 source: SelfSource<'tcx>,
1667 let SelfSource::MethodCall(expr) = source else { return; };
1668 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1670 let ty::Adt(kind, substs) = actual.kind() else { return; };
1671 match kind.adt_kind() {
1672 ty::AdtKind::Enum => {
1673 let matching_variants: Vec<_> = kind
1676 .flat_map(|variant| {
1677 let [field] = &variant.fields[..] else { return None; };
1678 let field_ty = field.ty(tcx, substs);
1680 // Skip `_`, since that'll just lead to ambiguity.
1681 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1685 self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
1687 .map(|pick| (variant, field, pick))
1691 let ret_ty_matches = |diagnostic_item| {
1692 if let Some(ret_ty) = self
1695 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1696 && let ty::Adt(kind, _) = ret_ty.kind()
1697 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1705 match &matching_variants[..] {
1706 [(_, field, pick)] => {
1707 let self_ty = field.ty(tcx, substs);
1709 tcx.def_span(pick.item.def_id),
1710 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1712 let (article, kind, variant, question) =
1713 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1714 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1715 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1716 ("an", "Option", "None", ret_ty_matches(sym::Option))
1721 err.span_suggestion_verbose(
1722 expr.span.shrink_to_hi(),
1724 "use the `?` operator to extract the `{self_ty}` value, propagating \
1725 {article} `{kind}::{variant}` value to the caller"
1728 Applicability::MachineApplicable,
1731 err.span_suggestion_verbose(
1732 expr.span.shrink_to_hi(),
1734 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1735 panicking if the value is {article} `{kind}::{variant}`"
1737 ".expect(\"REASON\")",
1738 Applicability::HasPlaceholders,
1742 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1746 // Target wrapper types - types that wrap or pretend to wrap another type,
1747 // perhaps this inner type is meant to be called?
1748 ty::AdtKind::Struct | ty::AdtKind::Union => {
1749 let [first] = ***substs else { return; };
1750 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1751 let Ok(pick) = self.lookup_probe(
1755 ProbeScope::TraitsInScope,
1758 let name = self.ty_to_value_string(actual);
1759 let inner_id = kind.did();
1760 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1761 pick.autoref_or_ptr_adjustment
1768 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1769 err.help("use `with` or `try_with` to access thread local storage");
1770 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1772 "if this `{name}` has been initialized, \
1773 use one of the `assume_init` methods to access the inner value"
1775 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1776 let (suggestion, borrow_kind, panic_if) = match mutable {
1777 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1778 Some(Mutability::Mut) => {
1779 (".borrow_mut()", "mutably borrow", "any borrows exist")
1783 err.span_suggestion_verbose(
1784 expr.span.shrink_to_hi(),
1786 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1787 panicking if {panic_if}"
1790 Applicability::MaybeIncorrect,
1792 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1793 err.span_suggestion_verbose(
1794 expr.span.shrink_to_hi(),
1796 "use `.lock().unwrap()` to borrow the `{ty}`, \
1797 blocking the current thread until it can be acquired"
1800 Applicability::MaybeIncorrect,
1802 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1803 let (suggestion, borrow_kind) = match mutable {
1804 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1805 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1808 err.span_suggestion_verbose(
1809 expr.span.shrink_to_hi(),
1811 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1812 blocking the current thread until it can be acquired"
1815 Applicability::MaybeIncorrect,
1822 tcx.def_span(pick.item.def_id),
1823 &format!("the method `{item_name}` exists on the type `{ty}`"),
1829 pub(crate) fn note_unmet_impls_on_type(
1831 err: &mut Diagnostic,
1832 errors: Vec<FulfillmentError<'tcx>>,
1834 let all_local_types_needing_impls =
1835 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1836 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1837 ty::Adt(def, _) => def.did().is_local(),
1842 let mut preds: Vec<_> = errors
1844 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1845 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1849 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1852 .filter_map(|pred| match pred.self_ty().kind() {
1853 ty::Adt(def, _) => Some(def.did()),
1856 .collect::<FxHashSet<_>>();
1857 let mut spans: MultiSpan = def_ids
1859 .filter_map(|def_id| {
1860 let span = self.tcx.def_span(*def_id);
1861 if span.is_dummy() { None } else { Some(span) }
1863 .collect::<Vec<_>>()
1866 for pred in &preds {
1867 match pred.self_ty().kind() {
1868 ty::Adt(def, _) if def.did().is_local() => {
1869 spans.push_span_label(
1870 self.tcx.def_span(def.did()),
1871 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1878 if all_local_types_needing_impls && spans.primary_span().is_some() {
1879 let msg = if preds.len() == 1 {
1881 "an implementation of `{}` might be missing for `{}`",
1882 preds[0].trait_ref.print_only_trait_path(),
1887 "the following type{} would have to `impl` {} required trait{} for this \
1888 operation to be valid",
1889 pluralize!(def_ids.len()),
1890 if def_ids.len() == 1 { "its" } else { "their" },
1891 pluralize!(preds.len()),
1894 err.span_note(spans, &msg);
1897 let preds: Vec<_> = errors
1899 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1901 self.suggest_derive(err, &preds);
1904 pub fn suggest_derive(
1906 err: &mut Diagnostic,
1907 unsatisfied_predicates: &[(
1908 ty::Predicate<'tcx>,
1909 Option<ty::Predicate<'tcx>>,
1910 Option<ObligationCause<'tcx>>,
1913 let mut derives = Vec::<(String, Span, Symbol)>::new();
1914 let mut traits = Vec::new();
1915 for (pred, _, _) in unsatisfied_predicates {
1916 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1917 let adt = match trait_pred.self_ty().ty_adt_def() {
1918 Some(adt) if adt.did().is_local() => adt,
1921 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1922 let can_derive = match diagnostic_name {
1923 sym::Default => !adt.is_enum(),
1931 | sym::Debug => true,
1935 let self_name = trait_pred.self_ty().to_string();
1936 let self_span = self.tcx.def_span(adt.did());
1937 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1938 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1940 if let Some(parent_diagnostic_name) =
1941 self.tcx.get_diagnostic_name(super_trait.def_id())
1946 parent_diagnostic_name,
1951 derives.push((self_name, self_span, diagnostic_name));
1953 traits.push(trait_pred.def_id());
1956 traits.push(trait_pred.def_id());
1965 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1966 for (self_name, self_span, trait_name) in derives.into_iter() {
1967 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1969 if last_self_name == &self_name {
1970 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1974 derives_grouped.push((self_name, self_span, trait_name.to_string()));
1977 let len = traits.len();
1980 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
1981 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
1982 for (i, &did) in traits.iter().enumerate().skip(1) {
1984 names.push_str(", ");
1987 names.push_str(" and ");
1990 names.push_str(&self.tcx.def_path_str(did));
1995 &format!("the trait{} {} must be implemented", pluralize!(len), names),
1999 for (self_name, self_span, traits) in &derives_grouped {
2000 err.span_suggestion_verbose(
2001 self_span.shrink_to_lo(),
2002 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
2003 format!("#[derive({})]\n", traits),
2004 Applicability::MaybeIncorrect,
2009 fn check_for_deref_method(
2011 err: &mut Diagnostic,
2012 self_source: SelfSource<'tcx>,
2016 let SelfSource::QPath(ty) = self_source else { return; };
2017 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
2018 if let Ok(pick) = self.probe_for_name(
2024 ProbeScope::TraitsInScope,
2026 if deref_ty.is_suggestable(self.tcx, true)
2027 // If this method receives `&self`, then the provided
2028 // argument _should_ coerce, so it's valid to suggest
2029 // just changing the path.
2030 && pick.item.fn_has_self_parameter
2031 && let Some(self_ty) =
2032 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
2035 let suggested_path = match deref_ty.kind() {
2043 | ty::Alias(ty::Projection, _)
2044 | ty::Param(_) => format!("{deref_ty}"),
2045 // we need to test something like <&[_]>::len or <(&[u32])>::len
2046 // and Vec::function();
2047 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2048 // but for Adt type like Vec::function()
2049 // we would suggest <[_]>::function();
2050 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
2051 _ => format!("<{deref_ty}>"),
2053 err.span_suggestion_verbose(
2055 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2057 Applicability::MaybeIncorrect,
2062 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2070 /// Print out the type for use in value namespace.
2071 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2073 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2074 _ => self.ty_to_string(ty),
2078 fn suggest_await_before_method(
2080 err: &mut Diagnostic,
2083 call: &hir::Expr<'_>,
2086 let output_ty = match self.get_impl_future_output_ty(ty) {
2087 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2090 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
2091 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2093 err.span_suggestion_verbose(
2094 span.shrink_to_lo(),
2095 "consider `await`ing on the `Future` and calling the method on its `Output`",
2097 Applicability::MaybeIncorrect,
2102 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2103 let parent_map = self.tcx.visible_parent_map(());
2105 // Separate out candidates that must be imported with a glob, because they are named `_`
2106 // and cannot be referred with their identifier.
2107 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2108 if let Some(parent_did) = parent_map.get(trait_did) {
2109 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2110 if *parent_did != self.tcx.parent(*trait_did)
2113 .module_children(*parent_did)
2115 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2116 .all(|child| child.ident.name == kw::Underscore)
2125 let module_did = self.tcx.parent_module(self.body_id);
2126 let (module, _, _) = self.tcx.hir().get_module(module_did);
2127 let span = module.spans.inject_use_span;
2129 let path_strings = candidates.iter().map(|trait_did| {
2130 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2133 let glob_path_strings = globs.iter().map(|trait_did| {
2134 let parent_did = parent_map.get(trait_did).unwrap();
2136 "use {}::*; // trait {}\n",
2137 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2138 self.tcx.item_name(*trait_did),
2142 err.span_suggestions(
2145 path_strings.chain(glob_path_strings),
2146 Applicability::MaybeIncorrect,
2150 fn suggest_valid_traits(
2152 err: &mut Diagnostic,
2153 valid_out_of_scope_traits: Vec<DefId>,
2155 if !valid_out_of_scope_traits.is_empty() {
2156 let mut candidates = valid_out_of_scope_traits;
2160 // `TryFrom` and `FromIterator` have no methods
2161 let edition_fix = candidates
2163 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2166 err.help("items from traits can only be used if the trait is in scope");
2168 "the following {traits_are} implemented but not in scope; \
2169 perhaps add a `use` for {one_of_them}:",
2170 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2171 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2174 self.suggest_use_candidates(err, msg, candidates);
2175 if let Some(did) = edition_fix {
2177 "'{}' is included in the prelude starting in Edition 2021",
2178 with_crate_prefix!(self.tcx.def_path_str(did))
2188 fn suggest_traits_to_import(
2190 err: &mut Diagnostic,
2194 inputs_len: Option<usize>,
2195 source: SelfSource<'tcx>,
2196 valid_out_of_scope_traits: Vec<DefId>,
2197 unsatisfied_predicates: &[(
2198 ty::Predicate<'tcx>,
2199 Option<ty::Predicate<'tcx>>,
2200 Option<ObligationCause<'tcx>>,
2202 static_candidates: &[CandidateSource],
2203 unsatisfied_bounds: bool,
2205 let mut alt_rcvr_sugg = false;
2206 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2208 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2209 span, item_name, rcvr_ty, rcvr
2212 self.tcx.lang_items().clone_trait(),
2213 self.tcx.lang_items().deref_trait(),
2214 self.tcx.lang_items().deref_mut_trait(),
2215 self.tcx.lang_items().drop_trait(),
2216 self.tcx.get_diagnostic_item(sym::AsRef),
2218 // Try alternative arbitrary self types that could fulfill this call.
2219 // FIXME: probe for all types that *could* be arbitrary self-types, not
2221 for (rcvr_ty, post) in &[
2223 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2224 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2226 match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
2228 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2229 // We point at the method, but we just skip the rest of the check for arbitrary
2230 // self types and rely on the suggestion to `use` the trait from
2231 // `suggest_valid_traits`.
2232 let did = Some(pick.item.container_id(self.tcx));
2233 let skip = skippable.contains(&did);
2234 if pick.autoderefs == 0 && !skip {
2236 pick.item.ident(self.tcx).span,
2237 &format!("the method is available for `{}` here", rcvr_ty),
2242 Err(MethodError::Ambiguity(_)) => {
2243 // If the method is defined (but ambiguous) for the receiver we have, it is also
2244 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2245 // the receiver, then it might disambiguate this method, but I think these
2246 // suggestions are generally misleading (see #94218).
2252 for (rcvr_ty, pre) in &[
2253 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2254 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2255 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2256 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2258 if let Some(new_rcvr_t) = *rcvr_ty
2259 && let Ok(pick) = self.lookup_probe(
2263 ProbeScope::AllTraits,
2266 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2267 let did = Some(pick.item.container_id(self.tcx));
2268 // We don't want to suggest a container type when the missing
2269 // method is `.clone()` or `.deref()` otherwise we'd suggest
2270 // `Arc::new(foo).clone()`, which is far from what the user wants.
2271 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2272 // implement the `AsRef` trait.
2273 let skip = skippable.contains(&did)
2274 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2275 || 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);
2276 // Make sure the method is defined for the *actual* receiver: we don't
2277 // want to treat `Box<Self>` as a receiver if it only works because of
2278 // an autoderef to `&self`
2279 if pick.autoderefs == 0 && !skip {
2281 pick.item.ident(self.tcx).span,
2282 &format!("the method is available for `{}` here", new_rcvr_t),
2284 err.multipart_suggestion(
2285 "consider wrapping the receiver expression with the \
2288 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2289 (rcvr.span.shrink_to_hi(), ")".to_string()),
2291 Applicability::MaybeIncorrect,
2293 // We don't care about the other suggestions.
2294 alt_rcvr_sugg = true;
2300 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2304 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2306 let mut arbitrary_rcvr = vec![];
2307 // There are no traits implemented, so lets suggest some traits to
2308 // implement, by finding ones that have the item name, and are
2309 // legal to implement.
2310 let mut candidates = all_traits(self.tcx)
2312 // Don't issue suggestions for unstable traits since they're
2313 // unlikely to be implementable anyway
2314 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2315 Some(attr) => attr.level.is_stable(),
2319 // Static candidates are already implemented, and known not to work
2320 // Do not suggest them again
2321 static_candidates.iter().all(|sc| match *sc {
2322 CandidateSource::Trait(def_id) => def_id != info.def_id,
2323 CandidateSource::Impl(def_id) => {
2324 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2329 // We approximate the coherence rules to only suggest
2330 // traits that are legal to implement by requiring that
2331 // either the type or trait is local. Multi-dispatch means
2332 // this isn't perfect (that is, there are cases when
2333 // implementing a trait would be legal but is rejected
2335 unsatisfied_predicates.iter().all(|(p, _, _)| {
2336 match p.kind().skip_binder() {
2337 // Hide traits if they are present in predicates as they can be fixed without
2338 // having to implement them.
2339 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2340 t.def_id() == info.def_id
2342 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2343 p.projection_ty.def_id == info.def_id
2347 }) && (type_is_local || info.def_id.is_local())
2348 && !self.tcx.trait_is_auto(info.def_id)
2350 .associated_value(info.def_id, item_name)
2352 if let ty::AssocKind::Fn = item.kind {
2356 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2357 if let Some(hir::Node::TraitItem(hir::TraitItem {
2358 kind: hir::TraitItemKind::Fn(fn_sig, method),
2360 })) = id.map(|id| self.tcx.hir().get(id))
2362 let self_first_arg = match method {
2363 hir::TraitFn::Required([ident, ..]) => {
2364 ident.name == kw::SelfLower
2366 hir::TraitFn::Provided(body_id) => {
2367 self.tcx.hir().body(*body_id).params.first().map_or(
2372 hir::PatKind::Binding(_, _, ident, _)
2373 if ident.name == kw::SelfLower
2381 if !fn_sig.decl.implicit_self.has_implicit_self()
2384 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2385 arbitrary_rcvr.push(ty.span);
2391 // We only want to suggest public or local traits (#45781).
2392 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2396 .collect::<Vec<_>>();
2397 for span in &arbitrary_rcvr {
2400 "the method might not be found because of this arbitrary self type",
2407 if !candidates.is_empty() {
2408 // Sort from most relevant to least relevant.
2409 candidates.sort_by(|a, b| a.cmp(b).reverse());
2412 let param_type = match rcvr_ty.kind() {
2413 ty::Param(param) => Some(param),
2414 ty::Ref(_, ty, _) => match ty.kind() {
2415 ty::Param(param) => Some(param),
2420 err.help(if param_type.is_some() {
2421 "items from traits can only be used if the type parameter is bounded by the trait"
2423 "items from traits can only be used if the trait is implemented and in scope"
2425 let candidates_len = candidates.len();
2426 let message = |action| {
2428 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2431 if candidates_len == 1 { "trait defines" } else { "traits define" },
2433 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2437 // Obtain the span for `param` and use it for a structured suggestion.
2438 if let Some(param) = param_type {
2439 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2440 let type_param = generics.type_param(param, self.tcx);
2441 let hir = self.tcx.hir();
2442 if let Some(def_id) = type_param.def_id.as_local() {
2443 let id = hir.local_def_id_to_hir_id(def_id);
2444 // Get the `hir::Param` to verify whether it already has any bounds.
2445 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2446 // instead we suggest `T: Foo + Bar` in that case.
2448 Node::GenericParam(param) => {
2454 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2455 let (sp, mut introducer) = if let Some(span) =
2456 ast_generics.bounds_span_for_suggestions(def_id)
2458 (span, Introducer::Plus)
2459 } else if let Some(colon_span) = param.colon_span {
2460 (colon_span.shrink_to_hi(), Introducer::Nothing)
2462 (param.span.shrink_to_hi(), Introducer::Colon)
2466 hir::GenericParamKind::Type { synthetic: true, .. },
2468 introducer = Introducer::Plus
2470 let trait_def_ids: FxHashSet<DefId> = ast_generics
2471 .bounds_for_param(def_id)
2472 .flat_map(|bp| bp.bounds.iter())
2473 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2475 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2476 err.span_suggestions(
2479 "restrict type parameter `{}` with",
2482 candidates.iter().map(|t| {
2486 Introducer::Plus => " +",
2487 Introducer::Colon => ":",
2488 Introducer::Nothing => "",
2490 self.tcx.def_path_str(t.def_id),
2493 Applicability::MaybeIncorrect,
2498 Node::Item(hir::Item {
2499 kind: hir::ItemKind::Trait(.., bounds, _),
2503 let (sp, sep, article) = if bounds.is_empty() {
2504 (ident.span.shrink_to_hi(), ":", "a")
2506 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2508 err.span_suggestions(
2510 &message(format!("add {} supertrait for", article)),
2511 candidates.iter().map(|t| {
2512 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2514 Applicability::MaybeIncorrect,
2523 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2524 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2525 // cases where a positive bound implies a negative impl.
2526 (candidates, Vec::new())
2527 } else if let Some(simp_rcvr_ty) =
2528 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2530 let mut potential_candidates = Vec::new();
2531 let mut explicitly_negative = Vec::new();
2532 for candidate in candidates {
2533 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2536 .all_impls(candidate.def_id)
2538 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2541 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2543 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2544 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2547 explicitly_negative.push(candidate);
2549 potential_candidates.push(candidate);
2552 (potential_candidates, explicitly_negative)
2554 // We don't know enough about `recv_ty` to make proper suggestions.
2555 (candidates, Vec::new())
2558 let action = if let Some(param) = param_type {
2559 format!("restrict type parameter `{}` with", param)
2561 // FIXME: it might only need to be imported into scope, not implemented.
2562 "implement".to_string()
2564 match &potential_candidates[..] {
2566 [trait_info] if trait_info.def_id.is_local() => {
2568 self.tcx.def_span(trait_info.def_id),
2570 "`{}` defines an item `{}`, perhaps you need to {} it",
2571 self.tcx.def_path_str(trait_info.def_id),
2578 let mut msg = message(action);
2579 for (i, trait_info) in trait_infos.iter().enumerate() {
2580 msg.push_str(&format!(
2581 "\ncandidate #{}: `{}`",
2583 self.tcx.def_path_str(trait_info.def_id),
2589 match &explicitly_negative[..] {
2593 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2594 self.tcx.def_path_str(trait_info.def_id),
2600 let mut msg = format!(
2601 "the following traits define an item `{}`, but are explicitly unimplemented:",
2604 for trait_info in trait_infos {
2605 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2613 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2614 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2615 pub(crate) fn suggest_else_fn_with_closure(
2617 err: &mut Diagnostic,
2618 expr: &hir::Expr<'_>,
2622 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2623 else { return false; };
2625 if !self.can_coerce(output, expected) {
2629 let parent = self.tcx.hir().parent_id(expr.hir_id);
2630 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2631 let hir::ExprKind::MethodCall(
2632 hir::PathSegment { ident: method_name, .. },
2636 ) = call_expr.kind &&
2637 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2638 let new_name = Ident {
2639 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2640 span: method_name.span,
2642 let probe = self.lookup_probe(
2646 ProbeScope::TraitsInScope,
2649 // check the method arguments number
2650 if let Ok(pick) = probe &&
2651 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2652 let fn_args = fn_sig.skip_binder().inputs() &&
2653 fn_args.len() == args.len() + 1 {
2654 err.span_suggestion_verbose(
2655 method_name.span.shrink_to_hi(),
2656 &format!("try calling `{}` instead", new_name.name.as_str()),
2658 Applicability::MaybeIncorrect,
2666 /// Checks whether there is a local type somewhere in the chain of
2667 /// autoderefs of `rcvr_ty`.
2668 fn type_derefs_to_local(
2672 source: SelfSource<'tcx>,
2674 fn is_local(ty: Ty<'_>) -> bool {
2676 ty::Adt(def, _) => def.did().is_local(),
2677 ty::Foreign(did) => did.is_local(),
2678 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2679 ty::Param(_) => true,
2681 // Everything else (primitive types, etc.) is effectively
2682 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2683 // the noise from these sort of types is usually just really
2684 // annoying, rather than any sort of help).
2689 // This occurs for UFCS desugaring of `T::method`, where there is no
2690 // receiver expression for the method call, and thus no autoderef.
2691 if let SelfSource::QPath(_) = source {
2692 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2695 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2699 #[derive(Copy, Clone, Debug)]
2700 pub enum SelfSource<'a> {
2701 QPath(&'a hir::Ty<'a>),
2702 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2705 #[derive(Copy, Clone)]
2706 pub struct TraitInfo {
2710 impl PartialEq for TraitInfo {
2711 fn eq(&self, other: &TraitInfo) -> bool {
2712 self.cmp(other) == Ordering::Equal
2715 impl Eq for TraitInfo {}
2716 impl PartialOrd for TraitInfo {
2717 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2718 Some(self.cmp(other))
2721 impl Ord for TraitInfo {
2722 fn cmp(&self, other: &TraitInfo) -> Ordering {
2723 // Local crates are more important than remote ones (local:
2724 // `cnum == 0`), and otherwise we throw in the defid for totality.
2726 let lhs = (other.def_id.krate, other.def_id);
2727 let rhs = (self.def_id.krate, self.def_id);
2732 /// Retrieves all traits in this crate and any dependent crates,
2733 /// and wraps them into `TraitInfo` for custom sorting.
2734 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2735 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2738 fn print_disambiguation_help<'tcx>(
2740 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2741 err: &mut Diagnostic,
2744 kind: ty::AssocKind,
2747 candidate: Option<usize>,
2748 source_map: &source_map::SourceMap,
2749 fn_has_self_parameter: bool,
2751 let mut applicability = Applicability::MachineApplicable;
2752 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2755 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2756 std::iter::once(receiver)
2758 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2759 applicability = Applicability::HasPlaceholders;
2762 .collect::<Vec<_>>()
2765 let trait_name = if !fn_has_self_parameter {
2766 format!("<{} as {}>", rcvr_ty, trait_name)
2770 (span, format!("{}::{}{}", trait_name, item_name, args))
2772 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2774 err.span_suggestion_verbose(
2777 "disambiguate the {} for {}",
2778 kind.as_def_kind().descr(def_id),
2779 if let Some(candidate) = candidate {
2780 format!("candidate #{}", candidate)
2782 "the candidate".to_string()