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::{DefKind, Namespace, Res};
9 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
10 use rustc_hir::intravisit;
11 use rustc_hir::lang_items::LangItem;
12 use rustc_hir::{ExprKind, Node, QPath};
13 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
14 use rustc_middle::ty::fast_reject::simplify_type;
15 use rustc_middle::ty::print::with_crate_prefix;
16 use rustc_middle::ty::{
17 self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
19 use rustc_span::lev_distance;
20 use rustc_span::symbol::{kw, sym, Ident};
21 use rustc_span::{source_map, FileName, Span};
22 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
23 use rustc_trait_selection::traits::Obligation;
25 use std::cmp::Ordering;
28 use super::probe::Mode;
29 use super::{CandidateSource, MethodError, NoMatchData};
31 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
35 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
36 // so we look for these beforehand.
37 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
38 // If it's not a simple function, look for things which implement `FnOnce`.
40 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
41 Ok(fn_once) => fn_once,
42 Err(..) => return false,
45 self.autoderef(span, ty).any(|(ty, _)| {
47 let fn_once_substs = tcx.mk_substs_trait(
50 .next_ty_var(TypeVariableOrigin {
51 kind: TypeVariableOriginKind::MiscVariable,
56 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
57 let poly_trait_ref = trait_ref.to_poly_trait_ref();
58 let obligation = Obligation::misc(
62 poly_trait_ref.without_const().to_predicate(tcx),
64 self.predicate_may_hold(&obligation)
71 pub fn report_method_error(
76 source: SelfSource<'tcx>,
77 error: MethodError<'tcx>,
78 args: Option<&'tcx [hir::Expr<'tcx>]>,
79 ) -> 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
102 .associated_item(impl_did, item_name, Namespace::ValueNS)
104 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
105 self.associated_item(
106 impl_trait_ref.def_id,
117 .span_if_local(item.def_id)
118 .or_else(|| self.tcx.hir().span_if_local(impl_did));
120 let impl_ty = self.tcx.at(span).type_of(impl_did);
122 let insertion = match self.tcx.impl_trait_ref(impl_did) {
123 None => String::new(),
124 Some(trait_ref) => format!(
125 " of the trait `{}`",
126 self.tcx.def_path_str(trait_ref.def_id)
130 let (note_str, idx) = if sources.len() > 1 {
133 "candidate #{} is defined in an impl{} for the type `{}`",
143 "the candidate is defined in an impl{} for the type `{}`",
149 if let Some(note_span) = note_span {
150 // We have a span pointing to the method. Show note with snippet.
152 self.tcx.sess.source_map().guess_head_span(note_span),
158 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
159 let path = self.tcx.def_path_str(trait_ref.def_id);
161 let ty = match item.kind {
162 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
163 ty::AssocKind::Fn => self
169 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
173 print_disambiguation_help(
183 self.tcx.sess.source_map(),
187 CandidateSource::TraitSource(trait_did) => {
189 match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
197 .guess_head_span(self.tcx.def_span(item.def_id));
198 let idx = if sources.len() > 1 {
200 "candidate #{} is defined in the trait `{}`",
202 self.tcx.def_path_str(trait_did)
204 err.span_note(item_span, msg);
208 "the candidate is defined in the trait `{}`",
209 self.tcx.def_path_str(trait_did)
211 err.span_note(item_span, msg);
214 let path = self.tcx.def_path_str(trait_did);
215 print_disambiguation_help(
225 self.tcx.sess.source_map(),
230 if sources.len() > limit {
231 err.note(&format!("and {} others", sources.len() - limit));
235 let sugg_span = if let SelfSource::MethodCall(expr) = source {
236 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
237 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
243 MethodError::NoMatch(NoMatchData {
244 static_candidates: static_sources,
245 unsatisfied_predicates,
252 let actual = self.resolve_vars_if_possible(rcvr_ty);
253 let ty_str = self.ty_to_string(actual);
254 let is_method = mode == Mode::MethodCall;
255 let item_kind = if is_method {
257 } else if actual.is_enum() {
258 "variant or associated item"
260 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
261 (Some(name), false) if name.is_lowercase() => "function or associated item",
262 (Some(_), false) => "associated item",
263 (Some(_), true) | (None, false) => "variant or associated item",
264 (None, true) => "variant",
267 let mut err = if !actual.references_error() {
268 // Suggest clamping down the type if the method that is being attempted to
269 // be used exists at all, and the type is an ambiguous numeric type
270 // ({integer}/{float}).
271 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
272 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
274 // There are methods that are defined on the primitive types and won't be
275 // found when exploring `all_traits`, but we also need them to be acurate on
276 // our suggestions (#47759).
277 let fund_assoc = |opt_def_id: Option<DefId>| {
279 .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
282 let lang_items = tcx.lang_items();
283 let found_candidate = candidates.next().is_some()
284 || fund_assoc(lang_items.i8_impl())
285 || fund_assoc(lang_items.i16_impl())
286 || fund_assoc(lang_items.i32_impl())
287 || fund_assoc(lang_items.i64_impl())
288 || fund_assoc(lang_items.i128_impl())
289 || fund_assoc(lang_items.u8_impl())
290 || fund_assoc(lang_items.u16_impl())
291 || fund_assoc(lang_items.u32_impl())
292 || fund_assoc(lang_items.u64_impl())
293 || fund_assoc(lang_items.u128_impl())
294 || fund_assoc(lang_items.f32_impl())
295 || fund_assoc(lang_items.f32_runtime_impl())
296 || fund_assoc(lang_items.f64_impl())
297 || fund_assoc(lang_items.f64_runtime_impl());
298 if let (true, false, SelfSource::MethodCall(expr), true) = (
300 actual.has_concrete_skeleton(),
304 let mut err = struct_span_err!(
308 "can't call {} `{}` on ambiguous numeric type `{}`",
313 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
315 ExprKind::Lit(ref lit) => {
320 .span_to_snippet(lit.span)
321 .unwrap_or_else(|_| "<numeric literal>".to_owned());
326 "you must specify a concrete type for this numeric value, \
330 format!("{}_{}", snippet, concrete_type),
331 Applicability::MaybeIncorrect,
334 ExprKind::Path(ref qpath) => {
336 if let QPath::Resolved(_, path) = qpath {
337 if let hir::def::Res::Local(hir_id) = path.res {
338 let span = tcx.hir().span(hir_id);
339 let snippet = tcx.sess.source_map().span_to_snippet(span);
340 let filename = tcx.sess.source_map().span_to_filename(span);
342 let parent_node = self
345 .get(self.tcx.hir().get_parent_node(hir_id));
347 "you must specify a type for this binding, like `{}`",
351 match (filename, parent_node, snippet) {
354 Node::Local(hir::Local {
355 source: hir::LocalSource::Normal,
362 // account for `let x: _ = 42;`
369 format!("{}: {}", snippet, concrete_type),
370 Applicability::MaybeIncorrect,
374 err.span_label(span, msg);
385 span = item_name.span;
387 // Don't show generic arguments when the method can't be found in any implementation (#81576).
388 let mut ty_str_reported = ty_str.clone();
389 if let ty::Adt(_, ref generics) = actual.kind() {
390 if generics.len() > 0 {
391 let mut autoderef = self.autoderef(span, actual);
392 let candidate_found = autoderef.any(|(ty, _)| {
393 if let ty::Adt(ref adt_deref, _) = ty.kind() {
395 .inherent_impls(adt_deref.did)
397 .filter_map(|def_id| {
398 self.associated_item(
410 let has_deref = autoderef.step_count() > 0;
413 && unsatisfied_predicates.is_empty()
415 if let Some((path_string, _)) = ty_str.split_once('<') {
416 ty_str_reported = path_string.to_string();
422 let mut err = struct_span_err!(
426 "no {} named `{}` found for {} `{}` in the current scope",
429 actual.prefix_string(self.tcx),
432 if let Mode::MethodCall = mode {
433 if let SelfSource::MethodCall(call) = source {
434 self.suggest_await_before_method(
435 &mut err, item_name, actual, call, span,
440 tcx.sess.confused_type_with_std_module.borrow().get(&span)
442 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
445 "you are looking for the module in `std`, \
446 not the primitive type",
447 format!("std::{}", snippet),
448 Applicability::MachineApplicable,
452 if let ty::RawPtr(_) = &actual.kind() {
454 "try using `<*const T>::as_ref()` to get a reference to the \
455 type behind the pointer: https://doc.rust-lang.org/std/\
456 primitive.pointer.html#method.as_ref",
459 "using `<*const T>::as_ref()` on a pointer \
460 which is unaligned or points to invalid \
461 or uninitialized memory is undefined behavior",
467 tcx.sess.diagnostic().struct_dummy()
470 if let Some(def) = actual.ty_adt_def() {
471 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
472 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
476 "{} `{}` not found {}",
479 if def.is_enum() && !is_method { "here" } else { "for this" }
485 let mut label_span_not_found = || {
486 if unsatisfied_predicates.is_empty() {
487 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
488 if let ty::Adt(ref adt, _) = rcvr_ty.kind() {
489 let mut inherent_impls_candidate = self
491 .inherent_impls(adt.did)
496 self.associated_item(*def_id, item_name, Namespace::ValueNS)
498 // Check for both mode is the same so we avoid suggesting
499 // incorrect associated item.
500 match (mode, assoc.fn_has_self_parameter, source) {
501 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
502 // We check that the suggest type is actually
503 // different from the received one
504 // So we avoid suggestion method with Box<Self>
506 self.tcx.at(span).type_of(*def_id) != actual
507 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
509 (Mode::Path, false, _) => true,
516 .collect::<Vec<_>>();
517 if inherent_impls_candidate.len() > 0 {
518 inherent_impls_candidate.sort();
519 inherent_impls_candidate.dedup();
521 // number of type to shows at most.
522 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
523 let type_candidates = inherent_impls_candidate
527 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
531 let additional_types = if inherent_impls_candidate.len() > limit {
533 "\nand {} more types",
534 inherent_impls_candidate.len() - limit
540 "the {item_kind} was found for\n{}{}",
541 type_candidates, additional_types
546 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
548 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
551 // If the method name is the name of a field with a function or closure type,
552 // give a helping note that it has to be called as `(x.f)(...)`.
553 if let SelfSource::MethodCall(expr) = source {
555 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
556 ty::Adt(def, substs) if !def.is_enum() => {
557 let variant = &def.non_enum_variant();
558 self.tcx.find_field_index(item_name, variant).map(|index| {
559 let field = &variant.fields[index];
560 let field_ty = field.ty(tcx, substs);
567 if let Some((field, field_ty)) = field_receiver {
568 let scope = self.tcx.parent_module(self.body_id).to_def_id();
569 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
572 if self.is_fn_ty(&field_ty, span) {
573 let expr_span = expr.span.to(item_name.span);
574 err.multipart_suggestion(
576 "to call the function stored in `{}`, \
577 surround the field access with parentheses",
581 (expr_span.shrink_to_lo(), '('.to_string()),
582 (expr_span.shrink_to_hi(), ')'.to_string()),
584 Applicability::MachineApplicable,
590 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
592 if let Some(span) = call_expr.span.trim_start(item_name.span) {
595 "remove the arguments",
597 Applicability::MaybeIncorrect,
603 let field_kind = if is_accessible { "field" } else { "private field" };
604 err.span_label(item_name.span, format!("{}, not a method", field_kind));
605 } else if lev_candidate.is_none() && static_sources.is_empty() {
606 label_span_not_found();
609 label_span_not_found();
612 if self.is_fn_ty(&rcvr_ty, span) {
613 fn report_function<T: std::fmt::Display>(
614 err: &mut DiagnosticBuilder<'_>,
618 &format!("`{}` is a function, perhaps you wish to call it", name,),
622 if let SelfSource::MethodCall(expr) = source {
623 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
624 report_function(&mut err, expr_string);
625 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
626 if let Some(segment) = path.segments.last() {
627 report_function(&mut err, segment.ident);
633 if !static_sources.is_empty() {
635 "found the following associated functions; to be used as methods, \
636 functions must have a `self` parameter",
638 err.span_label(span, "this is an associated function, not a method");
640 if static_sources.len() == 1 {
641 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
642 static_sources.get(0)
644 // When the "method" is resolved through dereferencing, we really want the
645 // original type that has the associated function for accurate suggestions.
647 let ty = tcx.at(span).type_of(*impl_did);
648 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
649 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
650 // Use `actual` as it will have more `substs` filled in.
651 self.ty_to_value_string(actual.peel_refs())
653 _ => self.ty_to_value_string(ty.peel_refs()),
656 self.ty_to_value_string(actual.peel_refs())
658 if let SelfSource::MethodCall(expr) = source {
661 "use associated function syntax instead",
662 format!("{}::{}", ty_str, item_name),
663 Applicability::MachineApplicable,
666 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
669 report_candidates(span, &mut err, static_sources, sugg_span);
670 } else if static_sources.len() > 1 {
671 report_candidates(span, &mut err, static_sources, sugg_span);
674 let mut restrict_type_params = false;
675 let mut unsatisfied_bounds = false;
676 if !unsatisfied_predicates.is_empty() {
677 let def_span = |def_id| {
678 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
680 let mut type_params = FxHashMap::default();
681 let mut bound_spans = vec![];
683 let mut collect_type_param_suggestions =
684 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
685 // We don't care about regions here, so it's fine to skip the binder here.
686 if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
687 (self_ty.kind(), parent_pred.kind().skip_binder())
689 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
690 let node = def.did.as_local().map(|def_id| {
693 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
695 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
696 if let Some(g) = kind.generics() {
697 let key = match g.where_clause.predicates {
698 [.., pred] => (pred.span().shrink_to_hi(), false),
701 .span_for_predicates_or_empty_place(),
707 .or_insert_with(FxHashSet::default)
708 .insert(obligation.to_owned());
714 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
716 "doesn't satisfy `{}`",
717 if obligation.len() > 50 { quiet } else { obligation }
719 match &self_ty.kind() {
720 // Point at the type that couldn't satisfy the bound.
721 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
722 // Point at the trait object that couldn't satisfy the bound.
723 ty::Dynamic(preds, _) => {
724 for pred in preds.iter() {
725 match pred.skip_binder() {
726 ty::ExistentialPredicate::Trait(tr) => {
727 bound_spans.push((def_span(tr.def_id), msg.clone()))
729 ty::ExistentialPredicate::Projection(_)
730 | ty::ExistentialPredicate::AutoTrait(_) => {}
734 // Point at the closure that couldn't satisfy the bound.
735 ty::Closure(def_id, _) => bound_spans
736 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
740 let mut format_pred = |pred: ty::Predicate<'tcx>| {
741 let bound_predicate = pred.kind();
742 match bound_predicate.skip_binder() {
743 ty::PredicateKind::Projection(pred) => {
744 let pred = bound_predicate.rebind(pred);
745 // `<Foo as Iterator>::Item = String`.
746 let projection_ty = pred.skip_binder().projection_ty;
748 let substs_with_infer_self = tcx.mk_substs(
749 iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
750 .chain(projection_ty.substs.iter().skip(1)),
753 let quiet_projection_ty = ty::ProjectionTy {
754 substs: substs_with_infer_self,
755 item_def_id: projection_ty.item_def_id,
758 let ty = pred.skip_binder().ty;
760 let obligation = format!("{} = {}", projection_ty, ty);
761 let quiet = format!("{} = {}", quiet_projection_ty, ty);
763 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
764 Some((obligation, projection_ty.self_ty()))
766 ty::PredicateKind::Trait(poly_trait_ref, _) => {
767 let p = poly_trait_ref.trait_ref;
768 let self_ty = p.self_ty();
769 let path = p.print_only_trait_path();
770 let obligation = format!("{}: {}", self_ty, path);
771 let quiet = format!("_: {}", path);
772 bound_span_label(self_ty, &obligation, &quiet);
773 Some((obligation, self_ty))
778 let mut bound_list = unsatisfied_predicates
780 .filter_map(|(pred, parent_pred)| {
781 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
782 None => format!("`{}`", &p),
783 Some(parent_pred) => match format_pred(*parent_pred) {
784 None => format!("`{}`", &p),
785 Some((parent_p, _)) => {
786 collect_type_param_suggestions(self_ty, parent_pred, &p);
787 format!("`{}`\nwhich is required by `{}`", p, parent_p)
793 .collect::<Vec<(usize, String)>>();
794 for ((span, empty_where), obligations) in type_params.into_iter() {
795 restrict_type_params = true;
796 // #74886: Sort here so that the output is always the same.
797 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
799 err.span_suggestion_verbose(
802 "consider restricting the type parameter{s} to satisfy the \
804 s = pluralize!(obligations.len())
808 if empty_where { " where" } else { "," },
809 obligations.join(", ")
811 Applicability::MaybeIncorrect,
815 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
816 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
817 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
820 for (span, msg) in bound_spans.into_iter() {
821 err.span_label(span, &msg);
823 if !bound_list.is_empty() {
824 let bound_list = bound_list
826 .map(|(_, path)| path)
829 let actual_prefix = actual.prefix_string(self.tcx);
830 err.set_primary_message(&format!(
831 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
834 "the following trait bounds were not satisfied:\n{bound_list}"
836 unsatisfied_bounds = true;
840 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
842 self.suggest_traits_to_import(
849 &unsatisfied_predicates,
854 // Don't emit a suggestion if we found an actual method
855 // that had unsatisfied trait bounds
856 if unsatisfied_predicates.is_empty() && actual.is_enum() {
857 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
858 if let Some(suggestion) = lev_distance::find_best_match_for_name(
859 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
865 "there is a variant with a similar name",
866 suggestion.to_string(),
867 Applicability::MaybeIncorrect,
872 let mut fallback_span = true;
873 let msg = "remove this method call";
874 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
875 if let SelfSource::MethodCall(expr) = source {
877 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
878 if let Some(span) = call_expr.span.trim_start(expr.span) {
883 Applicability::MachineApplicable,
885 fallback_span = false;
889 err.span_label(span, msg);
891 } else if let Some(lev_candidate) = lev_candidate {
892 // Don't emit a suggestion if we found an actual method
893 // that had unsatisfied trait bounds
894 if unsatisfied_predicates.is_empty() {
895 let def_kind = lev_candidate.kind.as_def_kind();
899 "there is {} {} with a similar name",
901 def_kind.descr(lev_candidate.def_id),
903 lev_candidate.ident.to_string(),
904 Applicability::MaybeIncorrect,
912 MethodError::Ambiguity(sources) => {
913 let mut err = struct_span_err!(
917 "multiple applicable items in scope"
919 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
921 report_candidates(span, &mut err, sources, sugg_span);
925 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
926 let kind = kind.descr(def_id);
927 let mut err = struct_span_err!(
931 "{} `{}` is private",
935 err.span_label(item_name.span, &format!("private {}", kind));
936 self.suggest_valid_traits(&mut err, out_of_scope_traits);
940 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
941 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
942 let mut err = self.sess().struct_span_err(span, &msg);
943 err.span_label(bound_span, "this has a `Sized` requirement");
944 if !candidates.is_empty() {
946 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
947 add a `use` for {one_of_them}:",
948 an = if candidates.len() == 1 { "an" } else { "" },
949 s = pluralize!(candidates.len()),
950 were = if candidates.len() == 1 { "was" } else { "were" },
951 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
953 self.suggest_use_candidates(&mut err, help, candidates);
955 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
957 let trait_type = self.tcx.mk_ref(
959 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
961 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
967 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
972 /// Print out the type for use in value namespace.
973 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
975 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
976 _ => self.ty_to_string(ty),
980 fn suggest_await_before_method(
982 err: &mut DiagnosticBuilder<'_>,
985 call: &hir::Expr<'_>,
988 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
989 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
992 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
993 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
995 err.span_suggestion_verbose(
997 "consider `await`ing on the `Future` and calling the method on its `Output`",
998 "await.".to_string(),
999 Applicability::MaybeIncorrect,
1004 fn suggest_use_candidates(
1006 err: &mut DiagnosticBuilder<'_>,
1008 candidates: Vec<DefId>,
1010 let module_did = self.tcx.parent_module(self.body_id);
1011 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
1012 let krate = self.tcx.hir().krate();
1013 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
1014 if let Some(span) = span {
1015 let path_strings = candidates.iter().map(|did| {
1016 // Produce an additional newline to separate the new use statement
1017 // from the directly following item.
1018 let additional_newline = if found_use { "" } else { "\n" };
1021 with_crate_prefix(|| self.tcx.def_path_str(*did)),
1026 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
1028 let limit = if candidates.len() == 5 { 5 } else { 4 };
1029 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
1030 if candidates.len() > 1 {
1031 msg.push_str(&format!(
1032 "\ncandidate #{}: `use {};`",
1034 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1037 msg.push_str(&format!(
1039 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1043 if candidates.len() > limit {
1044 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
1050 fn suggest_valid_traits(
1052 err: &mut DiagnosticBuilder<'_>,
1053 valid_out_of_scope_traits: Vec<DefId>,
1055 if !valid_out_of_scope_traits.is_empty() {
1056 let mut candidates = valid_out_of_scope_traits;
1059 err.help("items from traits can only be used if the trait is in scope");
1061 "the following {traits_are} implemented but not in scope; \
1062 perhaps add a `use` for {one_of_them}:",
1063 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1064 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1067 self.suggest_use_candidates(err, msg, candidates);
1074 fn suggest_traits_to_import(
1076 err: &mut DiagnosticBuilder<'_>,
1080 source: SelfSource<'tcx>,
1081 valid_out_of_scope_traits: Vec<DefId>,
1082 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
1083 unsatisfied_bounds: bool,
1085 let mut alt_rcvr_sugg = false;
1086 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1087 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1089 self.tcx.lang_items().clone_trait(),
1090 self.tcx.lang_items().deref_trait(),
1091 self.tcx.lang_items().deref_mut_trait(),
1092 self.tcx.lang_items().drop_trait(),
1094 // Try alternative arbitrary self types that could fulfill this call.
1095 // FIXME: probe for all types that *could* be arbitrary self-types, not
1097 for (rcvr_ty, post) in &[
1099 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
1100 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
1102 if let Ok(pick) = self.lookup_probe(
1107 crate::check::method::probe::ProbeScope::AllTraits,
1109 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1110 // We point at the method, but we just skip the rest of the check for arbitrary
1111 // self types and rely on the suggestion to `use` the trait from
1112 // `suggest_valid_traits`.
1113 let did = Some(pick.item.container.id());
1114 let skip = skippable.contains(&did);
1115 if pick.autoderefs == 0 && !skip {
1117 pick.item.ident.span,
1118 &format!("the method is available for `{}` here", rcvr_ty),
1123 for (rcvr_ty, pre) in &[
1124 (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1125 (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1126 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1127 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1129 if let Some(new_rcvr_t) = *rcvr_ty {
1130 if let Ok(pick) = self.lookup_probe(
1135 crate::check::method::probe::ProbeScope::AllTraits,
1137 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1138 let did = Some(pick.item.container.id());
1139 // We don't want to suggest a container type when the missing
1140 // method is `.clone()` or `.deref()` otherwise we'd suggest
1141 // `Arc::new(foo).clone()`, which is far from what the user wants.
1142 let skip = skippable.contains(&did);
1143 // Make sure the method is defined for the *actual* receiver: we don't
1144 // want to treat `Box<Self>` as a receiver if it only works because of
1145 // an autoderef to `&self`
1146 if pick.autoderefs == 0 && !skip {
1148 pick.item.ident.span,
1149 &format!("the method is available for `{}` here", new_rcvr_t),
1151 err.multipart_suggestion(
1152 "consider wrapping the receiver expression with the \
1155 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1156 (rcvr.span.shrink_to_hi(), ")".to_string()),
1158 Applicability::MaybeIncorrect,
1160 // We don't care about the other suggestions.
1161 alt_rcvr_sugg = true;
1168 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1172 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1174 let mut arbitrary_rcvr = vec![];
1175 // There are no traits implemented, so lets suggest some traits to
1176 // implement, by finding ones that have the item name, and are
1177 // legal to implement.
1178 let mut candidates = all_traits(self.tcx)
1180 // Don't issue suggestions for unstable traits since they're
1181 // unlikely to be implementable anyway
1182 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1183 Some(attr) => attr.level.is_stable(),
1187 // We approximate the coherence rules to only suggest
1188 // traits that are legal to implement by requiring that
1189 // either the type or trait is local. Multi-dispatch means
1190 // this isn't perfect (that is, there are cases when
1191 // implementing a trait would be legal but is rejected
1193 unsatisfied_predicates.iter().all(|(p, _)| {
1194 match p.kind().skip_binder() {
1195 // Hide traits if they are present in predicates as they can be fixed without
1196 // having to implement them.
1197 ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
1198 ty::PredicateKind::Projection(p) => {
1199 p.projection_ty.item_def_id == info.def_id
1203 }) && (type_is_local || info.def_id.is_local())
1205 .associated_item(info.def_id, item_name, Namespace::ValueNS)
1207 if let ty::AssocKind::Fn = item.kind {
1211 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1212 if let Some(hir::Node::TraitItem(hir::TraitItem {
1213 kind: hir::TraitItemKind::Fn(fn_sig, method),
1215 })) = id.map(|id| self.tcx.hir().get(id))
1217 let self_first_arg = match method {
1218 hir::TraitFn::Required([ident, ..]) => {
1219 ident.name == kw::SelfLower
1221 hir::TraitFn::Provided(body_id) => {
1222 self.tcx.hir().body(*body_id).params.first().map_or(
1227 hir::PatKind::Binding(_, _, ident, _)
1228 if ident.name == kw::SelfLower
1236 if !fn_sig.decl.implicit_self.has_implicit_self()
1239 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1240 arbitrary_rcvr.push(ty.span);
1246 // We only want to suggest public or local traits (#45781).
1247 item.vis == ty::Visibility::Public || info.def_id.is_local()
1251 .collect::<Vec<_>>();
1252 for span in &arbitrary_rcvr {
1255 "the method might not be found because of this arbitrary self type",
1262 if !candidates.is_empty() {
1263 // Sort from most relevant to least relevant.
1264 candidates.sort_by(|a, b| a.cmp(b).reverse());
1267 let param_type = match rcvr_ty.kind() {
1268 ty::Param(param) => Some(param),
1269 ty::Ref(_, ty, _) => match ty.kind() {
1270 ty::Param(param) => Some(param),
1275 err.help(if param_type.is_some() {
1276 "items from traits can only be used if the type parameter is bounded by the trait"
1278 "items from traits can only be used if the trait is implemented and in scope"
1280 let candidates_len = candidates.len();
1281 let message = |action| {
1283 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1286 if candidates_len == 1 { "trait defines" } else { "traits define" },
1288 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1292 // Obtain the span for `param` and use it for a structured suggestion.
1293 if let (Some(ref param), Some(ref table)) =
1294 (param_type, self.in_progress_typeck_results)
1296 let table_owner = table.borrow().hir_owner;
1297 let generics = self.tcx.generics_of(table_owner.to_def_id());
1298 let type_param = generics.type_param(param, self.tcx);
1299 let hir = &self.tcx.hir();
1300 if let Some(def_id) = type_param.def_id.as_local() {
1301 let id = hir.local_def_id_to_hir_id(def_id);
1302 // Get the `hir::Param` to verify whether it already has any bounds.
1303 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1304 // instead we suggest `T: Foo + Bar` in that case.
1306 Node::GenericParam(ref param) => {
1307 let mut impl_trait = false;
1309 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1312 // We've found `fn foo(x: impl Trait)` instead of
1313 // `fn foo<T>(x: T)`. We want to suggest the correct
1314 // `fn foo(x: impl Trait + TraitBound)` instead of
1315 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1321 let sp = hir.span(id);
1322 let sp = if let Some(first_bound) = has_bounds {
1323 // `sp` only covers `T`, change it so that it covers
1324 // `T:` when appropriate
1325 sp.until(first_bound.span())
1329 let trait_def_ids: FxHashSet<DefId> = param
1332 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1334 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1335 err.span_suggestions(
1338 "restrict type parameter `{}` with",
1341 candidates.iter().map(|t| {
1345 if impl_trait { " +" } else { ":" },
1346 self.tcx.def_path_str(t.def_id),
1347 if has_bounds.is_some() { " + " } else { "" },
1350 Applicability::MaybeIncorrect,
1355 Node::Item(hir::Item {
1356 kind: hir::ItemKind::Trait(.., bounds, _),
1360 let (sp, sep, article) = if bounds.is_empty() {
1361 (ident.span.shrink_to_hi(), ":", "a")
1363 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1365 err.span_suggestions(
1367 &message(format!("add {} supertrait for", article)),
1368 candidates.iter().map(|t| {
1369 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1371 Applicability::MaybeIncorrect,
1380 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1381 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1382 // cases where a positive bound implies a negative impl.
1383 (candidates, Vec::new())
1384 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1385 let mut potential_candidates = Vec::new();
1386 let mut explicitly_negative = Vec::new();
1387 for candidate in candidates {
1388 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1391 .all_impls(candidate.def_id)
1393 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1396 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1397 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1398 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1401 explicitly_negative.push(candidate);
1403 potential_candidates.push(candidate);
1406 (potential_candidates, explicitly_negative)
1408 // We don't know enough about `recv_ty` to make proper suggestions.
1409 (candidates, Vec::new())
1412 let action = if let Some(param) = param_type {
1413 format!("restrict type parameter `{}` with", param)
1415 // FIXME: it might only need to be imported into scope, not implemented.
1416 "implement".to_string()
1418 match &potential_candidates[..] {
1420 [trait_info] if trait_info.def_id.is_local() => {
1421 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1423 self.tcx.sess.source_map().guess_head_span(span),
1425 "`{}` defines an item `{}`, perhaps you need to {} it",
1426 self.tcx.def_path_str(trait_info.def_id),
1433 let mut msg = message(action);
1434 for (i, trait_info) in trait_infos.iter().enumerate() {
1435 msg.push_str(&format!(
1436 "\ncandidate #{}: `{}`",
1438 self.tcx.def_path_str(trait_info.def_id),
1444 match &explicitly_negative[..] {
1448 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1449 self.tcx.def_path_str(trait_info.def_id),
1455 let mut msg = format!(
1456 "the following traits define an item `{}`, but are explicitely unimplemented:",
1459 for trait_info in trait_infos {
1460 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1468 /// Checks whether there is a local type somewhere in the chain of
1469 /// autoderefs of `rcvr_ty`.
1470 fn type_derefs_to_local(
1474 source: SelfSource<'tcx>,
1476 fn is_local(ty: Ty<'_>) -> bool {
1478 ty::Adt(def, _) => def.did.is_local(),
1479 ty::Foreign(did) => did.is_local(),
1480 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1481 ty::Param(_) => true,
1483 // Everything else (primitive types, etc.) is effectively
1484 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1485 // the noise from these sort of types is usually just really
1486 // annoying, rather than any sort of help).
1491 // This occurs for UFCS desugaring of `T::method`, where there is no
1492 // receiver expression for the method call, and thus no autoderef.
1493 if let SelfSource::QPath(_) = source {
1494 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1497 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1501 #[derive(Copy, Clone, Debug)]
1502 pub enum SelfSource<'a> {
1503 QPath(&'a hir::Ty<'a>),
1504 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1507 #[derive(Copy, Clone)]
1508 pub struct TraitInfo {
1512 impl PartialEq for TraitInfo {
1513 fn eq(&self, other: &TraitInfo) -> bool {
1514 self.cmp(other) == Ordering::Equal
1517 impl Eq for TraitInfo {}
1518 impl PartialOrd for TraitInfo {
1519 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1520 Some(self.cmp(other))
1523 impl Ord for TraitInfo {
1524 fn cmp(&self, other: &TraitInfo) -> Ordering {
1525 // Local crates are more important than remote ones (local:
1526 // `cnum == 0`), and otherwise we throw in the defid for totality.
1528 let lhs = (other.def_id.krate, other.def_id);
1529 let rhs = (self.def_id.krate, self.def_id);
1534 /// Retrieves all traits in this crate and any dependent crates.
1535 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1536 tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
1539 /// Computes all traits in this crate and any dependent crates.
1540 fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
1541 use hir::itemlikevisit;
1543 let mut traits = vec![];
1547 struct Visitor<'a> {
1548 traits: &'a mut Vec<DefId>,
1551 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1552 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1554 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1555 self.traits.push(i.def_id.to_def_id());
1561 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1563 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1565 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1568 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1572 let mut external_mods = FxHashSet::default();
1573 fn handle_external_res(
1575 traits: &mut Vec<DefId>,
1576 external_mods: &mut FxHashSet<DefId>,
1580 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1581 traits.push(def_id);
1583 Res::Def(DefKind::Mod, def_id) => {
1584 if !external_mods.insert(def_id) {
1587 for child in tcx.item_children(def_id).iter() {
1588 handle_external_res(tcx, traits, external_mods, child.res)
1594 for &cnum in tcx.crates().iter() {
1595 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1596 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1599 tcx.arena.alloc_from_iter(traits)
1602 pub fn provide(providers: &mut ty::query::Providers) {
1603 providers.all_traits = compute_all_traits;
1606 struct UsePlacementFinder<'tcx> {
1607 target_module: hir::HirId,
1613 impl UsePlacementFinder<'tcx> {
1616 krate: &'tcx hir::Crate<'tcx>,
1617 target_module: hir::HirId,
1618 ) -> (Option<Span>, bool) {
1619 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1620 intravisit::walk_crate(&mut finder, krate);
1621 (finder.span, finder.found_use)
1625 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1626 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1627 if self.span.is_some() {
1630 if hir_id != self.target_module {
1631 intravisit::walk_mod(self, module, hir_id);
1634 // Find a `use` statement.
1635 for &item_id in module.item_ids {
1636 let item = self.tcx.hir().item(item_id);
1638 hir::ItemKind::Use(..) => {
1639 // Don't suggest placing a `use` before the prelude
1640 // import or other generated ones.
1641 if !item.span.from_expansion() {
1642 self.span = Some(item.span.shrink_to_lo());
1643 self.found_use = true;
1647 // Don't place `use` before `extern crate`...
1648 hir::ItemKind::ExternCrate(_) => {}
1649 // ...but do place them before the first other item.
1651 if self.span.map_or(true, |span| item.span < span) {
1652 if !item.span.from_expansion() {
1653 // Don't insert between attributes and an item.
1654 let attrs = self.tcx.hir().attrs(item.hir_id());
1655 if attrs.is_empty() {
1656 self.span = Some(item.span.shrink_to_lo());
1658 // Find the first attribute on the item.
1660 if self.span.map_or(true, |span| attr.span < span) {
1661 self.span = Some(attr.span.shrink_to_lo());
1672 type Map = intravisit::ErasedMap<'tcx>;
1674 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1675 intravisit::NestedVisitorMap::None
1679 fn print_disambiguation_help(
1681 args: Option<&'tcx [hir::Expr<'tcx>]>,
1682 err: &mut DiagnosticBuilder<'_>,
1685 kind: ty::AssocKind,
1688 candidate: Option<usize>,
1689 source_map: &source_map::SourceMap,
1691 let mut applicability = Applicability::MachineApplicable;
1692 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1695 if rcvr_ty.is_region_ptr() {
1696 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1701 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1702 applicability = Applicability::HasPlaceholders;
1705 .collect::<Vec<_>>()
1711 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1712 err.span_suggestion(
1715 "disambiguate the {} for {}",
1716 kind.as_def_kind().descr(def_id),
1717 if let Some(candidate) = candidate {
1718 format!("candidate #{}", candidate)
1720 "the candidate".to_string()