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 if let Some(g) = kind.generics() {
511 g.tail_span_for_predicate_suggestion(),
512 g.add_where_or_trailing_comma(),
516 .or_insert_with(FxHashSet::default)
517 .insert(obligation.to_owned());
522 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
524 "doesn't satisfy `{}`",
525 if obligation.len() > 50 { quiet } else { obligation }
527 match &self_ty.kind() {
528 // Point at the type that couldn't satisfy the bound.
529 ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
530 // Point at the trait object that couldn't satisfy the bound.
531 ty::Dynamic(preds, _, _) => {
532 for pred in preds.iter() {
533 match pred.skip_binder() {
534 ty::ExistentialPredicate::Trait(tr) => {
535 bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
537 ty::ExistentialPredicate::Projection(_)
538 | ty::ExistentialPredicate::AutoTrait(_) => {}
542 // Point at the closure that couldn't satisfy the bound.
543 ty::Closure(def_id, _) => bound_spans
544 .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
548 let mut format_pred = |pred: ty::Predicate<'tcx>| {
549 let bound_predicate = pred.kind();
550 match bound_predicate.skip_binder() {
551 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
552 let pred = bound_predicate.rebind(pred);
553 // `<Foo as Iterator>::Item = String`.
554 let projection_ty = pred.skip_binder().projection_ty;
556 let substs_with_infer_self = tcx.mk_substs(
557 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
558 .chain(projection_ty.substs.iter().skip(1)),
561 let quiet_projection_ty =
562 tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
564 let term = pred.skip_binder().term;
566 let obligation = format!("{} = {}", projection_ty, term);
567 let quiet = with_forced_trimmed_paths!(format!(
569 quiet_projection_ty, term
572 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
573 Some((obligation, projection_ty.self_ty()))
575 ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
576 let p = poly_trait_ref.trait_ref;
577 let self_ty = p.self_ty();
578 let path = p.print_only_trait_path();
579 let obligation = format!("{}: {}", self_ty, path);
580 let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
581 bound_span_label(self_ty, &obligation, &quiet);
582 Some((obligation, self_ty))
588 // Find all the requirements that come from a local `impl` block.
589 let mut skip_list: FxHashSet<_> = Default::default();
590 let mut spanned_predicates = FxHashMap::default();
591 for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates
593 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
594 .filter_map(|(p, parent, c)| match c.code() {
595 ObligationCauseCode::ImplDerivedObligation(data)
596 if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
598 Some((p, parent, data.impl_def_id, data))
603 match self.tcx.hir().get_if_local(impl_def_id) {
604 // Unmet obligation comes from a `derive` macro, point at it once to
605 // avoid multiple span labels pointing at the same place.
606 Some(Node::Item(hir::Item {
607 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
610 self_ty.span.ctxt().outer_expn_data().kind,
611 ExpnKind::Macro(MacroKind::Derive, _)
613 of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
614 Some(ExpnKind::Macro(MacroKind::Derive, _))
617 let span = self_ty.span.ctxt().outer_expn_data().call_site;
618 let entry = spanned_predicates.entry(span);
619 let entry = entry.or_insert_with(|| {
620 (FxHashSet::default(), FxHashSet::default(), Vec::new())
622 entry.0.insert(span);
625 "unsatisfied trait bound introduced in this `derive` macro",
631 // Unmet obligation coming from an `impl`.
632 Some(Node::Item(hir::Item {
633 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
638 unsatisfied_predicates.iter().any(|(pred, _, _)| {
639 match pred.kind().skip_binder() {
640 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
641 Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
642 && pred.polarity == ty::ImplPolarity::Positive
647 for param in generics.params {
648 if param.span == cause.span && sized_pred {
649 let (sp, sugg) = match param.colon_span {
650 Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
651 None => (param.span.shrink_to_hi(), ": ?Sized"),
653 err.span_suggestion_verbose(
655 "consider relaxing the type parameter's implicit `Sized` bound",
657 Applicability::MachineApplicable,
661 if let Some(pred) = parent_p {
662 // Done to add the "doesn't satisfy" `span_label`.
663 let _ = format_pred(*pred);
666 let entry = spanned_predicates.entry(self_ty.span);
667 let entry = entry.or_insert_with(|| {
668 (FxHashSet::default(), FxHashSet::default(), Vec::new())
671 if cause.span != *item_span {
672 entry.0.insert(cause.span);
673 entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
675 if let Some(trait_ref) = of_trait {
676 entry.0.insert(trait_ref.path.span);
678 entry.0.insert(self_ty.span);
680 if let Some(trait_ref) = of_trait {
681 entry.1.insert((trait_ref.path.span, ""));
683 entry.1.insert((self_ty.span, ""));
685 Some(Node::Item(hir::Item {
686 kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
690 tcx.sess.delay_span_bug(
692 "auto trait is invoked with no method error, but no error reported?",
695 Some(_) => unreachable!(),
699 let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
700 spanned_predicates.sort_by_key(|(span, _)| *span);
701 for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
702 let mut preds: Vec<_> = predicates
704 .filter_map(|pred| format_pred(**pred))
705 .map(|(p, _)| format!("`{}`", p))
709 let msg = if let [pred] = &preds[..] {
710 format!("trait bound {} was not satisfied", pred)
712 format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
714 let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
715 for (sp, label) in span_labels {
716 span.push_span_label(sp, label);
718 err.span_note(span, &msg);
719 unsatisfied_bounds = true;
722 // The requirements that didn't have an `impl` span to show.
723 let mut bound_list = unsatisfied_predicates
725 .filter_map(|(pred, parent_pred, _cause)| {
726 format_pred(*pred).map(|(p, self_ty)| {
727 collect_type_param_suggestions(self_ty, *pred, &p);
730 None => format!("`{}`", &p),
731 Some(parent_pred) => match format_pred(*parent_pred) {
732 None => format!("`{}`", &p),
733 Some((parent_p, _)) => {
734 collect_type_param_suggestions(self_ty, *parent_pred, &p);
735 format!("`{}`\nwhich is required by `{}`", p, parent_p)
743 .filter(|(_, pred)| !skip_list.contains(&pred))
746 .collect::<Vec<(usize, String)>>();
748 for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
749 restrict_type_params = true;
750 // #74886: Sort here so that the output is always the same.
751 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
753 err.span_suggestion_verbose(
756 "consider restricting the type parameter{s} to satisfy the \
758 s = pluralize!(obligations.len())
760 format!("{} {}", add_where_or_comma, obligations.join(", ")),
761 Applicability::MaybeIncorrect,
765 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
766 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
767 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
769 if !bound_list.is_empty() || !skip_list.is_empty() {
771 bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
772 let actual_prefix = rcvr_ty.prefix_string(self.tcx);
773 info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
774 let (primary_message, label) = if unimplemented_traits.len() == 1
775 && unimplemented_traits_only
780 .map(|(_, (trait_ref, obligation))| {
781 if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
786 let OnUnimplementedNote { message, label, .. } =
787 self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
794 let primary_message = primary_message.unwrap_or_else(|| {
796 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
797 but its trait bounds were not satisfied"
800 err.set_primary_message(&primary_message);
801 if let Some(label) = label {
802 custom_span_label = true;
803 err.span_label(span, label);
805 if !bound_list.is_empty() {
807 "the following trait bounds were not satisfied:\n{bound_list}"
810 self.suggest_derive(&mut err, &unsatisfied_predicates);
812 unsatisfied_bounds = true;
816 let label_span_not_found = |err: &mut Diagnostic| {
817 if unsatisfied_predicates.is_empty() {
818 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
819 let is_string_or_ref_str = match rcvr_ty.kind() {
820 ty::Ref(_, ty, _) => {
824 ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
827 ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
830 if is_string_or_ref_str && item_name.name == sym::iter {
831 err.span_suggestion_verbose(
833 "because of the in-memory representation of `&str`, to obtain \
834 an `Iterator` over each of its codepoint use method `chars`",
836 Applicability::MachineApplicable,
839 if let ty::Adt(adt, _) = rcvr_ty.kind() {
840 let mut inherent_impls_candidate = self
842 .inherent_impls(adt.did())
846 if let Some(assoc) = self.associated_value(*def_id, item_name) {
847 // Check for both mode is the same so we avoid suggesting
848 // incorrect associated item.
849 match (mode, assoc.fn_has_self_parameter, source) {
850 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
851 // We check that the suggest type is actually
852 // different from the received one
853 // So we avoid suggestion method with Box<Self>
855 self.tcx.at(span).type_of(*def_id) != rcvr_ty
856 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
858 (Mode::Path, false, _) => true,
865 .collect::<Vec<_>>();
866 if !inherent_impls_candidate.is_empty() {
867 inherent_impls_candidate.sort();
868 inherent_impls_candidate.dedup();
870 // number of type to shows at most.
871 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
872 let type_candidates = inherent_impls_candidate
876 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
880 let additional_types = if inherent_impls_candidate.len() > limit {
881 format!("\nand {} more types", inherent_impls_candidate.len() - limit)
886 "the {item_kind} was found for\n{}{}",
887 type_candidates, additional_types
893 if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
896 format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
901 // If the method name is the name of a field with a function or closure type,
902 // give a helping note that it has to be called as `(x.f)(...)`.
903 if let SelfSource::MethodCall(expr) = source {
904 if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
905 && lev_candidate.is_none()
906 && !custom_span_label
908 label_span_not_found(&mut err);
910 } else if !custom_span_label {
911 label_span_not_found(&mut err);
914 // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
915 // can't be called due to `typeof(expr): Clone` not holding.
916 if unsatisfied_predicates.is_empty() {
917 self.suggest_calling_method_on_field(
923 expected.only_has_type(self),
927 self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
931 for (span, msg) in bound_spans.into_iter() {
932 err.span_label(span, &msg);
935 if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
937 self.suggest_traits_to_import(
942 args.map(|(_, args)| args.len() + 1),
944 no_match_data.out_of_scope_traits.clone(),
945 &unsatisfied_predicates,
948 expected.only_has_type(self),
952 // Don't emit a suggestion if we found an actual method
953 // that had unsatisfied trait bounds
954 if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
955 let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
956 if let Some(suggestion) = lev_distance::find_best_match_for_name(
957 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
963 "there is a variant with a similar name",
965 Applicability::MaybeIncorrect,
970 if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
971 let msg = "remove this method call";
972 let mut fallback_span = true;
973 if let SelfSource::MethodCall(expr) = source {
974 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
975 if let Some(span) = call_expr.span.trim_start(expr.span) {
976 err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
977 fallback_span = false;
981 err.span_label(span, msg);
983 } else if let Some(lev_candidate) = lev_candidate {
984 // Don't emit a suggestion if we found an actual method
985 // that had unsatisfied trait bounds
986 if unsatisfied_predicates.is_empty() {
987 let def_kind = lev_candidate.kind.as_def_kind();
988 // Methods are defined within the context of a struct and their first parameter is always self,
989 // which represents the instance of the struct the method is being called on
990 // Associated functions don’t take self as a parameter and
991 // they are not methods because they don’t have an instance of the struct to work with.
992 if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
995 "there is a method with a similar name",
997 Applicability::MaybeIncorrect,
1000 err.span_suggestion(
1003 "there is {} {} with a similar name",
1005 def_kind.descr(lev_candidate.def_id),
1008 Applicability::MaybeIncorrect,
1014 self.check_for_deref_method(&mut err, source, rcvr_ty, item_name, expected);
1018 fn note_candidates_on_method_error(
1022 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1024 err: &mut Diagnostic,
1025 sources: &mut Vec<CandidateSource>,
1026 sugg_span: Option<Span>,
1030 // Dynamic limit to avoid hiding just one candidate, which is silly.
1031 let limit = if sources.len() == 5 { 5 } else { 4 };
1033 for (idx, source) in sources.iter().take(limit).enumerate() {
1035 CandidateSource::Impl(impl_did) => {
1036 // Provide the best span we can. Use the item, if local to crate, else
1037 // the impl, if local to crate (item may be defaulted), else nothing.
1038 let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
1039 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
1040 self.associated_value(impl_trait_ref.def_id, item_name)
1045 let note_span = if item.def_id.is_local() {
1046 Some(self.tcx.def_span(item.def_id))
1047 } else if impl_did.is_local() {
1048 Some(self.tcx.def_span(impl_did))
1053 let impl_ty = self.tcx.at(span).type_of(impl_did);
1055 let insertion = match self.tcx.impl_trait_ref(impl_did) {
1056 None => String::new(),
1057 Some(trait_ref) => {
1058 format!(" of the trait `{}`", self.tcx.def_path_str(trait_ref.def_id))
1062 let (note_str, idx) = if sources.len() > 1 {
1065 "candidate #{} is defined in an impl{} for the type `{}`",
1075 "the candidate is defined in an impl{} for the type `{}`",
1081 if let Some(note_span) = note_span {
1082 // We have a span pointing to the method. Show note with snippet.
1083 err.span_note(note_span, ¬e_str);
1085 err.note(¬e_str);
1087 if let Some(sugg_span) = sugg_span
1088 && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
1089 let path = self.tcx.def_path_str(trait_ref.def_id);
1091 let ty = match item.kind {
1092 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
1093 ty::AssocKind::Fn => self
1095 .fn_sig(item.def_id)
1099 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
1101 .unwrap_or(rcvr_ty),
1103 print_disambiguation_help(
1113 self.tcx.sess.source_map(),
1114 item.fn_has_self_parameter,
1118 CandidateSource::Trait(trait_did) => {
1119 let Some(item) = self.associated_value(trait_did, item_name) else { continue };
1120 let item_span = self.tcx.def_span(item.def_id);
1121 let idx = if sources.len() > 1 {
1123 "candidate #{} is defined in the trait `{}`",
1125 self.tcx.def_path_str(trait_did)
1127 err.span_note(item_span, msg);
1131 "the candidate is defined in the trait `{}`",
1132 self.tcx.def_path_str(trait_did)
1134 err.span_note(item_span, msg);
1137 if let Some(sugg_span) = sugg_span {
1138 let path = self.tcx.def_path_str(trait_did);
1139 print_disambiguation_help(
1149 self.tcx.sess.source_map(),
1150 item.fn_has_self_parameter,
1156 if sources.len() > limit {
1157 err.note(&format!("and {} others", sources.len() - limit));
1161 /// Suggest calling `Ty::method` if `.method()` isn't found because the method
1162 /// doesn't take a `self` receiver.
1163 fn suggest_associated_call_syntax(
1165 err: &mut Diagnostic,
1166 static_candidates: &Vec<CandidateSource>,
1168 source: SelfSource<'tcx>,
1170 args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
1173 let mut has_unsuggestable_args = false;
1174 let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
1175 // When the "method" is resolved through dereferencing, we really want the
1176 // original type that has the associated function for accurate suggestions.
1178 let impl_ty = self.tcx.type_of(*impl_did);
1179 let target_ty = self
1180 .autoderef(sugg_span, rcvr_ty)
1181 .find(|(rcvr_ty, _)| {
1182 DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
1183 .types_may_unify(*rcvr_ty, impl_ty)
1185 .map_or(impl_ty, |(ty, _)| ty)
1187 if let ty::Adt(def, substs) = target_ty.kind() {
1188 // If there are any inferred arguments, (`{integer}`), we should replace
1189 // them with underscores to allow the compiler to infer them
1190 let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
1191 if !arg.is_suggestable(self.tcx, true) {
1192 has_unsuggestable_args = true;
1193 match arg.unpack() {
1194 GenericArgKind::Lifetime(_) => self
1195 .next_region_var(RegionVariableOrigin::MiscVariable(
1196 rustc_span::DUMMY_SP,
1199 GenericArgKind::Type(_) => self
1200 .next_ty_var(TypeVariableOrigin {
1201 span: rustc_span::DUMMY_SP,
1202 kind: TypeVariableOriginKind::MiscVariable,
1205 GenericArgKind::Const(arg) => self
1208 ConstVariableOrigin {
1209 span: rustc_span::DUMMY_SP,
1210 kind: ConstVariableOriginKind::MiscVariable,
1220 self.tcx.value_path_str_with_substs(def.did(), infer_substs)
1222 self.ty_to_value_string(target_ty)
1225 self.ty_to_value_string(rcvr_ty.peel_refs())
1227 if let SelfSource::MethodCall(_) = source {
1228 let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
1229 && let Some(assoc) = self.associated_value(*impl_did, item_name)
1230 && assoc.kind == ty::AssocKind::Fn
1232 let sig = self.tcx.fn_sig(assoc.def_id);
1233 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
1236 Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
1241 let mut applicability = Applicability::MachineApplicable;
1242 let args = if let Some((receiver, args)) = args {
1243 // The first arg is the same kind as the receiver
1244 let explicit_args = if first_arg.is_some() {
1245 std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
1247 // There is no `Self` kind to infer the arguments from
1248 if has_unsuggestable_args {
1249 applicability = Applicability::HasPlaceholders;
1251 args.iter().collect()
1255 first_arg.unwrap_or(""),
1262 .span_to_snippet(arg.span)
1263 .unwrap_or_else(|_| {
1264 applicability = Applicability::HasPlaceholders;
1267 .collect::<Vec<_>>()
1271 applicability = Applicability::HasPlaceholders;
1274 err.span_suggestion(
1276 "use associated function syntax instead",
1277 format!("{}::{}{}", ty_str, item_name, args),
1281 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
1285 /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
1286 /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
1287 fn suggest_calling_field_as_fn(
1291 expr: &hir::Expr<'_>,
1293 err: &mut Diagnostic,
1296 let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
1297 ty::Adt(def, substs) if !def.is_enum() => {
1298 let variant = &def.non_enum_variant();
1299 tcx.find_field_index(item_name, variant).map(|index| {
1300 let field = &variant.fields[index];
1301 let field_ty = field.ty(tcx, substs);
1307 if let Some((field, field_ty)) = field_receiver {
1308 let scope = tcx.parent_module(self.body_id);
1309 let is_accessible = field.vis.is_accessible_from(scope, tcx);
1312 if self.is_fn_ty(field_ty, span) {
1313 let expr_span = expr.span.to(item_name.span);
1314 err.multipart_suggestion(
1316 "to call the function stored in `{}`, \
1317 surround the field access with parentheses",
1321 (expr_span.shrink_to_lo(), '('.to_string()),
1322 (expr_span.shrink_to_hi(), ')'.to_string()),
1324 Applicability::MachineApplicable,
1327 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1329 if let Some(span) = call_expr.span.trim_start(item_name.span) {
1330 err.span_suggestion(
1332 "remove the arguments",
1334 Applicability::MaybeIncorrect,
1340 let field_kind = if is_accessible { "field" } else { "private field" };
1341 err.span_label(item_name.span, format!("{}, not a method", field_kind));
1347 /// Suggest possible range with adding parentheses, for example:
1348 /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
1349 fn suggest_wrapping_range_with_parens(
1353 source: SelfSource<'tcx>,
1358 if let SelfSource::MethodCall(expr) = source {
1359 for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1360 if let Node::Expr(parent_expr) = parent {
1361 let lang_item = match parent_expr.kind {
1362 ExprKind::Struct(ref qpath, _, _) => match **qpath {
1363 QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1364 QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1365 QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1366 Some(LangItem::RangeToInclusive)
1370 ExprKind::Call(ref func, _) => match func.kind {
1371 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1372 ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1373 Some(LangItem::RangeInclusiveStruct)
1380 if lang_item.is_none() {
1384 let span_included = match parent_expr.kind {
1385 hir::ExprKind::Struct(_, eps, _) => {
1386 eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1388 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1389 hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1397 let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1399 self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1401 let pick = self.lookup_probe_for_diagnostic(
1405 ProbeScope::AllTraits,
1409 let range_span = parent_expr.span.with_hi(expr.span.hi());
1410 tcx.sess.emit_err(errors::MissingParentheseInRange {
1412 ty_str: ty_str.to_string(),
1413 method_name: item_name.as_str().to_string(),
1414 add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1415 func_name: item_name.name.as_str().to_string(),
1416 left: range_span.shrink_to_lo(),
1417 right: range_span.shrink_to_hi(),
1428 fn suggest_constraining_numerical_ty(
1432 source: SelfSource<'_>,
1438 let found_candidate = all_traits(self.tcx)
1440 .any(|info| self.associated_value(info.def_id, item_name).is_some());
1441 let found_assoc = |ty: Ty<'tcx>| {
1442 simplify_type(tcx, ty, TreatParams::AsInfer)
1444 tcx.incoherent_impls(simp)
1446 .find_map(|&id| self.associated_value(id, item_name))
1450 let found_candidate = found_candidate
1451 || found_assoc(tcx.types.i8)
1452 || found_assoc(tcx.types.i16)
1453 || found_assoc(tcx.types.i32)
1454 || found_assoc(tcx.types.i64)
1455 || found_assoc(tcx.types.i128)
1456 || found_assoc(tcx.types.u8)
1457 || found_assoc(tcx.types.u16)
1458 || found_assoc(tcx.types.u32)
1459 || found_assoc(tcx.types.u64)
1460 || found_assoc(tcx.types.u128)
1461 || found_assoc(tcx.types.f32)
1462 || found_assoc(tcx.types.f32);
1464 && actual.is_numeric()
1465 && !actual.has_concrete_skeleton()
1466 && let SelfSource::MethodCall(expr) = source
1468 let mut err = struct_span_err!(
1472 "can't call {} `{}` on ambiguous numeric type `{}`",
1477 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
1479 ExprKind::Lit(ref lit) => {
1484 .span_to_snippet(lit.span)
1485 .unwrap_or_else(|_| "<numeric literal>".to_owned());
1487 // If this is a floating point literal that ends with '.',
1488 // get rid of it to stop this from becoming a member access.
1489 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
1490 err.span_suggestion(
1493 "you must specify a concrete type for this numeric value, \
1497 format!("{snippet}_{concrete_type}"),
1498 Applicability::MaybeIncorrect,
1501 ExprKind::Path(QPath::Resolved(_, path)) => {
1503 if let hir::def::Res::Local(hir_id) = path.res {
1504 let span = tcx.hir().span(hir_id);
1505 let filename = tcx.sess.source_map().span_to_filename(span);
1508 self.tcx.hir().get_parent(hir_id);
1510 "you must specify a type for this binding, like `{}`",
1514 match (filename, parent_node) {
1517 Node::Local(hir::Local {
1518 source: hir::LocalSource::Normal,
1523 let type_span = ty.map(|ty| ty.span.with_lo(span.hi())).unwrap_or(span.shrink_to_hi());
1524 err.span_suggestion(
1525 // account for `let x: _ = 42;`
1529 format!(": {concrete_type}"),
1530 Applicability::MaybeIncorrect,
1534 err.span_label(span, msg);
1547 /// For code `rect::area(...)`,
1548 /// if `rect` is a local variable and `area` is a valid assoc method for it,
1549 /// we try to suggest `rect.area()`
1550 pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
1551 debug!("suggest_assoc_method_call segs: {:?}", segs);
1552 let [seg1, seg2] = segs else { return; };
1553 let Some(mut diag) =
1554 self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
1557 let map = self.infcx.tcx.hir();
1558 let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
1559 struct LetVisitor<'a> {
1560 result: Option<&'a hir::Expr<'a>>,
1564 // FIXME: This really should be taking scoping, etc into account.
1565 impl<'v> Visitor<'v> for LetVisitor<'v> {
1566 fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
1567 if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
1568 && let Binding(_, _, ident, ..) = pat.kind
1569 && ident.name == self.ident_name
1571 self.result = *init;
1573 hir::intravisit::walk_stmt(self, ex);
1578 let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
1579 visitor.visit_body(&body);
1581 let parent = self.tcx.hir().parent_id(seg1.hir_id);
1582 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
1583 && let Some(expr) = visitor.result
1584 && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
1586 let probe = self.lookup_probe_for_diagnostic(
1590 ProbeScope::TraitsInScope,
1594 let sm = self.infcx.tcx.sess.source_map();
1595 diag.span_suggestion_verbose(
1596 sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
1597 "you may have meant to call an instance method",
1599 Applicability::MaybeIncorrect,
1606 /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
1607 fn suggest_calling_method_on_field(
1609 err: &mut Diagnostic,
1610 source: SelfSource<'tcx>,
1614 return_type: Option<Ty<'tcx>>,
1616 if let SelfSource::MethodCall(expr) = source
1617 && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
1618 && let Some((fields, substs)) =
1619 self.get_field_candidates_considering_privacy(span, actual, mod_id)
1621 let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
1623 let lang_items = self.tcx.lang_items();
1624 let never_mention_traits = [
1625 lang_items.clone_trait(),
1626 lang_items.deref_trait(),
1627 lang_items.deref_mut_trait(),
1628 self.tcx.get_diagnostic_item(sym::AsRef),
1629 self.tcx.get_diagnostic_item(sym::AsMut),
1630 self.tcx.get_diagnostic_item(sym::Borrow),
1631 self.tcx.get_diagnostic_item(sym::BorrowMut),
1633 let candidate_fields: Vec<_> = fields
1634 .filter_map(|candidate_field| {
1635 self.check_for_nested_field_satisfying(
1638 self.lookup_probe_for_diagnostic(
1642 ProbeScope::TraitsInScope,
1645 .map_or(false, |pick| {
1646 !never_mention_traits
1649 .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
1661 .map(|id| id.name.to_ident_string())
1662 .collect::<Vec<String>>()
1667 let len = candidate_fields.len();
1669 err.span_suggestions(
1670 item_name.span.shrink_to_lo(),
1672 "{} of the expressions' fields {} a method of the same name",
1673 if len > 1 { "some" } else { "one" },
1674 if len > 1 { "have" } else { "has" },
1676 candidate_fields.iter().map(|path| format!("{path}.")),
1677 Applicability::MaybeIncorrect,
1683 fn check_for_inner_self(
1685 err: &mut Diagnostic,
1686 source: SelfSource<'tcx>,
1691 let SelfSource::MethodCall(expr) = source else { return; };
1692 let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
1694 let ty::Adt(kind, substs) = actual.kind() else { return; };
1695 match kind.adt_kind() {
1696 ty::AdtKind::Enum => {
1697 let matching_variants: Vec<_> = kind
1700 .flat_map(|variant| {
1701 let [field] = &variant.fields[..] else { return None; };
1702 let field_ty = field.ty(tcx, substs);
1704 // Skip `_`, since that'll just lead to ambiguity.
1705 if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1709 self.lookup_probe_for_diagnostic(
1713 ProbeScope::TraitsInScope,
1717 .map(|pick| (variant, field, pick))
1721 let ret_ty_matches = |diagnostic_item| {
1722 if let Some(ret_ty) = self
1725 .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1726 && let ty::Adt(kind, _) = ret_ty.kind()
1727 && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1735 match &matching_variants[..] {
1736 [(_, field, pick)] => {
1737 let self_ty = field.ty(tcx, substs);
1739 tcx.def_span(pick.item.def_id),
1740 &format!("the method `{item_name}` exists on the type `{self_ty}`"),
1742 let (article, kind, variant, question) =
1743 if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1744 ("a", "Result", "Err", ret_ty_matches(sym::Result))
1745 } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1746 ("an", "Option", "None", ret_ty_matches(sym::Option))
1751 err.span_suggestion_verbose(
1752 expr.span.shrink_to_hi(),
1754 "use the `?` operator to extract the `{self_ty}` value, propagating \
1755 {article} `{kind}::{variant}` value to the caller"
1758 Applicability::MachineApplicable,
1761 err.span_suggestion_verbose(
1762 expr.span.shrink_to_hi(),
1764 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1765 panicking if the value is {article} `{kind}::{variant}`"
1767 ".expect(\"REASON\")",
1768 Applicability::HasPlaceholders,
1772 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1776 // Target wrapper types - types that wrap or pretend to wrap another type,
1777 // perhaps this inner type is meant to be called?
1778 ty::AdtKind::Struct | ty::AdtKind::Union => {
1779 let [first] = ***substs else { return; };
1780 let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1781 let Ok(pick) = self.lookup_probe_for_diagnostic(
1785 ProbeScope::TraitsInScope,
1789 let name = self.ty_to_value_string(actual);
1790 let inner_id = kind.did();
1791 let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1792 pick.autoref_or_ptr_adjustment
1799 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1800 err.help("use `with` or `try_with` to access thread local storage");
1801 } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1803 "if this `{name}` has been initialized, \
1804 use one of the `assume_init` methods to access the inner value"
1806 } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1807 let (suggestion, borrow_kind, panic_if) = match mutable {
1808 Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1809 Some(Mutability::Mut) => {
1810 (".borrow_mut()", "mutably borrow", "any borrows exist")
1814 err.span_suggestion_verbose(
1815 expr.span.shrink_to_hi(),
1817 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1818 panicking if {panic_if}"
1821 Applicability::MaybeIncorrect,
1823 } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
1824 err.span_suggestion_verbose(
1825 expr.span.shrink_to_hi(),
1827 "use `.lock().unwrap()` to borrow the `{ty}`, \
1828 blocking the current thread until it can be acquired"
1831 Applicability::MaybeIncorrect,
1833 } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1834 let (suggestion, borrow_kind) = match mutable {
1835 Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1836 Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1839 err.span_suggestion_verbose(
1840 expr.span.shrink_to_hi(),
1842 "use `{suggestion}` to {borrow_kind} the `{ty}`, \
1843 blocking the current thread until it can be acquired"
1846 Applicability::MaybeIncorrect,
1853 tcx.def_span(pick.item.def_id),
1854 &format!("the method `{item_name}` exists on the type `{ty}`"),
1860 pub(crate) fn note_unmet_impls_on_type(
1862 err: &mut Diagnostic,
1863 errors: Vec<FulfillmentError<'tcx>>,
1865 let all_local_types_needing_impls =
1866 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1867 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => match pred.self_ty().kind() {
1868 ty::Adt(def, _) => def.did().is_local(),
1873 let mut preds: Vec<_> = errors
1875 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1876 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => Some(pred),
1880 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1883 .filter_map(|pred| match pred.self_ty().kind() {
1884 ty::Adt(def, _) => Some(def.did()),
1887 .collect::<FxHashSet<_>>();
1888 let mut spans: MultiSpan = def_ids
1890 .filter_map(|def_id| {
1891 let span = self.tcx.def_span(*def_id);
1892 if span.is_dummy() { None } else { Some(span) }
1894 .collect::<Vec<_>>()
1897 for pred in &preds {
1898 match pred.self_ty().kind() {
1899 ty::Adt(def, _) if def.did().is_local() => {
1900 spans.push_span_label(
1901 self.tcx.def_span(def.did()),
1902 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1909 if all_local_types_needing_impls && spans.primary_span().is_some() {
1910 let msg = if preds.len() == 1 {
1912 "an implementation of `{}` might be missing for `{}`",
1913 preds[0].trait_ref.print_only_trait_path(),
1918 "the following type{} would have to `impl` {} required trait{} for this \
1919 operation to be valid",
1920 pluralize!(def_ids.len()),
1921 if def_ids.len() == 1 { "its" } else { "their" },
1922 pluralize!(preds.len()),
1925 err.span_note(spans, &msg);
1928 let preds: Vec<_> = errors
1930 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1932 self.suggest_derive(err, &preds);
1935 pub fn suggest_derive(
1937 err: &mut Diagnostic,
1938 unsatisfied_predicates: &[(
1939 ty::Predicate<'tcx>,
1940 Option<ty::Predicate<'tcx>>,
1941 Option<ObligationCause<'tcx>>,
1944 let mut derives = Vec::<(String, Span, Symbol)>::new();
1945 let mut traits = Vec::new();
1946 for (pred, _, _) in unsatisfied_predicates {
1947 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
1948 let adt = match trait_pred.self_ty().ty_adt_def() {
1949 Some(adt) if adt.did().is_local() => adt,
1952 if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1953 let can_derive = match diagnostic_name {
1954 sym::Default => !adt.is_enum(),
1962 | sym::Debug => true,
1966 let self_name = trait_pred.self_ty().to_string();
1967 let self_span = self.tcx.def_span(adt.did());
1968 if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
1969 for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
1971 if let Some(parent_diagnostic_name) =
1972 self.tcx.get_diagnostic_name(super_trait.def_id())
1977 parent_diagnostic_name,
1982 derives.push((self_name, self_span, diagnostic_name));
1984 traits.push(trait_pred.def_id());
1987 traits.push(trait_pred.def_id());
1996 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1997 for (self_name, self_span, trait_name) in derives.into_iter() {
1998 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2000 if last_self_name == &self_name {
2001 last_trait_names.push_str(format!(", {}", trait_name).as_str());
2005 derives_grouped.push((self_name, self_span, trait_name.to_string()));
2008 let len = traits.len();
2011 MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
2012 let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
2013 for (i, &did) in traits.iter().enumerate().skip(1) {
2015 names.push_str(", ");
2018 names.push_str(" and ");
2021 names.push_str(&self.tcx.def_path_str(did));
2026 &format!("the trait{} {} must be implemented", pluralize!(len), names),
2030 for (self_name, self_span, traits) in &derives_grouped {
2031 err.span_suggestion_verbose(
2032 self_span.shrink_to_lo(),
2033 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
2034 format!("#[derive({})]\n", traits),
2035 Applicability::MaybeIncorrect,
2040 fn check_for_deref_method(
2042 err: &mut Diagnostic,
2043 self_source: SelfSource<'tcx>,
2046 expected: Expectation<'tcx>,
2048 let SelfSource::QPath(ty) = self_source else { return; };
2049 for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
2050 if let Ok(pick) = self.probe_for_name(
2053 expected.only_has_type(self),
2057 ProbeScope::TraitsInScope,
2059 if deref_ty.is_suggestable(self.tcx, true)
2060 // If this method receives `&self`, then the provided
2061 // argument _should_ coerce, so it's valid to suggest
2062 // just changing the path.
2063 && pick.item.fn_has_self_parameter
2064 && let Some(self_ty) =
2065 self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
2068 let suggested_path = match deref_ty.kind() {
2076 | ty::Alias(ty::Projection, _)
2077 | ty::Param(_) => format!("{deref_ty}"),
2078 // we need to test something like <&[_]>::len or <(&[u32])>::len
2079 // and Vec::function();
2080 // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
2081 // but for Adt type like Vec::function()
2082 // we would suggest <[_]>::function();
2083 _ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
2084 _ => format!("<{deref_ty}>"),
2086 err.span_suggestion_verbose(
2088 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2090 Applicability::MaybeIncorrect,
2095 format!("the function `{item_name}` is implemented on `{deref_ty}`"),
2103 /// Print out the type for use in value namespace.
2104 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
2106 ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
2107 _ => self.ty_to_string(ty),
2111 fn suggest_await_before_method(
2113 err: &mut Diagnostic,
2116 call: &hir::Expr<'_>,
2118 return_type: Option<Ty<'tcx>>,
2120 let output_ty = match self.get_impl_future_output_ty(ty) {
2121 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
2125 self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
2126 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
2128 err.span_suggestion_verbose(
2129 span.shrink_to_lo(),
2130 "consider `await`ing on the `Future` and calling the method on its `Output`",
2132 Applicability::MaybeIncorrect,
2137 fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
2138 let parent_map = self.tcx.visible_parent_map(());
2140 // Separate out candidates that must be imported with a glob, because they are named `_`
2141 // and cannot be referred with their identifier.
2142 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
2143 if let Some(parent_did) = parent_map.get(trait_did) {
2144 // If the item is re-exported as `_`, we should suggest a glob-import instead.
2145 if *parent_did != self.tcx.parent(*trait_did)
2148 .module_children(*parent_did)
2150 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
2151 .all(|child| child.ident.name == kw::Underscore)
2160 let module_did = self.tcx.parent_module(self.body_id);
2161 let (module, _, _) = self.tcx.hir().get_module(module_did);
2162 let span = module.spans.inject_use_span;
2164 let path_strings = candidates.iter().map(|trait_did| {
2165 format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
2168 let glob_path_strings = globs.iter().map(|trait_did| {
2169 let parent_did = parent_map.get(trait_did).unwrap();
2171 "use {}::*; // trait {}\n",
2172 with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
2173 self.tcx.item_name(*trait_did),
2177 err.span_suggestions(
2180 path_strings.chain(glob_path_strings),
2181 Applicability::MaybeIncorrect,
2185 fn suggest_valid_traits(
2187 err: &mut Diagnostic,
2188 valid_out_of_scope_traits: Vec<DefId>,
2190 if !valid_out_of_scope_traits.is_empty() {
2191 let mut candidates = valid_out_of_scope_traits;
2195 // `TryFrom` and `FromIterator` have no methods
2196 let edition_fix = candidates
2198 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
2201 err.help("items from traits can only be used if the trait is in scope");
2203 "the following {traits_are} implemented but not in scope; \
2204 perhaps add a `use` for {one_of_them}:",
2205 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
2206 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
2209 self.suggest_use_candidates(err, msg, candidates);
2210 if let Some(did) = edition_fix {
2212 "'{}' is included in the prelude starting in Edition 2021",
2213 with_crate_prefix!(self.tcx.def_path_str(did))
2223 fn suggest_traits_to_import(
2225 err: &mut Diagnostic,
2229 inputs_len: Option<usize>,
2230 source: SelfSource<'tcx>,
2231 valid_out_of_scope_traits: Vec<DefId>,
2232 unsatisfied_predicates: &[(
2233 ty::Predicate<'tcx>,
2234 Option<ty::Predicate<'tcx>>,
2235 Option<ObligationCause<'tcx>>,
2237 static_candidates: &[CandidateSource],
2238 unsatisfied_bounds: bool,
2239 return_type: Option<Ty<'tcx>>,
2241 let mut alt_rcvr_sugg = false;
2242 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
2244 "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
2245 span, item_name, rcvr_ty, rcvr
2248 self.tcx.lang_items().clone_trait(),
2249 self.tcx.lang_items().deref_trait(),
2250 self.tcx.lang_items().deref_mut_trait(),
2251 self.tcx.lang_items().drop_trait(),
2252 self.tcx.get_diagnostic_item(sym::AsRef),
2254 // Try alternative arbitrary self types that could fulfill this call.
2255 // FIXME: probe for all types that *could* be arbitrary self-types, not
2257 for (rcvr_ty, post) in &[
2259 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2260 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2262 match self.lookup_probe_for_diagnostic(
2266 ProbeScope::AllTraits,
2270 // If the method is defined for the receiver we have, it likely wasn't `use`d.
2271 // We point at the method, but we just skip the rest of the check for arbitrary
2272 // self types and rely on the suggestion to `use` the trait from
2273 // `suggest_valid_traits`.
2274 let did = Some(pick.item.container_id(self.tcx));
2275 let skip = skippable.contains(&did);
2276 if pick.autoderefs == 0 && !skip {
2278 pick.item.ident(self.tcx).span,
2279 &format!("the method is available for `{}` here", rcvr_ty),
2284 Err(MethodError::Ambiguity(_)) => {
2285 // If the method is defined (but ambiguous) for the receiver we have, it is also
2286 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
2287 // the receiver, then it might disambiguate this method, but I think these
2288 // suggestions are generally misleading (see #94218).
2294 for (rcvr_ty, pre) in &[
2295 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
2296 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
2297 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
2298 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
2300 if let Some(new_rcvr_t) = *rcvr_ty
2301 && let Ok(pick) = self.lookup_probe_for_diagnostic(
2305 ProbeScope::AllTraits,
2309 debug!("try_alt_rcvr: pick candidate {:?}", pick);
2310 let did = Some(pick.item.container_id(self.tcx));
2311 // We don't want to suggest a container type when the missing
2312 // method is `.clone()` or `.deref()` otherwise we'd suggest
2313 // `Arc::new(foo).clone()`, which is far from what the user wants.
2314 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2315 // implement the `AsRef` trait.
2316 let skip = skippable.contains(&did)
2317 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2318 || 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);
2319 // Make sure the method is defined for the *actual* receiver: we don't
2320 // want to treat `Box<Self>` as a receiver if it only works because of
2321 // an autoderef to `&self`
2322 if pick.autoderefs == 0 && !skip {
2324 pick.item.ident(self.tcx).span,
2325 &format!("the method is available for `{}` here", new_rcvr_t),
2327 err.multipart_suggestion(
2328 "consider wrapping the receiver expression with the \
2331 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
2332 (rcvr.span.shrink_to_hi(), ")".to_string()),
2334 Applicability::MaybeIncorrect,
2336 // We don't care about the other suggestions.
2337 alt_rcvr_sugg = true;
2343 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2347 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
2349 let mut arbitrary_rcvr = vec![];
2350 // There are no traits implemented, so lets suggest some traits to
2351 // implement, by finding ones that have the item name, and are
2352 // legal to implement.
2353 let mut candidates = all_traits(self.tcx)
2355 // Don't issue suggestions for unstable traits since they're
2356 // unlikely to be implementable anyway
2357 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
2358 Some(attr) => attr.level.is_stable(),
2362 // Static candidates are already implemented, and known not to work
2363 // Do not suggest them again
2364 static_candidates.iter().all(|sc| match *sc {
2365 CandidateSource::Trait(def_id) => def_id != info.def_id,
2366 CandidateSource::Impl(def_id) => {
2367 self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
2372 // We approximate the coherence rules to only suggest
2373 // traits that are legal to implement by requiring that
2374 // either the type or trait is local. Multi-dispatch means
2375 // this isn't perfect (that is, there are cases when
2376 // implementing a trait would be legal but is rejected
2378 unsatisfied_predicates.iter().all(|(p, _, _)| {
2379 match p.kind().skip_binder() {
2380 // Hide traits if they are present in predicates as they can be fixed without
2381 // having to implement them.
2382 ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
2383 t.def_id() == info.def_id
2385 ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
2386 p.projection_ty.def_id == info.def_id
2390 }) && (type_is_local || info.def_id.is_local())
2391 && !self.tcx.trait_is_auto(info.def_id)
2393 .associated_value(info.def_id, item_name)
2395 if let ty::AssocKind::Fn = item.kind {
2399 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
2400 if let Some(hir::Node::TraitItem(hir::TraitItem {
2401 kind: hir::TraitItemKind::Fn(fn_sig, method),
2403 })) = id.map(|id| self.tcx.hir().get(id))
2405 let self_first_arg = match method {
2406 hir::TraitFn::Required([ident, ..]) => {
2407 ident.name == kw::SelfLower
2409 hir::TraitFn::Provided(body_id) => {
2410 self.tcx.hir().body(*body_id).params.first().map_or(
2415 hir::PatKind::Binding(_, _, ident, _)
2416 if ident.name == kw::SelfLower
2424 if !fn_sig.decl.implicit_self.has_implicit_self()
2427 if let Some(ty) = fn_sig.decl.inputs.get(0) {
2428 arbitrary_rcvr.push(ty.span);
2434 // We only want to suggest public or local traits (#45781).
2435 item.visibility(self.tcx).is_public() || info.def_id.is_local()
2439 .collect::<Vec<_>>();
2440 for span in &arbitrary_rcvr {
2443 "the method might not be found because of this arbitrary self type",
2450 if !candidates.is_empty() {
2451 // Sort from most relevant to least relevant.
2452 candidates.sort_by(|a, b| a.cmp(b).reverse());
2455 let param_type = match rcvr_ty.kind() {
2456 ty::Param(param) => Some(param),
2457 ty::Ref(_, ty, _) => match ty.kind() {
2458 ty::Param(param) => Some(param),
2463 err.help(if param_type.is_some() {
2464 "items from traits can only be used if the type parameter is bounded by the trait"
2466 "items from traits can only be used if the trait is implemented and in scope"
2468 let candidates_len = candidates.len();
2469 let message = |action| {
2471 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
2474 if candidates_len == 1 { "trait defines" } else { "traits define" },
2476 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
2480 // Obtain the span for `param` and use it for a structured suggestion.
2481 if let Some(param) = param_type {
2482 let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
2483 let type_param = generics.type_param(param, self.tcx);
2484 let hir = self.tcx.hir();
2485 if let Some(def_id) = type_param.def_id.as_local() {
2486 let id = hir.local_def_id_to_hir_id(def_id);
2487 // Get the `hir::Param` to verify whether it already has any bounds.
2488 // We do this to avoid suggesting code that ends up as `T: FooBar`,
2489 // instead we suggest `T: Foo + Bar` in that case.
2491 Node::GenericParam(param) => {
2497 let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2498 let (sp, mut introducer) = if let Some(span) =
2499 ast_generics.bounds_span_for_suggestions(def_id)
2501 (span, Introducer::Plus)
2502 } else if let Some(colon_span) = param.colon_span {
2503 (colon_span.shrink_to_hi(), Introducer::Nothing)
2505 (param.span.shrink_to_hi(), Introducer::Colon)
2509 hir::GenericParamKind::Type { synthetic: true, .. },
2511 introducer = Introducer::Plus
2513 let trait_def_ids: FxHashSet<DefId> = ast_generics
2514 .bounds_for_param(def_id)
2515 .flat_map(|bp| bp.bounds.iter())
2516 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
2518 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2519 err.span_suggestions(
2522 "restrict type parameter `{}` with",
2525 candidates.iter().map(|t| {
2529 Introducer::Plus => " +",
2530 Introducer::Colon => ":",
2531 Introducer::Nothing => "",
2533 self.tcx.def_path_str(t.def_id),
2536 Applicability::MaybeIncorrect,
2541 Node::Item(hir::Item {
2542 kind: hir::ItemKind::Trait(.., bounds, _),
2546 let (sp, sep, article) = if bounds.is_empty() {
2547 (ident.span.shrink_to_hi(), ":", "a")
2549 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
2551 err.span_suggestions(
2553 &message(format!("add {} supertrait for", article)),
2554 candidates.iter().map(|t| {
2555 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
2557 Applicability::MaybeIncorrect,
2566 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
2567 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2568 // cases where a positive bound implies a negative impl.
2569 (candidates, Vec::new())
2570 } else if let Some(simp_rcvr_ty) =
2571 simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
2573 let mut potential_candidates = Vec::new();
2574 let mut explicitly_negative = Vec::new();
2575 for candidate in candidates {
2576 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2579 .all_impls(candidate.def_id)
2581 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
2584 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
2586 simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
2587 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
2590 explicitly_negative.push(candidate);
2592 potential_candidates.push(candidate);
2595 (potential_candidates, explicitly_negative)
2597 // We don't know enough about `recv_ty` to make proper suggestions.
2598 (candidates, Vec::new())
2601 let action = if let Some(param) = param_type {
2602 format!("restrict type parameter `{}` with", param)
2604 // FIXME: it might only need to be imported into scope, not implemented.
2605 "implement".to_string()
2607 match &potential_candidates[..] {
2609 [trait_info] if trait_info.def_id.is_local() => {
2611 self.tcx.def_span(trait_info.def_id),
2613 "`{}` defines an item `{}`, perhaps you need to {} it",
2614 self.tcx.def_path_str(trait_info.def_id),
2621 let mut msg = message(action);
2622 for (i, trait_info) in trait_infos.iter().enumerate() {
2623 msg.push_str(&format!(
2624 "\ncandidate #{}: `{}`",
2626 self.tcx.def_path_str(trait_info.def_id),
2632 match &explicitly_negative[..] {
2636 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2637 self.tcx.def_path_str(trait_info.def_id),
2643 let mut msg = format!(
2644 "the following traits define an item `{}`, but are explicitly unimplemented:",
2647 for trait_info in trait_infos {
2648 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
2656 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
2657 /// FIXME: currently not working for suggesting `map_or_else`, see #102408
2658 pub(crate) fn suggest_else_fn_with_closure(
2660 err: &mut Diagnostic,
2661 expr: &hir::Expr<'_>,
2665 let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
2666 else { return false; };
2668 if !self.can_coerce(output, expected) {
2672 let parent = self.tcx.hir().parent_id(expr.hir_id);
2673 if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
2674 let hir::ExprKind::MethodCall(
2675 hir::PathSegment { ident: method_name, .. },
2679 ) = call_expr.kind &&
2680 let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
2681 let new_name = Ident {
2682 name: Symbol::intern(&format!("{}_else", method_name.as_str())),
2683 span: method_name.span,
2685 let probe = self.lookup_probe_for_diagnostic(
2689 ProbeScope::TraitsInScope,
2693 // check the method arguments number
2694 if let Ok(pick) = probe &&
2695 let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
2696 let fn_args = fn_sig.skip_binder().inputs() &&
2697 fn_args.len() == args.len() + 1 {
2698 err.span_suggestion_verbose(
2699 method_name.span.shrink_to_hi(),
2700 &format!("try calling `{}` instead", new_name.name.as_str()),
2702 Applicability::MaybeIncorrect,
2710 /// Checks whether there is a local type somewhere in the chain of
2711 /// autoderefs of `rcvr_ty`.
2712 fn type_derefs_to_local(
2716 source: SelfSource<'tcx>,
2718 fn is_local(ty: Ty<'_>) -> bool {
2720 ty::Adt(def, _) => def.did().is_local(),
2721 ty::Foreign(did) => did.is_local(),
2722 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
2723 ty::Param(_) => true,
2725 // Everything else (primitive types, etc.) is effectively
2726 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2727 // the noise from these sort of types is usually just really
2728 // annoying, rather than any sort of help).
2733 // This occurs for UFCS desugaring of `T::method`, where there is no
2734 // receiver expression for the method call, and thus no autoderef.
2735 if let SelfSource::QPath(_) = source {
2736 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
2739 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
2743 #[derive(Copy, Clone, Debug)]
2744 pub enum SelfSource<'a> {
2745 QPath(&'a hir::Ty<'a>),
2746 MethodCall(&'a hir::Expr<'a> /* rcvr */),
2749 #[derive(Copy, Clone)]
2750 pub struct TraitInfo {
2754 impl PartialEq for TraitInfo {
2755 fn eq(&self, other: &TraitInfo) -> bool {
2756 self.cmp(other) == Ordering::Equal
2759 impl Eq for TraitInfo {}
2760 impl PartialOrd for TraitInfo {
2761 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
2762 Some(self.cmp(other))
2765 impl Ord for TraitInfo {
2766 fn cmp(&self, other: &TraitInfo) -> Ordering {
2767 // Local crates are more important than remote ones (local:
2768 // `cnum == 0`), and otherwise we throw in the defid for totality.
2770 let lhs = (other.def_id.krate, other.def_id);
2771 let rhs = (self.def_id.krate, self.def_id);
2776 /// Retrieves all traits in this crate and any dependent crates,
2777 /// and wraps them into `TraitInfo` for custom sorting.
2778 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
2779 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
2782 fn print_disambiguation_help<'tcx>(
2784 args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2785 err: &mut Diagnostic,
2788 kind: ty::AssocKind,
2791 candidate: Option<usize>,
2792 source_map: &source_map::SourceMap,
2793 fn_has_self_parameter: bool,
2795 let mut applicability = Applicability::MachineApplicable;
2796 let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
2799 rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
2800 std::iter::once(receiver)
2802 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
2803 applicability = Applicability::HasPlaceholders;
2806 .collect::<Vec<_>>()
2809 let trait_name = if !fn_has_self_parameter {
2810 format!("<{} as {}>", rcvr_ty, trait_name)
2814 (span, format!("{}::{}{}", trait_name, item_name, args))
2816 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
2818 err.span_suggestion_verbose(
2821 "disambiguate the {} for {}",
2822 kind.as_def_kind().descr(def_id),
2823 if let Some(candidate) = candidate {
2824 format!("candidate #{}", candidate)
2826 "the candidate".to_string()