1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
4 use crate::check::FnCtxt;
5 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
8 use rustc_hir::def_id::{DefId, LocalDefId};
9 use rustc_hir::lang_items::LangItem;
10 use rustc_hir::{ExprKind, Node, QPath};
11 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
12 use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
13 use rustc_middle::ty::print::with_crate_prefix;
14 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
15 use rustc_span::lev_distance;
16 use rustc_span::symbol::{kw, sym, Ident};
17 use rustc_span::{source_map, FileName, MultiSpan, Span};
18 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
19 use rustc_trait_selection::traits::{
20 FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
23 use std::cmp::Ordering;
26 use super::probe::Mode;
27 use super::{CandidateSource, MethodError, NoMatchData};
29 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
33 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
34 // so we look for these beforehand.
35 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
36 // If it's not a simple function, look for things which implement `FnOnce`.
38 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
39 Ok(fn_once) => fn_once,
40 Err(..) => return false,
43 self.autoderef(span, ty).any(|(ty, _)| {
45 let fn_once_substs = tcx.mk_substs_trait(
48 .next_ty_var(TypeVariableOrigin {
49 kind: TypeVariableOriginKind::MiscVariable,
54 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
55 let poly_trait_ref = ty::Binder::dummy(trait_ref);
56 let obligation = Obligation::misc(
60 poly_trait_ref.without_const().to_predicate(tcx),
62 self.predicate_may_hold(&obligation)
69 fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
70 self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
73 pub fn report_method_error(
78 source: SelfSource<'tcx>,
79 error: MethodError<'tcx>,
80 args: Option<&'tcx [hir::Expr<'tcx>]>,
81 ) -> Option<DiagnosticBuilder<'_>> {
82 // Avoid suggestions when we don't know what's going on.
83 if rcvr_ty.references_error() {
87 let report_candidates = |span: Span,
88 err: &mut DiagnosticBuilder<'_>,
89 mut sources: Vec<CandidateSource>,
93 // Dynamic limit to avoid hiding just one candidate, which is silly.
94 let limit = if sources.len() == 5 { 5 } else { 4 };
96 for (idx, source) in sources.iter().take(limit).enumerate() {
98 CandidateSource::ImplSource(impl_did) => {
99 // Provide the best span we can. Use the item, if local to crate, else
100 // the impl, if local to crate (item may be defaulted), else nothing.
101 let item = match self.associated_value(impl_did, item_name).or_else(|| {
102 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
103 self.associated_value(impl_trait_ref.def_id, item_name)
111 .span_if_local(item.def_id)
112 .or_else(|| self.tcx.hir().span_if_local(impl_did));
114 let impl_ty = self.tcx.at(span).type_of(impl_did);
116 let insertion = match self.tcx.impl_trait_ref(impl_did) {
117 None => String::new(),
118 Some(trait_ref) => format!(
119 " of the trait `{}`",
120 self.tcx.def_path_str(trait_ref.def_id)
124 let (note_str, idx) = if sources.len() > 1 {
127 "candidate #{} is defined in an impl{} for the type `{}`",
137 "the candidate is defined in an impl{} for the type `{}`",
143 if let Some(note_span) = note_span {
144 // We have a span pointing to the method. Show note with snippet.
146 self.tcx.sess.source_map().guess_head_span(note_span),
152 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
153 let path = self.tcx.def_path_str(trait_ref.def_id);
155 let ty = match item.kind {
156 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
157 ty::AssocKind::Fn => self
163 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
167 print_disambiguation_help(
177 self.tcx.sess.source_map(),
178 item.fn_has_self_parameter,
182 CandidateSource::TraitSource(trait_did) => {
183 let item = match self.associated_value(trait_did, item_name) {
191 .guess_head_span(self.tcx.def_span(item.def_id));
192 let idx = if sources.len() > 1 {
194 "candidate #{} is defined in the trait `{}`",
196 self.tcx.def_path_str(trait_did)
198 err.span_note(item_span, msg);
202 "the candidate is defined in the trait `{}`",
203 self.tcx.def_path_str(trait_did)
205 err.span_note(item_span, msg);
208 let path = self.tcx.def_path_str(trait_did);
209 print_disambiguation_help(
219 self.tcx.sess.source_map(),
220 item.fn_has_self_parameter,
225 if sources.len() > limit {
226 err.note(&format!("and {} others", sources.len() - limit));
230 let sugg_span = if let SelfSource::MethodCall(expr) = source {
231 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
232 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
238 MethodError::NoMatch(NoMatchData {
239 static_candidates: static_sources,
240 unsatisfied_predicates,
247 let actual = self.resolve_vars_if_possible(rcvr_ty);
248 let ty_str = self.ty_to_string(actual);
249 let is_method = mode == Mode::MethodCall;
250 let item_kind = if is_method {
252 } else if actual.is_enum() {
253 "variant or associated item"
255 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
256 (Some(name), false) if name.is_lowercase() => "function or associated item",
257 (Some(_), false) => "associated item",
258 (Some(_), true) | (None, false) => "variant or associated item",
259 (None, true) => "variant",
262 let mut err = if !actual.references_error() {
263 // Suggest clamping down the type if the method that is being attempted to
264 // be used exists at all, and the type is an ambiguous numeric type
265 // ({integer}/{float}).
266 let mut candidates = all_traits(self.tcx)
268 .filter_map(|info| self.associated_value(info.def_id, item_name));
269 // There are methods that are defined on the primitive types and won't be
270 // found when exploring `all_traits`, but we also need them to be acurate on
271 // our suggestions (#47759).
272 let fund_assoc = |opt_def_id: Option<DefId>| {
273 opt_def_id.and_then(|id| self.associated_value(id, item_name)).is_some()
275 let lang_items = tcx.lang_items();
276 let found_candidate = candidates.next().is_some()
277 || fund_assoc(lang_items.i8_impl())
278 || fund_assoc(lang_items.i16_impl())
279 || fund_assoc(lang_items.i32_impl())
280 || fund_assoc(lang_items.i64_impl())
281 || fund_assoc(lang_items.i128_impl())
282 || fund_assoc(lang_items.u8_impl())
283 || fund_assoc(lang_items.u16_impl())
284 || fund_assoc(lang_items.u32_impl())
285 || fund_assoc(lang_items.u64_impl())
286 || fund_assoc(lang_items.u128_impl())
287 || fund_assoc(lang_items.f32_impl())
288 || fund_assoc(lang_items.f32_runtime_impl())
289 || fund_assoc(lang_items.f64_impl())
290 || fund_assoc(lang_items.f64_runtime_impl());
291 if let (true, false, SelfSource::MethodCall(expr), true) = (
293 actual.has_concrete_skeleton(),
297 let mut err = struct_span_err!(
301 "can't call {} `{}` on ambiguous numeric type `{}`",
306 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
308 ExprKind::Lit(ref lit) => {
313 .span_to_snippet(lit.span)
314 .unwrap_or_else(|_| "<numeric literal>".to_owned());
316 // If this is a floating point literal that ends with '.',
317 // get rid of it to stop this from becoming a member access.
318 let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
323 "you must specify a concrete type for this numeric value, \
327 format!("{snippet}_{concrete_type}"),
328 Applicability::MaybeIncorrect,
331 ExprKind::Path(QPath::Resolved(_, path)) => {
333 if let hir::def::Res::Local(hir_id) = path.res {
334 let span = tcx.hir().span(hir_id);
335 let snippet = tcx.sess.source_map().span_to_snippet(span);
336 let filename = tcx.sess.source_map().span_to_filename(span);
339 self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
341 "you must specify a type for this binding, like `{}`",
345 match (filename, parent_node, snippet) {
348 Node::Local(hir::Local {
349 source: hir::LocalSource::Normal,
356 // account for `let x: _ = 42;`
363 format!("{}: {}", snippet, concrete_type),
364 Applicability::MaybeIncorrect,
368 err.span_label(span, msg);
378 span = item_name.span;
380 // Don't show generic arguments when the method can't be found in any implementation (#81576).
381 let mut ty_str_reported = ty_str.clone();
382 if let ty::Adt(_, generics) = actual.kind() {
383 if generics.len() > 0 {
384 let mut autoderef = self.autoderef(span, actual);
385 let candidate_found = autoderef.any(|(ty, _)| {
386 if let ty::Adt(adt_deref, _) = ty.kind() {
388 .inherent_impls(adt_deref.did)
390 .filter_map(|def_id| {
391 self.associated_value(*def_id, item_name)
399 let has_deref = autoderef.step_count() > 0;
402 && unsatisfied_predicates.is_empty()
404 if let Some((path_string, _)) = ty_str.split_once('<') {
405 ty_str_reported = path_string.to_string();
411 let mut err = struct_span_err!(
415 "no {} named `{}` found for {} `{}` in the current scope",
418 actual.prefix_string(self.tcx),
421 if let Mode::MethodCall = mode {
422 if let SelfSource::MethodCall(call) = source {
423 self.suggest_await_before_method(
424 &mut err, item_name, actual, call, span,
429 tcx.resolutions(()).confused_type_with_std_module.get(&span)
431 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
434 "you are looking for the module in `std`, \
435 not the primitive type",
436 format!("std::{}", snippet),
437 Applicability::MachineApplicable,
441 if let ty::RawPtr(_) = &actual.kind() {
443 "try using `<*const T>::as_ref()` to get a reference to the \
444 type behind the pointer: https://doc.rust-lang.org/std/\
445 primitive.pointer.html#method.as_ref",
448 "using `<*const T>::as_ref()` on a pointer \
449 which is unaligned or points to invalid \
450 or uninitialized memory is undefined behavior",
456 tcx.sess.diagnostic().struct_dummy()
459 if let Some(def) = actual.ty_adt_def() {
460 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
461 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
465 "{} `{}` not found {}",
468 if def.is_enum() && !is_method { "here" } else { "for this" }
474 let mut label_span_not_found = || {
475 if unsatisfied_predicates.is_empty() {
476 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
477 let is_string_or_ref_str = match actual.kind() {
478 ty::Ref(_, ty, _) => {
482 ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did)
485 ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did),
488 if is_string_or_ref_str && item_name.name == sym::iter {
489 err.span_suggestion_verbose(
491 "because of the in-memory representation of `&str`, to obtain \
492 an `Iterator` over each of its codepoint use method `chars`",
493 String::from("chars"),
494 Applicability::MachineApplicable,
497 if let ty::Adt(adt, _) = rcvr_ty.kind() {
498 let mut inherent_impls_candidate = self
500 .inherent_impls(adt.did)
504 if let Some(assoc) = self.associated_value(*def_id, item_name) {
505 // Check for both mode is the same so we avoid suggesting
506 // incorrect associated item.
507 match (mode, assoc.fn_has_self_parameter, source) {
508 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
509 // We check that the suggest type is actually
510 // different from the received one
511 // So we avoid suggestion method with Box<Self>
513 self.tcx.at(span).type_of(*def_id) != actual
514 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
516 (Mode::Path, false, _) => true,
523 .collect::<Vec<_>>();
524 if !inherent_impls_candidate.is_empty() {
525 inherent_impls_candidate.sort();
526 inherent_impls_candidate.dedup();
528 // number of type to shows at most.
529 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
530 let type_candidates = inherent_impls_candidate
534 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
538 let additional_types = if inherent_impls_candidate.len() > limit {
540 "\nand {} more types",
541 inherent_impls_candidate.len() - limit
547 "the {item_kind} was found for\n{}{}",
548 type_candidates, additional_types
553 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
557 // If the method name is the name of a field with a function or closure type,
558 // give a helping note that it has to be called as `(x.f)(...)`.
559 if let SelfSource::MethodCall(expr) = source {
561 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
562 ty::Adt(def, substs) if !def.is_enum() => {
563 let variant = &def.non_enum_variant();
564 self.tcx.find_field_index(item_name, variant).map(|index| {
565 let field = &variant.fields[index];
566 let field_ty = field.ty(tcx, substs);
573 if let Some((field, field_ty)) = field_receiver {
574 let scope = self.tcx.parent_module(self.body_id).to_def_id();
575 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
578 if self.is_fn_ty(field_ty, span) {
579 let expr_span = expr.span.to(item_name.span);
580 err.multipart_suggestion(
582 "to call the function stored in `{}`, \
583 surround the field access with parentheses",
587 (expr_span.shrink_to_lo(), '('.to_string()),
588 (expr_span.shrink_to_hi(), ')'.to_string()),
590 Applicability::MachineApplicable,
596 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
598 if let Some(span) = call_expr.span.trim_start(item_name.span) {
601 "remove the arguments",
603 Applicability::MaybeIncorrect,
609 let field_kind = if is_accessible { "field" } else { "private field" };
610 err.span_label(item_name.span, format!("{}, not a method", field_kind));
611 } else if lev_candidate.is_none() && static_sources.is_empty() {
612 label_span_not_found();
615 label_span_not_found();
618 if self.is_fn_ty(rcvr_ty, span) {
619 fn report_function<T: std::fmt::Display>(
620 err: &mut DiagnosticBuilder<'_>,
624 &format!("`{}` is a function, perhaps you wish to call it", name,),
628 if let SelfSource::MethodCall(expr) = source {
629 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
630 report_function(&mut err, expr_string);
631 } else if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind {
632 if let Some(segment) = path.segments.last() {
633 report_function(&mut err, segment.ident);
639 if !static_sources.is_empty() {
641 "found the following associated functions; to be used as methods, \
642 functions must have a `self` parameter",
644 err.span_label(span, "this is an associated function, not a method");
646 if static_sources.len() == 1 {
647 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
648 static_sources.get(0)
650 // When the "method" is resolved through dereferencing, we really want the
651 // original type that has the associated function for accurate suggestions.
653 let ty = tcx.at(span).type_of(*impl_did);
654 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
655 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
656 // Use `actual` as it will have more `substs` filled in.
657 self.ty_to_value_string(actual.peel_refs())
659 _ => self.ty_to_value_string(ty.peel_refs()),
662 self.ty_to_value_string(actual.peel_refs())
664 if let SelfSource::MethodCall(expr) = source {
667 "use associated function syntax instead",
668 format!("{}::{}", ty_str, item_name),
669 Applicability::MachineApplicable,
672 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
675 report_candidates(span, &mut err, static_sources, sugg_span);
676 } else if static_sources.len() > 1 {
677 report_candidates(span, &mut err, static_sources, sugg_span);
680 let mut restrict_type_params = false;
681 let mut unsatisfied_bounds = false;
682 if item_name.name == sym::count && self.is_slice_ty(actual, span) {
683 let msg = "consider using `len` instead";
684 if let SelfSource::MethodCall(_expr) = source {
685 err.span_suggestion_short(
689 Applicability::MachineApplicable,
692 err.span_label(span, msg);
694 if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
695 let iterator_trait = self.tcx.def_path_str(iterator_trait);
696 err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
698 } else if !unsatisfied_predicates.is_empty() {
699 let def_span = |def_id| {
700 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
702 let mut type_params = FxHashMap::default();
703 let mut bound_spans = vec![];
705 let mut collect_type_param_suggestions =
706 |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
707 // We don't care about regions here, so it's fine to skip the binder here.
708 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
709 (self_ty.kind(), parent_pred.kind().skip_binder())
711 let node = match p.trait_ref.self_ty().kind() {
713 // Account for `fn` items like in `issue-35677.rs` to
714 // suggest restricting its type params.
715 let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
716 hir_id: self.body_id,
721 .get(self.tcx.hir().local_def_id_to_hir_id(did)),
724 ty::Adt(def, _) => def.did.as_local().map(|def_id| {
727 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
731 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
732 if let Some(g) = kind.generics() {
733 let key = match g.where_clause.predicates {
734 [.., pred] => (pred.span().shrink_to_hi(), false),
736 g.where_clause.span_for_predicates_or_empty_place(),
742 .or_insert_with(FxHashSet::default)
743 .insert(obligation.to_owned());
748 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
750 "doesn't satisfy `{}`",
751 if obligation.len() > 50 { quiet } else { obligation }
753 match &self_ty.kind() {
754 // Point at the type that couldn't satisfy the bound.
755 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
756 // Point at the trait object that couldn't satisfy the bound.
757 ty::Dynamic(preds, _) => {
758 for pred in preds.iter() {
759 match pred.skip_binder() {
760 ty::ExistentialPredicate::Trait(tr) => {
761 bound_spans.push((def_span(tr.def_id), msg.clone()))
763 ty::ExistentialPredicate::Projection(_)
764 | ty::ExistentialPredicate::AutoTrait(_) => {}
768 // Point at the closure that couldn't satisfy the bound.
769 ty::Closure(def_id, _) => bound_spans
770 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
774 let mut format_pred = |pred: ty::Predicate<'tcx>| {
775 let bound_predicate = pred.kind();
776 match bound_predicate.skip_binder() {
777 ty::PredicateKind::Projection(pred) => {
778 let pred = bound_predicate.rebind(pred);
779 // `<Foo as Iterator>::Item = String`.
780 let projection_ty = pred.skip_binder().projection_ty;
782 let substs_with_infer_self = tcx.mk_substs(
783 iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
784 .chain(projection_ty.substs.iter().skip(1)),
787 let quiet_projection_ty = ty::ProjectionTy {
788 substs: substs_with_infer_self,
789 item_def_id: projection_ty.item_def_id,
792 let term = pred.skip_binder().term;
794 let obligation = format!("{} = {}", projection_ty, term);
795 let quiet = format!("{} = {}", quiet_projection_ty, term);
797 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
798 Some((obligation, projection_ty.self_ty()))
800 ty::PredicateKind::Trait(poly_trait_ref) => {
801 let p = poly_trait_ref.trait_ref;
802 let self_ty = p.self_ty();
803 let path = p.print_only_trait_path();
804 let obligation = format!("{}: {}", self_ty, path);
805 let quiet = format!("_: {}", path);
806 bound_span_label(self_ty, &obligation, &quiet);
807 Some((obligation, self_ty))
813 // Find all the requirements that come from a local `impl` block.
814 let mut skip_list: FxHashSet<_> = Default::default();
815 let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
816 for (data, p, parent_p) in unsatisfied_predicates
818 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
819 .filter_map(|(p, parent, c)| match c.code() {
820 ObligationCauseCode::ImplDerivedObligation(ref data) => {
821 Some((data, p, parent))
826 let parent_trait_ref = data.parent_trait_pred;
827 let parent_def_id = parent_trait_ref.def_id();
828 let path = parent_trait_ref.print_modifiers_and_trait_path();
829 let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
830 let mut candidates = vec![];
831 self.tcx.for_each_relevant_impl(
833 parent_trait_ref.self_ty().skip_binder(),
834 |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) {
835 Some(Node::Item(hir::Item {
836 kind: hir::ItemKind::Impl(hir::Impl { .. }),
839 candidates.push(impl_def_id);
844 if let [def_id] = &candidates[..] {
845 match self.tcx.hir().get_if_local(*def_id) {
846 Some(Node::Item(hir::Item {
847 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
850 if let Some(pred) = parent_p {
851 // Done to add the "doesn't satisfy" `span_label`.
852 let _ = format_pred(*pred);
855 let mut spans = Vec::with_capacity(2);
856 if let Some(trait_ref) = of_trait {
857 spans.push(trait_ref.path.span);
859 spans.push(self_ty.span);
860 let entry = spanned_predicates.entry(spans.into());
862 .or_insert_with(|| (path, tr_self_ty, Vec::new()))
870 for (span, (path, self_ty, preds)) in spanned_predicates {
874 "the following trait bounds were not satisfied because of the \
875 requirements of the implementation of `{}` for `{}`:\n{}",
880 // .map(|pred| format!("{:?}", pred))
881 .filter_map(|pred| format_pred(*pred))
882 .map(|(p, _)| format!("`{}`", p))
889 // The requirements that didn't have an `impl` span to show.
890 let mut bound_list = unsatisfied_predicates
892 .filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred))
893 .filter_map(|(pred, parent_pred, _cause)| {
894 format_pred(*pred).map(|(p, self_ty)| {
895 collect_type_param_suggestions(self_ty, *pred, &p);
897 None => format!("`{}`", &p),
898 Some(parent_pred) => match format_pred(*parent_pred) {
899 None => format!("`{}`", &p),
900 Some((parent_p, _)) => {
901 collect_type_param_suggestions(
906 format!("`{}`\nwhich is required by `{}`", p, parent_p)
913 .collect::<Vec<(usize, String)>>();
915 for ((span, empty_where), obligations) in type_params.into_iter() {
916 restrict_type_params = true;
917 // #74886: Sort here so that the output is always the same.
918 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
920 err.span_suggestion_verbose(
923 "consider restricting the type parameter{s} to satisfy the \
925 s = pluralize!(obligations.len())
929 if empty_where { " where" } else { "," },
930 obligations.join(", ")
932 Applicability::MaybeIncorrect,
936 bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
937 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
938 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
941 for (span, msg) in bound_spans.into_iter() {
942 err.span_label(span, &msg);
944 if !bound_list.is_empty() || !skip_list.is_empty() {
945 let bound_list = bound_list
947 .map(|(_, path)| path)
950 let actual_prefix = actual.prefix_string(self.tcx);
951 err.set_primary_message(&format!(
952 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
954 if !bound_list.is_empty() {
956 "the following trait bounds were not satisfied:\n{bound_list}"
959 self.suggest_derive(&mut err, &unsatisfied_predicates);
961 unsatisfied_bounds = true;
965 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
967 self.suggest_traits_to_import(
974 &unsatisfied_predicates,
979 // Don't emit a suggestion if we found an actual method
980 // that had unsatisfied trait bounds
981 if unsatisfied_predicates.is_empty() && actual.is_enum() {
982 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
983 if let Some(suggestion) = lev_distance::find_best_match_for_name(
984 &adt_def.variants.iter().map(|s| s.name).collect::<Vec<_>>(),
990 "there is a variant with a similar name",
991 suggestion.to_string(),
992 Applicability::MaybeIncorrect,
997 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
998 let msg = "remove this method call";
999 let mut fallback_span = true;
1000 if let SelfSource::MethodCall(expr) = source {
1002 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
1003 if let Some(span) = call_expr.span.trim_start(expr.span) {
1004 err.span_suggestion(
1008 Applicability::MachineApplicable,
1010 fallback_span = false;
1014 err.span_label(span, msg);
1016 } else if let Some(lev_candidate) = lev_candidate {
1017 // Don't emit a suggestion if we found an actual method
1018 // that had unsatisfied trait bounds
1019 if unsatisfied_predicates.is_empty() {
1020 let def_kind = lev_candidate.kind.as_def_kind();
1021 err.span_suggestion(
1024 "there is {} {} with a similar name",
1026 def_kind.descr(lev_candidate.def_id),
1028 lev_candidate.name.to_string(),
1029 Applicability::MaybeIncorrect,
1037 MethodError::Ambiguity(sources) => {
1038 let mut err = struct_span_err!(
1042 "multiple applicable items in scope"
1044 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
1046 report_candidates(span, &mut err, sources, sugg_span);
1050 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
1051 let kind = kind.descr(def_id);
1052 let mut err = struct_span_err!(
1056 "{} `{}` is private",
1060 err.span_label(item_name.span, &format!("private {}", kind));
1064 .span_if_local(def_id)
1065 .unwrap_or_else(|| self.tcx.def_span(def_id));
1066 err.span_label(sp, &format!("private {} defined here", kind));
1067 self.suggest_valid_traits(&mut err, out_of_scope_traits);
1071 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
1072 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
1073 let mut err = self.sess().struct_span_err(span, &msg);
1074 err.span_label(bound_span, "this has a `Sized` requirement");
1075 if !candidates.is_empty() {
1077 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1078 add a `use` for {one_of_them}:",
1079 an = if candidates.len() == 1 { "an" } else { "" },
1080 s = pluralize!(candidates.len()),
1081 were = if candidates.len() == 1 { "was" } else { "were" },
1082 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
1084 self.suggest_use_candidates(&mut err, help, candidates);
1086 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
1088 let trait_type = self.tcx.mk_ref(
1090 ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
1092 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
1098 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
1103 crate fn note_unmet_impls_on_type(
1105 err: &mut rustc_errors::DiagnosticBuilder<'_>,
1106 errors: Vec<FulfillmentError<'tcx>>,
1108 let all_local_types_needing_impls =
1109 errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
1110 ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
1111 ty::Adt(def, _) => def.did.is_local(),
1116 let mut preds: Vec<_> = errors
1118 .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
1119 ty::PredicateKind::Trait(pred) => Some(pred),
1123 preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
1126 .filter_map(|pred| match pred.self_ty().kind() {
1127 ty::Adt(def, _) => Some(def.did),
1130 .collect::<FxHashSet<_>>();
1131 let sm = self.tcx.sess.source_map();
1132 let mut spans: MultiSpan = def_ids
1134 .filter_map(|def_id| {
1135 let span = self.tcx.def_span(*def_id);
1136 if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) }
1138 .collect::<Vec<_>>()
1141 for pred in &preds {
1142 match pred.self_ty().kind() {
1143 ty::Adt(def, _) => {
1144 spans.push_span_label(
1145 sm.guess_head_span(self.tcx.def_span(def.did)),
1146 format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
1153 if all_local_types_needing_impls && spans.primary_span().is_some() {
1154 let msg = if preds.len() == 1 {
1156 "an implementation of `{}` might be missing for `{}`",
1157 preds[0].trait_ref.print_only_trait_path(),
1162 "the following type{} would have to `impl` {} required trait{} for this \
1163 operation to be valid",
1164 pluralize!(def_ids.len()),
1165 if def_ids.len() == 1 { "its" } else { "their" },
1166 pluralize!(preds.len()),
1169 err.span_note(spans, &msg);
1172 let preds: Vec<_> = errors
1174 .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
1176 self.suggest_derive(err, &preds);
1181 err: &mut DiagnosticBuilder<'_>,
1182 unsatisfied_predicates: &[(
1183 ty::Predicate<'tcx>,
1184 Option<ty::Predicate<'tcx>>,
1185 Option<ObligationCause<'tcx>>,
1188 let mut derives = Vec::<(String, Span, String)>::new();
1189 let mut traits = Vec::<Span>::new();
1190 for (pred, _, _) in unsatisfied_predicates {
1191 let trait_pred = match pred.kind().skip_binder() {
1192 ty::PredicateKind::Trait(trait_pred) => trait_pred,
1195 let adt = match trait_pred.self_ty().ty_adt_def() {
1196 Some(adt) if adt.did.is_local() => adt,
1199 let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1200 Some(sym::Default) => !adt.is_enum(),
1215 format!("{}", trait_pred.self_ty()),
1216 self.tcx.def_span(adt.did),
1217 format!("{}", trait_pred.trait_ref.print_only_trait_name()),
1220 traits.push(self.tcx.def_span(trait_pred.def_id()));
1229 let mut derives_grouped = Vec::<(String, Span, String)>::new();
1230 for (self_name, self_span, trait_name) in derives.into_iter() {
1231 if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1233 if last_self_name == &self_name {
1234 last_trait_names.push_str(format!(", {}", trait_name).as_str());
1238 derives_grouped.push((self_name, self_span, trait_name));
1241 let len = traits.len();
1243 let span: MultiSpan = traits.into();
1246 &format!("the following trait{} must be implemented", pluralize!(len),),
1250 for (self_name, self_span, traits) in &derives_grouped {
1251 err.span_suggestion_verbose(
1252 self_span.shrink_to_lo(),
1253 &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
1254 format!("#[derive({})]\n", traits),
1255 Applicability::MaybeIncorrect,
1260 /// Print out the type for use in value namespace.
1261 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1263 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
1264 _ => self.ty_to_string(ty),
1268 fn suggest_await_before_method(
1270 err: &mut DiagnosticBuilder<'_>,
1273 call: &hir::Expr<'_>,
1276 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
1277 Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
1280 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
1281 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
1283 err.span_suggestion_verbose(
1284 span.shrink_to_lo(),
1285 "consider `await`ing on the `Future` and calling the method on its `Output`",
1286 "await.".to_string(),
1287 Applicability::MaybeIncorrect,
1292 fn suggest_use_candidates(
1294 err: &mut DiagnosticBuilder<'_>,
1296 candidates: Vec<DefId>,
1298 let parent_map = self.tcx.visible_parent_map(());
1300 // Separate out candidates that must be imported with a glob, because they are named `_`
1301 // and cannot be referred with their identifier.
1302 let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
1303 if let Some(parent_did) = parent_map.get(trait_did) {
1304 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1305 if Some(*parent_did) != self.tcx.parent(*trait_did)
1308 .module_children(*parent_did)
1310 .filter(|child| child.res.opt_def_id() == Some(*trait_did))
1311 .all(|child| child.ident.name == kw::Underscore)
1320 let module_did = self.tcx.parent_module(self.body_id);
1321 let (span, found_use) = find_use_placement(self.tcx, module_did);
1322 if let Some(span) = span {
1323 let path_strings = candidates.iter().map(|trait_did| {
1324 // Produce an additional newline to separate the new use statement
1325 // from the directly following item.
1326 let additional_newline = if found_use { "" } else { "\n" };
1329 with_crate_prefix(|| self.tcx.def_path_str(*trait_did)),
1334 let glob_path_strings = globs.iter().map(|trait_did| {
1335 let parent_did = parent_map.get(trait_did).unwrap();
1337 // Produce an additional newline to separate the new use statement
1338 // from the directly following item.
1339 let additional_newline = if found_use { "" } else { "\n" };
1341 "use {}::*; // trait {}\n{}",
1342 with_crate_prefix(|| self.tcx.def_path_str(*parent_did)),
1343 self.tcx.item_name(*trait_did),
1348 err.span_suggestions(
1351 path_strings.chain(glob_path_strings),
1352 Applicability::MaybeIncorrect,
1355 let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 };
1356 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
1357 if candidates.len() + globs.len() > 1 {
1358 msg.push_str(&format!(
1359 "\ncandidate #{}: `use {};`",
1361 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1364 msg.push_str(&format!(
1366 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1370 for (i, trait_did) in
1371 globs.iter().take(limit.saturating_sub(candidates.len())).enumerate()
1373 let parent_did = parent_map.get(trait_did).unwrap();
1375 if candidates.len() + globs.len() > 1 {
1376 msg.push_str(&format!(
1377 "\ncandidate #{}: `use {}::*; // trait {}`",
1378 candidates.len() + i + 1,
1379 with_crate_prefix(|| self.tcx.def_path_str(*parent_did)),
1380 self.tcx.item_name(*trait_did),
1383 msg.push_str(&format!(
1384 "\n`use {}::*; // trait {}`",
1385 with_crate_prefix(|| self.tcx.def_path_str(*parent_did)),
1386 self.tcx.item_name(*trait_did),
1390 if candidates.len() > limit {
1391 msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit));
1397 fn suggest_valid_traits(
1399 err: &mut DiagnosticBuilder<'_>,
1400 valid_out_of_scope_traits: Vec<DefId>,
1402 if !valid_out_of_scope_traits.is_empty() {
1403 let mut candidates = valid_out_of_scope_traits;
1407 // `TryFrom` and `FromIterator` have no methods
1408 let edition_fix = candidates
1410 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1413 err.help("items from traits can only be used if the trait is in scope");
1415 "the following {traits_are} implemented but not in scope; \
1416 perhaps add a `use` for {one_of_them}:",
1417 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1418 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1421 self.suggest_use_candidates(err, msg, candidates);
1422 if let Some(did) = edition_fix {
1424 "'{}' is included in the prelude starting in Edition 2021",
1425 with_crate_prefix(|| self.tcx.def_path_str(did))
1435 fn suggest_traits_to_import(
1437 err: &mut DiagnosticBuilder<'_>,
1441 source: SelfSource<'tcx>,
1442 valid_out_of_scope_traits: Vec<DefId>,
1443 unsatisfied_predicates: &[(
1444 ty::Predicate<'tcx>,
1445 Option<ty::Predicate<'tcx>>,
1446 Option<ObligationCause<'tcx>>,
1448 unsatisfied_bounds: bool,
1450 let mut alt_rcvr_sugg = false;
1451 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1452 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1454 self.tcx.lang_items().clone_trait(),
1455 self.tcx.lang_items().deref_trait(),
1456 self.tcx.lang_items().deref_mut_trait(),
1457 self.tcx.lang_items().drop_trait(),
1458 self.tcx.get_diagnostic_item(sym::AsRef),
1460 // Try alternative arbitrary self types that could fulfill this call.
1461 // FIXME: probe for all types that *could* be arbitrary self-types, not
1463 for (rcvr_ty, post) in &[
1465 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
1466 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
1468 if let Ok(pick) = self.lookup_probe(
1473 crate::check::method::probe::ProbeScope::AllTraits,
1475 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1476 // We point at the method, but we just skip the rest of the check for arbitrary
1477 // self types and rely on the suggestion to `use` the trait from
1478 // `suggest_valid_traits`.
1479 let did = Some(pick.item.container.id());
1480 let skip = skippable.contains(&did);
1481 if pick.autoderefs == 0 && !skip {
1483 pick.item.ident(self.tcx).span,
1484 &format!("the method is available for `{}` here", rcvr_ty),
1489 for (rcvr_ty, pre) in &[
1490 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
1491 (self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),
1492 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
1493 (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
1495 if let Some(new_rcvr_t) = *rcvr_ty {
1496 if let Ok(pick) = self.lookup_probe(
1501 crate::check::method::probe::ProbeScope::AllTraits,
1503 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1504 let did = Some(pick.item.container.id());
1505 // We don't want to suggest a container type when the missing
1506 // method is `.clone()` or `.deref()` otherwise we'd suggest
1507 // `Arc::new(foo).clone()`, which is far from what the user wants.
1508 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1509 // implement the `AsRef` trait.
1510 let skip = skippable.contains(&did)
1511 || (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
1512 // Make sure the method is defined for the *actual* receiver: we don't
1513 // want to treat `Box<Self>` as a receiver if it only works because of
1514 // an autoderef to `&self`
1515 if pick.autoderefs == 0 && !skip {
1517 pick.item.ident(self.tcx).span,
1518 &format!("the method is available for `{}` here", new_rcvr_t),
1520 err.multipart_suggestion(
1521 "consider wrapping the receiver expression with the \
1524 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1525 (rcvr.span.shrink_to_hi(), ")".to_string()),
1527 Applicability::MaybeIncorrect,
1529 // We don't care about the other suggestions.
1530 alt_rcvr_sugg = true;
1537 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1541 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1543 let mut arbitrary_rcvr = vec![];
1544 // There are no traits implemented, so lets suggest some traits to
1545 // implement, by finding ones that have the item name, and are
1546 // legal to implement.
1547 let mut candidates = all_traits(self.tcx)
1549 // Don't issue suggestions for unstable traits since they're
1550 // unlikely to be implementable anyway
1551 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1552 Some(attr) => attr.level.is_stable(),
1556 // We approximate the coherence rules to only suggest
1557 // traits that are legal to implement by requiring that
1558 // either the type or trait is local. Multi-dispatch means
1559 // this isn't perfect (that is, there are cases when
1560 // implementing a trait would be legal but is rejected
1562 unsatisfied_predicates.iter().all(|(p, _, _)| {
1563 match p.kind().skip_binder() {
1564 // Hide traits if they are present in predicates as they can be fixed without
1565 // having to implement them.
1566 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1567 ty::PredicateKind::Projection(p) => {
1568 p.projection_ty.item_def_id == info.def_id
1572 }) && (type_is_local || info.def_id.is_local())
1574 .associated_value(info.def_id, item_name)
1576 if let ty::AssocKind::Fn = item.kind {
1580 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1581 if let Some(hir::Node::TraitItem(hir::TraitItem {
1582 kind: hir::TraitItemKind::Fn(fn_sig, method),
1584 })) = id.map(|id| self.tcx.hir().get(id))
1586 let self_first_arg = match method {
1587 hir::TraitFn::Required([ident, ..]) => {
1588 ident.name == kw::SelfLower
1590 hir::TraitFn::Provided(body_id) => {
1591 self.tcx.hir().body(*body_id).params.first().map_or(
1596 hir::PatKind::Binding(_, _, ident, _)
1597 if ident.name == kw::SelfLower
1605 if !fn_sig.decl.implicit_self.has_implicit_self()
1608 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1609 arbitrary_rcvr.push(ty.span);
1615 // We only want to suggest public or local traits (#45781).
1616 item.vis.is_public() || info.def_id.is_local()
1620 .collect::<Vec<_>>();
1621 for span in &arbitrary_rcvr {
1624 "the method might not be found because of this arbitrary self type",
1631 if !candidates.is_empty() {
1632 // Sort from most relevant to least relevant.
1633 candidates.sort_by(|a, b| a.cmp(b).reverse());
1636 let param_type = match rcvr_ty.kind() {
1637 ty::Param(param) => Some(param),
1638 ty::Ref(_, ty, _) => match ty.kind() {
1639 ty::Param(param) => Some(param),
1644 err.help(if param_type.is_some() {
1645 "items from traits can only be used if the type parameter is bounded by the trait"
1647 "items from traits can only be used if the trait is implemented and in scope"
1649 let candidates_len = candidates.len();
1650 let message = |action| {
1652 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1655 if candidates_len == 1 { "trait defines" } else { "traits define" },
1657 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1661 // Obtain the span for `param` and use it for a structured suggestion.
1662 if let (Some(param), Some(table)) = (param_type, self.in_progress_typeck_results) {
1663 let table_owner = table.borrow().hir_owner;
1664 let generics = self.tcx.generics_of(table_owner.to_def_id());
1665 let type_param = generics.type_param(param, self.tcx);
1666 let hir = self.tcx.hir();
1667 if let Some(def_id) = type_param.def_id.as_local() {
1668 let id = hir.local_def_id_to_hir_id(def_id);
1669 // Get the `hir::Param` to verify whether it already has any bounds.
1670 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1671 // instead we suggest `T: Foo + Bar` in that case.
1673 Node::GenericParam(param) => {
1674 let mut impl_trait = false;
1676 if let hir::GenericParamKind::Type { synthetic: true, .. } =
1679 // We've found `fn foo(x: impl Trait)` instead of
1680 // `fn foo<T>(x: T)`. We want to suggest the correct
1681 // `fn foo(x: impl Trait + TraitBound)` instead of
1682 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1688 let sp = hir.span(id);
1689 let sp = if let Some(first_bound) = has_bounds {
1690 // `sp` only covers `T`, change it so that it covers
1691 // `T:` when appropriate
1692 sp.until(first_bound.span())
1696 let trait_def_ids: FxHashSet<DefId> = param
1699 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1701 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1702 err.span_suggestions(
1705 "restrict type parameter `{}` with",
1708 candidates.iter().map(|t| {
1712 if impl_trait { " +" } else { ":" },
1713 self.tcx.def_path_str(t.def_id),
1714 if has_bounds.is_some() { " + " } else { "" },
1717 Applicability::MaybeIncorrect,
1722 Node::Item(hir::Item {
1723 kind: hir::ItemKind::Trait(.., bounds, _),
1727 let (sp, sep, article) = if bounds.is_empty() {
1728 (ident.span.shrink_to_hi(), ":", "a")
1730 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1732 err.span_suggestions(
1734 &message(format!("add {} supertrait for", article)),
1735 candidates.iter().map(|t| {
1736 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1738 Applicability::MaybeIncorrect,
1747 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1748 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1749 // cases where a positive bound implies a negative impl.
1750 (candidates, Vec::new())
1751 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes)
1753 let mut potential_candidates = Vec::new();
1754 let mut explicitly_negative = Vec::new();
1755 for candidate in candidates {
1756 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1759 .all_impls(candidate.def_id)
1761 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1764 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1766 simplify_type(self.tcx, imp.self_ty(), SimplifyParams::Yes);
1767 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1770 explicitly_negative.push(candidate);
1772 potential_candidates.push(candidate);
1775 (potential_candidates, explicitly_negative)
1777 // We don't know enough about `recv_ty` to make proper suggestions.
1778 (candidates, Vec::new())
1781 let action = if let Some(param) = param_type {
1782 format!("restrict type parameter `{}` with", param)
1784 // FIXME: it might only need to be imported into scope, not implemented.
1785 "implement".to_string()
1787 match &potential_candidates[..] {
1789 [trait_info] if trait_info.def_id.is_local() => {
1790 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1792 self.tcx.sess.source_map().guess_head_span(span),
1794 "`{}` defines an item `{}`, perhaps you need to {} it",
1795 self.tcx.def_path_str(trait_info.def_id),
1802 let mut msg = message(action);
1803 for (i, trait_info) in trait_infos.iter().enumerate() {
1804 msg.push_str(&format!(
1805 "\ncandidate #{}: `{}`",
1807 self.tcx.def_path_str(trait_info.def_id),
1813 match &explicitly_negative[..] {
1817 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
1818 self.tcx.def_path_str(trait_info.def_id),
1824 let mut msg = format!(
1825 "the following traits define an item `{}`, but are explicitly unimplemented:",
1828 for trait_info in trait_infos {
1829 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1837 /// Checks whether there is a local type somewhere in the chain of
1838 /// autoderefs of `rcvr_ty`.
1839 fn type_derefs_to_local(
1843 source: SelfSource<'tcx>,
1845 fn is_local(ty: Ty<'_>) -> bool {
1847 ty::Adt(def, _) => def.did.is_local(),
1848 ty::Foreign(did) => did.is_local(),
1849 ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1850 ty::Param(_) => true,
1852 // Everything else (primitive types, etc.) is effectively
1853 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1854 // the noise from these sort of types is usually just really
1855 // annoying, rather than any sort of help).
1860 // This occurs for UFCS desugaring of `T::method`, where there is no
1861 // receiver expression for the method call, and thus no autoderef.
1862 if let SelfSource::QPath(_) = source {
1863 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1866 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1870 #[derive(Copy, Clone, Debug)]
1871 pub enum SelfSource<'a> {
1872 QPath(&'a hir::Ty<'a>),
1873 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1876 #[derive(Copy, Clone)]
1877 pub struct TraitInfo {
1881 impl PartialEq for TraitInfo {
1882 fn eq(&self, other: &TraitInfo) -> bool {
1883 self.cmp(other) == Ordering::Equal
1886 impl Eq for TraitInfo {}
1887 impl PartialOrd for TraitInfo {
1888 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1889 Some(self.cmp(other))
1892 impl Ord for TraitInfo {
1893 fn cmp(&self, other: &TraitInfo) -> Ordering {
1894 // Local crates are more important than remote ones (local:
1895 // `cnum == 0`), and otherwise we throw in the defid for totality.
1897 let lhs = (other.def_id.krate, other.def_id);
1898 let rhs = (self.def_id.krate, self.def_id);
1903 /// Retrieves all traits in this crate and any dependent crates,
1904 /// and wraps them into `TraitInfo` for custom sorting.
1905 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1906 tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
1909 fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {
1910 let mut span = None;
1911 let mut found_use = false;
1912 let (module, _, _) = tcx.hir().get_module(target_module);
1914 // Find a `use` statement.
1915 for &item_id in module.item_ids {
1916 let item = tcx.hir().item(item_id);
1918 hir::ItemKind::Use(..) => {
1919 // Don't suggest placing a `use` before the prelude
1920 // import or other generated ones.
1921 if !item.span.from_expansion() {
1922 span = Some(item.span.shrink_to_lo());
1927 // Don't place `use` before `extern crate`...
1928 hir::ItemKind::ExternCrate(_) => {}
1929 // ...but do place them before the first other item.
1931 if span.map_or(true, |span| item.span < span) {
1932 if !item.span.from_expansion() {
1933 span = Some(item.span.shrink_to_lo());
1934 // Don't insert between attributes and an item.
1935 let attrs = tcx.hir().attrs(item.hir_id());
1936 // Find the first attribute on the item.
1937 // FIXME: This is broken for active attributes.
1939 if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) {
1940 span = Some(attr.span.shrink_to_lo());
1952 fn print_disambiguation_help<'tcx>(
1954 args: Option<&'tcx [hir::Expr<'tcx>]>,
1955 err: &mut DiagnosticBuilder<'_>,
1958 kind: ty::AssocKind,
1961 candidate: Option<usize>,
1962 source_map: &source_map::SourceMap,
1963 fn_has_self_parameter: bool,
1965 let mut applicability = Applicability::MachineApplicable;
1966 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1969 if rcvr_ty.is_region_ptr() {
1970 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1975 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1976 applicability = Applicability::HasPlaceholders;
1979 .collect::<Vec<_>>()
1982 let trait_name = if !fn_has_self_parameter {
1983 format!("<{} as {}>", rcvr_ty, trait_name)
1987 (span, format!("{}::{}{}", trait_name, item_name, args))
1989 (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name))
1991 err.span_suggestion_verbose(
1994 "disambiguate the {} for {}",
1995 kind.as_def_kind().descr(def_id),
1996 if let Some(candidate) = candidate {
1997 format!("candidate #{}", candidate)
1999 "the candidate".to_string()