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<'_>> {
80 // Avoid suggestions when we don't know what's going on.
81 if rcvr_ty.references_error() {
85 let report_candidates = |span: Span,
86 err: &mut DiagnosticBuilder<'_>,
87 mut sources: Vec<CandidateSource>,
91 // Dynamic limit to avoid hiding just one candidate, which is silly.
92 let limit = if sources.len() == 5 { 5 } else { 4 };
94 for (idx, source) in sources.iter().take(limit).enumerate() {
96 CandidateSource::ImplSource(impl_did) => {
97 // Provide the best span we can. Use the item, if local to crate, else
98 // the impl, if local to crate (item may be defaulted), else nothing.
100 .associated_item(impl_did, item_name, Namespace::ValueNS)
102 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
103 self.associated_item(
104 impl_trait_ref.def_id,
115 .span_if_local(item.def_id)
116 .or_else(|| self.tcx.hir().span_if_local(impl_did));
118 let impl_ty = self.tcx.at(span).type_of(impl_did);
120 let insertion = match self.tcx.impl_trait_ref(impl_did) {
121 None => String::new(),
122 Some(trait_ref) => format!(
123 " of the trait `{}`",
124 self.tcx.def_path_str(trait_ref.def_id)
128 let (note_str, idx) = if sources.len() > 1 {
131 "candidate #{} is defined in an impl{} for the type `{}`",
141 "the candidate is defined in an impl{} for the type `{}`",
147 if let Some(note_span) = note_span {
148 // We have a span pointing to the method. Show note with snippet.
150 self.tcx.sess.source_map().guess_head_span(note_span),
156 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
157 let path = self.tcx.def_path_str(trait_ref.def_id);
159 let ty = match item.kind {
160 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
161 ty::AssocKind::Fn => self
167 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
171 print_disambiguation_help(
181 self.tcx.sess.source_map(),
185 CandidateSource::TraitSource(trait_did) => {
187 match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
195 .guess_head_span(self.tcx.def_span(item.def_id));
196 let idx = if sources.len() > 1 {
198 "candidate #{} is defined in the trait `{}`",
200 self.tcx.def_path_str(trait_did)
202 err.span_note(item_span, msg);
206 "the candidate is defined in the trait `{}`",
207 self.tcx.def_path_str(trait_did)
209 err.span_note(item_span, msg);
212 let path = self.tcx.def_path_str(trait_did);
213 print_disambiguation_help(
223 self.tcx.sess.source_map(),
228 if sources.len() > limit {
229 err.note(&format!("and {} others", sources.len() - limit));
233 let sugg_span = if let SelfSource::MethodCall(expr) = source {
234 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
235 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
241 MethodError::NoMatch(NoMatchData {
242 static_candidates: static_sources,
243 unsatisfied_predicates,
250 let actual = self.resolve_vars_if_possible(rcvr_ty);
251 let ty_str = self.ty_to_string(actual);
252 let is_method = mode == Mode::MethodCall;
253 let item_kind = if is_method {
255 } else if actual.is_enum() {
256 "variant or associated item"
258 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
259 (Some(name), false) if name.is_lowercase() => "function or associated item",
260 (Some(_), false) => "associated item",
261 (Some(_), true) | (None, false) => "variant or associated item",
262 (None, true) => "variant",
265 let mut err = if !actual.references_error() {
266 // Suggest clamping down the type if the method that is being attempted to
267 // be used exists at all, and the type is an ambiguous numeric type
268 // ({integer}/{float}).
269 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
270 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
272 // There are methods that are defined on the primitive types and won't be
273 // found when exploring `all_traits`, but we also need them to be acurate on
274 // our suggestions (#47759).
275 let fund_assoc = |opt_def_id: Option<DefId>| {
277 .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
280 let lang_items = tcx.lang_items();
281 let found_candidate = candidates.next().is_some()
282 || fund_assoc(lang_items.i8_impl())
283 || fund_assoc(lang_items.i16_impl())
284 || fund_assoc(lang_items.i32_impl())
285 || fund_assoc(lang_items.i64_impl())
286 || fund_assoc(lang_items.i128_impl())
287 || fund_assoc(lang_items.u8_impl())
288 || fund_assoc(lang_items.u16_impl())
289 || fund_assoc(lang_items.u32_impl())
290 || fund_assoc(lang_items.u64_impl())
291 || fund_assoc(lang_items.u128_impl())
292 || fund_assoc(lang_items.f32_impl())
293 || fund_assoc(lang_items.f32_runtime_impl())
294 || fund_assoc(lang_items.f64_impl())
295 || fund_assoc(lang_items.f64_runtime_impl());
296 if let (true, false, SelfSource::MethodCall(expr), true) = (
298 actual.has_concrete_skeleton(),
302 let mut err = struct_span_err!(
306 "can't call {} `{}` on ambiguous numeric type `{}`",
311 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
313 ExprKind::Lit(ref lit) => {
318 .span_to_snippet(lit.span)
319 .unwrap_or_else(|_| "<numeric literal>".to_owned());
324 "you must specify a concrete type for this numeric value, \
328 format!("{}_{}", snippet, concrete_type),
329 Applicability::MaybeIncorrect,
332 ExprKind::Path(ref qpath) => {
334 if let QPath::Resolved(_, path) = qpath {
335 if let hir::def::Res::Local(hir_id) = path.res {
336 let span = tcx.hir().span(hir_id);
337 let snippet = tcx.sess.source_map().span_to_snippet(span);
338 let filename = tcx.sess.source_map().span_to_filename(span);
340 let parent_node = self
343 .get(self.tcx.hir().get_parent_node(hir_id));
345 "you must specify a type for this binding, like `{}`",
349 match (filename, parent_node, snippet) {
352 Node::Local(hir::Local {
353 source: hir::LocalSource::Normal,
360 // account for `let x: _ = 42;`
367 format!("{}: {}", snippet, concrete_type),
368 Applicability::MaybeIncorrect,
372 err.span_label(span, msg);
383 span = item_name.span;
385 // Don't show generic arguments when the method can't be found in any implementation (#81576).
386 let mut ty_str_reported = ty_str.clone();
387 if let ty::Adt(_, ref generics) = actual.kind() {
388 if generics.len() > 0 {
389 let mut autoderef = self.autoderef(span, actual);
390 let candidate_found = autoderef.any(|(ty, _)| {
391 if let ty::Adt(ref adt_deref, _) = ty.kind() {
393 .inherent_impls(adt_deref.did)
395 .filter_map(|def_id| {
396 self.associated_item(
408 let has_deref = autoderef.step_count() > 0;
411 && unsatisfied_predicates.is_empty()
413 if let Some((path_string, _)) = ty_str.split_once('<') {
414 ty_str_reported = path_string.to_string();
420 let mut err = struct_span_err!(
424 "no {} named `{}` found for {} `{}` in the current scope",
427 actual.prefix_string(self.tcx),
430 if let Mode::MethodCall = mode {
431 if let SelfSource::MethodCall(call) = source {
432 self.suggest_await_before_method(
433 &mut err, item_name, actual, call, span,
438 tcx.sess.confused_type_with_std_module.borrow().get(&span)
440 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
443 "you are looking for the module in `std`, \
444 not the primitive type",
445 format!("std::{}", snippet),
446 Applicability::MachineApplicable,
450 if let ty::RawPtr(_) = &actual.kind() {
452 "try using `<*const T>::as_ref()` to get a reference to the \
453 type behind the pointer: https://doc.rust-lang.org/std/\
454 primitive.pointer.html#method.as_ref",
457 "using `<*const T>::as_ref()` on a pointer \
458 which is unaligned or points to invalid \
459 or uninitialized memory is undefined behavior",
465 tcx.sess.diagnostic().struct_dummy()
468 if let Some(def) = actual.ty_adt_def() {
469 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
470 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
474 "{} `{}` not found {}",
477 if def.is_enum() && !is_method { "here" } else { "for this" }
483 let mut label_span_not_found = || {
484 if unsatisfied_predicates.is_empty() {
485 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
486 if let ty::Adt(ref adt, _) = rcvr_ty.kind() {
487 let mut inherent_impls_candidate = self
489 .inherent_impls(adt.did)
494 self.associated_item(*def_id, item_name, Namespace::ValueNS)
496 // Check for both mode is the same so we avoid suggesting
497 // incorrect associated item.
498 match (mode, assoc.fn_has_self_parameter, source) {
499 (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
500 // We check that the suggest type is actually
501 // different from the received one
502 // So we avoid suggestion method with Box<Self>
504 self.tcx.at(span).type_of(*def_id) != actual
505 && self.tcx.at(span).type_of(*def_id) != rcvr_ty
507 (Mode::Path, false, _) => true,
514 .collect::<Vec<_>>();
515 if inherent_impls_candidate.len() > 0 {
516 inherent_impls_candidate.sort();
517 inherent_impls_candidate.dedup();
519 // number of type to shows at most.
520 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
521 let type_candidates = inherent_impls_candidate
525 format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
529 let additional_types = if inherent_impls_candidate.len() > limit {
531 "\nand {} more types",
532 inherent_impls_candidate.len() - limit
538 "the {item_kind} was found for\n{}{}",
539 type_candidates, additional_types
544 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
548 // If the method name is the name of a field with a function or closure type,
549 // give a helping note that it has to be called as `(x.f)(...)`.
550 if let SelfSource::MethodCall(expr) = source {
552 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
553 ty::Adt(def, substs) if !def.is_enum() => {
554 let variant = &def.non_enum_variant();
555 self.tcx.find_field_index(item_name, variant).map(|index| {
556 let field = &variant.fields[index];
557 let field_ty = field.ty(tcx, substs);
564 if let Some((field, field_ty)) = field_receiver {
565 let scope = self.tcx.parent_module(self.body_id).to_def_id();
566 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
569 if self.is_fn_ty(&field_ty, span) {
570 let expr_span = expr.span.to(item_name.span);
571 err.multipart_suggestion(
573 "to call the function stored in `{}`, \
574 surround the field access with parentheses",
578 (expr_span.shrink_to_lo(), '('.to_string()),
579 (expr_span.shrink_to_hi(), ')'.to_string()),
581 Applicability::MachineApplicable,
587 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
589 if let Some(span) = call_expr.span.trim_start(item_name.span) {
592 "remove the arguments",
594 Applicability::MaybeIncorrect,
600 let field_kind = if is_accessible { "field" } else { "private field" };
601 err.span_label(item_name.span, format!("{}, not a method", field_kind));
602 } else if lev_candidate.is_none() && static_sources.is_empty() {
603 label_span_not_found();
606 label_span_not_found();
609 if self.is_fn_ty(&rcvr_ty, span) {
610 fn report_function<T: std::fmt::Display>(
611 err: &mut DiagnosticBuilder<'_>,
615 &format!("`{}` is a function, perhaps you wish to call it", name,),
619 if let SelfSource::MethodCall(expr) = source {
620 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
621 report_function(&mut err, expr_string);
622 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
623 if let Some(segment) = path.segments.last() {
624 report_function(&mut err, segment.ident);
630 if !static_sources.is_empty() {
632 "found the following associated functions; to be used as methods, \
633 functions must have a `self` parameter",
635 err.span_label(span, "this is an associated function, not a method");
637 if static_sources.len() == 1 {
638 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
639 static_sources.get(0)
641 // When the "method" is resolved through dereferencing, we really want the
642 // original type that has the associated function for accurate suggestions.
644 let ty = tcx.at(span).type_of(*impl_did);
645 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
646 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
647 // Use `actual` as it will have more `substs` filled in.
648 self.ty_to_value_string(actual.peel_refs())
650 _ => self.ty_to_value_string(ty.peel_refs()),
653 self.ty_to_value_string(actual.peel_refs())
655 if let SelfSource::MethodCall(expr) = source {
658 "use associated function syntax instead",
659 format!("{}::{}", ty_str, item_name),
660 Applicability::MachineApplicable,
663 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
666 report_candidates(span, &mut err, static_sources, sugg_span);
667 } else if static_sources.len() > 1 {
668 report_candidates(span, &mut err, static_sources, sugg_span);
671 let mut restrict_type_params = false;
672 let mut unsatisfied_bounds = false;
673 if !unsatisfied_predicates.is_empty() {
674 let def_span = |def_id| {
675 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
677 let mut type_params = FxHashMap::default();
678 let mut bound_spans = vec![];
680 let mut collect_type_param_suggestions =
681 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
682 // We don't care about regions here, so it's fine to skip the binder here.
683 if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
684 (self_ty.kind(), parent_pred.kind().skip_binder())
686 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
687 let node = def.did.as_local().map(|def_id| {
690 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
692 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
693 if let Some(g) = kind.generics() {
694 let key = match g.where_clause.predicates {
695 [.., pred] => (pred.span().shrink_to_hi(), false),
698 .span_for_predicates_or_empty_place(),
704 .or_insert_with(FxHashSet::default)
705 .insert(obligation.to_owned());
711 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
713 "doesn't satisfy `{}`",
714 if obligation.len() > 50 { quiet } else { obligation }
716 match &self_ty.kind() {
717 // Point at the type that couldn't satisfy the bound.
718 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
719 // Point at the trait object that couldn't satisfy the bound.
720 ty::Dynamic(preds, _) => {
721 for pred in preds.iter() {
722 match pred.skip_binder() {
723 ty::ExistentialPredicate::Trait(tr) => {
724 bound_spans.push((def_span(tr.def_id), msg.clone()))
726 ty::ExistentialPredicate::Projection(_)
727 | ty::ExistentialPredicate::AutoTrait(_) => {}
731 // Point at the closure that couldn't satisfy the bound.
732 ty::Closure(def_id, _) => bound_spans
733 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
737 let mut format_pred = |pred: ty::Predicate<'tcx>| {
738 let bound_predicate = pred.kind();
739 match bound_predicate.skip_binder() {
740 ty::PredicateKind::Projection(pred) => {
741 let pred = bound_predicate.rebind(pred);
742 // `<Foo as Iterator>::Item = String`.
743 let projection_ty = pred.skip_binder().projection_ty;
745 let substs_with_infer_self = tcx.mk_substs(
746 iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
747 .chain(projection_ty.substs.iter().skip(1)),
750 let quiet_projection_ty = ty::ProjectionTy {
751 substs: substs_with_infer_self,
752 item_def_id: projection_ty.item_def_id,
755 let ty = pred.skip_binder().ty;
757 let obligation = format!("{} = {}", projection_ty, ty);
758 let quiet = format!("{} = {}", quiet_projection_ty, ty);
760 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
761 Some((obligation, projection_ty.self_ty()))
763 ty::PredicateKind::Trait(poly_trait_ref) => {
764 let p = poly_trait_ref.trait_ref;
765 let self_ty = p.self_ty();
766 let path = p.print_only_trait_path();
767 let obligation = format!("{}: {}", self_ty, path);
768 let quiet = format!("_: {}", path);
769 bound_span_label(self_ty, &obligation, &quiet);
770 Some((obligation, self_ty))
775 let mut bound_list = unsatisfied_predicates
777 .filter_map(|(pred, parent_pred)| {
778 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
779 None => format!("`{}`", &p),
780 Some(parent_pred) => match format_pred(*parent_pred) {
781 None => format!("`{}`", &p),
782 Some((parent_p, _)) => {
783 collect_type_param_suggestions(self_ty, parent_pred, &p);
784 format!("`{}`\nwhich is required by `{}`", p, parent_p)
790 .collect::<Vec<(usize, String)>>();
791 for ((span, empty_where), obligations) in type_params.into_iter() {
792 restrict_type_params = true;
793 // #74886: Sort here so that the output is always the same.
794 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
796 err.span_suggestion_verbose(
799 "consider restricting the type parameter{s} to satisfy the \
801 s = pluralize!(obligations.len())
805 if empty_where { " where" } else { "," },
806 obligations.join(", ")
808 Applicability::MaybeIncorrect,
812 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
813 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
814 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
817 for (span, msg) in bound_spans.into_iter() {
818 err.span_label(span, &msg);
820 if !bound_list.is_empty() {
821 let bound_list = bound_list
823 .map(|(_, path)| path)
826 let actual_prefix = actual.prefix_string(self.tcx);
827 err.set_primary_message(&format!(
828 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
831 "the following trait bounds were not satisfied:\n{bound_list}"
833 unsatisfied_bounds = true;
837 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
839 self.suggest_traits_to_import(
846 &unsatisfied_predicates,
851 // Don't emit a suggestion if we found an actual method
852 // that had unsatisfied trait bounds
853 if unsatisfied_predicates.is_empty() && actual.is_enum() {
854 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
855 if let Some(suggestion) = lev_distance::find_best_match_for_name(
856 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
862 "there is a variant with a similar name",
863 suggestion.to_string(),
864 Applicability::MaybeIncorrect,
869 let mut fallback_span = true;
870 let msg = "remove this method call";
871 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
872 if let SelfSource::MethodCall(expr) = source {
874 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
875 if let Some(span) = call_expr.span.trim_start(expr.span) {
880 Applicability::MachineApplicable,
882 fallback_span = false;
886 err.span_label(span, msg);
888 } else if let Some(lev_candidate) = lev_candidate {
889 // Don't emit a suggestion if we found an actual method
890 // that had unsatisfied trait bounds
891 if unsatisfied_predicates.is_empty() {
892 let def_kind = lev_candidate.kind.as_def_kind();
896 "there is {} {} with a similar name",
898 def_kind.descr(lev_candidate.def_id),
900 lev_candidate.ident.to_string(),
901 Applicability::MaybeIncorrect,
909 MethodError::Ambiguity(sources) => {
910 let mut err = struct_span_err!(
914 "multiple applicable items in scope"
916 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
918 report_candidates(span, &mut err, sources, sugg_span);
922 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
923 let kind = kind.descr(def_id);
924 let mut err = struct_span_err!(
928 "{} `{}` is private",
932 err.span_label(item_name.span, &format!("private {}", kind));
936 .span_if_local(def_id)
937 .unwrap_or_else(|| self.tcx.def_span(def_id));
938 err.span_label(sp, &format!("private {} defined here", kind));
939 self.suggest_valid_traits(&mut err, out_of_scope_traits);
943 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
944 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
945 let mut err = self.sess().struct_span_err(span, &msg);
946 err.span_label(bound_span, "this has a `Sized` requirement");
947 if !candidates.is_empty() {
949 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
950 add a `use` for {one_of_them}:",
951 an = if candidates.len() == 1 { "an" } else { "" },
952 s = pluralize!(candidates.len()),
953 were = if candidates.len() == 1 { "was" } else { "were" },
954 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
956 self.suggest_use_candidates(&mut err, help, candidates);
958 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
960 let trait_type = self.tcx.mk_ref(
962 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
964 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
970 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
975 /// Print out the type for use in value namespace.
976 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
978 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
979 _ => self.ty_to_string(ty),
983 fn suggest_await_before_method(
985 err: &mut DiagnosticBuilder<'_>,
988 call: &hir::Expr<'_>,
991 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
992 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
995 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
996 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
998 err.span_suggestion_verbose(
1000 "consider `await`ing on the `Future` and calling the method on its `Output`",
1001 "await.".to_string(),
1002 Applicability::MaybeIncorrect,
1007 fn suggest_use_candidates(
1009 err: &mut DiagnosticBuilder<'_>,
1011 candidates: Vec<DefId>,
1013 let module_did = self.tcx.parent_module(self.body_id);
1014 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
1015 let (span, found_use) = UsePlacementFinder::check(self.tcx, module_id);
1016 if let Some(span) = span {
1017 let path_strings = candidates.iter().map(|did| {
1018 // Produce an additional newline to separate the new use statement
1019 // from the directly following item.
1020 let additional_newline = if found_use { "" } else { "\n" };
1023 with_crate_prefix(|| self.tcx.def_path_str(*did)),
1028 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
1030 let limit = if candidates.len() == 5 { 5 } else { 4 };
1031 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
1032 if candidates.len() > 1 {
1033 msg.push_str(&format!(
1034 "\ncandidate #{}: `use {};`",
1036 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1039 msg.push_str(&format!(
1041 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1045 if candidates.len() > limit {
1046 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
1052 fn suggest_valid_traits(
1054 err: &mut DiagnosticBuilder<'_>,
1055 valid_out_of_scope_traits: Vec<DefId>,
1057 if !valid_out_of_scope_traits.is_empty() {
1058 let mut candidates = valid_out_of_scope_traits;
1061 err.help("items from traits can only be used if the trait is in scope");
1063 "the following {traits_are} implemented but not in scope; \
1064 perhaps add a `use` for {one_of_them}:",
1065 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1066 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1069 self.suggest_use_candidates(err, msg, candidates);
1076 fn suggest_traits_to_import(
1078 err: &mut DiagnosticBuilder<'_>,
1082 source: SelfSource<'tcx>,
1083 valid_out_of_scope_traits: Vec<DefId>,
1084 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
1085 unsatisfied_bounds: bool,
1087 let mut alt_rcvr_sugg = false;
1088 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1089 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1091 self.tcx.lang_items().clone_trait(),
1092 self.tcx.lang_items().deref_trait(),
1093 self.tcx.lang_items().deref_mut_trait(),
1094 self.tcx.lang_items().drop_trait(),
1096 // Try alternative arbitrary self types that could fulfill this call.
1097 // FIXME: probe for all types that *could* be arbitrary self-types, not
1099 for (rcvr_ty, post) in &[
1101 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
1102 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
1104 if let Ok(pick) = self.lookup_probe(
1109 crate::check::method::probe::ProbeScope::AllTraits,
1111 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1112 // We point at the method, but we just skip the rest of the check for arbitrary
1113 // self types and rely on the suggestion to `use` the trait from
1114 // `suggest_valid_traits`.
1115 let did = Some(pick.item.container.id());
1116 let skip = skippable.contains(&did);
1117 if pick.autoderefs == 0 && !skip {
1119 pick.item.ident.span,
1120 &format!("the method is available for `{}` here", rcvr_ty),
1125 for (rcvr_ty, pre) in &[
1126 (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1127 (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1128 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1129 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1131 if let Some(new_rcvr_t) = *rcvr_ty {
1132 if let Ok(pick) = self.lookup_probe(
1137 crate::check::method::probe::ProbeScope::AllTraits,
1139 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1140 let did = Some(pick.item.container.id());
1141 // We don't want to suggest a container type when the missing
1142 // method is `.clone()` or `.deref()` otherwise we'd suggest
1143 // `Arc::new(foo).clone()`, which is far from what the user wants.
1144 let skip = skippable.contains(&did);
1145 // Make sure the method is defined for the *actual* receiver: we don't
1146 // want to treat `Box<Self>` as a receiver if it only works because of
1147 // an autoderef to `&self`
1148 if pick.autoderefs == 0 && !skip {
1150 pick.item.ident.span,
1151 &format!("the method is available for `{}` here", new_rcvr_t),
1153 err.multipart_suggestion(
1154 "consider wrapping the receiver expression with the \
1157 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1158 (rcvr.span.shrink_to_hi(), ")".to_string()),
1160 Applicability::MaybeIncorrect,
1162 // We don't care about the other suggestions.
1163 alt_rcvr_sugg = true;
1170 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1174 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1176 let mut arbitrary_rcvr = vec![];
1177 // There are no traits implemented, so lets suggest some traits to
1178 // implement, by finding ones that have the item name, and are
1179 // legal to implement.
1180 let mut candidates = all_traits(self.tcx)
1182 // Don't issue suggestions for unstable traits since they're
1183 // unlikely to be implementable anyway
1184 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1185 Some(attr) => attr.level.is_stable(),
1189 // We approximate the coherence rules to only suggest
1190 // traits that are legal to implement by requiring that
1191 // either the type or trait is local. Multi-dispatch means
1192 // this isn't perfect (that is, there are cases when
1193 // implementing a trait would be legal but is rejected
1195 unsatisfied_predicates.iter().all(|(p, _)| {
1196 match p.kind().skip_binder() {
1197 // Hide traits if they are present in predicates as they can be fixed without
1198 // having to implement them.
1199 ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1200 ty::PredicateKind::Projection(p) => {
1201 p.projection_ty.item_def_id == info.def_id
1205 }) && (type_is_local || info.def_id.is_local())
1207 .associated_item(info.def_id, item_name, Namespace::ValueNS)
1209 if let ty::AssocKind::Fn = item.kind {
1213 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1214 if let Some(hir::Node::TraitItem(hir::TraitItem {
1215 kind: hir::TraitItemKind::Fn(fn_sig, method),
1217 })) = id.map(|id| self.tcx.hir().get(id))
1219 let self_first_arg = match method {
1220 hir::TraitFn::Required([ident, ..]) => {
1221 ident.name == kw::SelfLower
1223 hir::TraitFn::Provided(body_id) => {
1224 self.tcx.hir().body(*body_id).params.first().map_or(
1229 hir::PatKind::Binding(_, _, ident, _)
1230 if ident.name == kw::SelfLower
1238 if !fn_sig.decl.implicit_self.has_implicit_self()
1241 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1242 arbitrary_rcvr.push(ty.span);
1248 // We only want to suggest public or local traits (#45781).
1249 item.vis == ty::Visibility::Public || info.def_id.is_local()
1253 .collect::<Vec<_>>();
1254 for span in &arbitrary_rcvr {
1257 "the method might not be found because of this arbitrary self type",
1264 if !candidates.is_empty() {
1265 // Sort from most relevant to least relevant.
1266 candidates.sort_by(|a, b| a.cmp(b).reverse());
1269 let param_type = match rcvr_ty.kind() {
1270 ty::Param(param) => Some(param),
1271 ty::Ref(_, ty, _) => match ty.kind() {
1272 ty::Param(param) => Some(param),
1277 err.help(if param_type.is_some() {
1278 "items from traits can only be used if the type parameter is bounded by the trait"
1280 "items from traits can only be used if the trait is implemented and in scope"
1282 let candidates_len = candidates.len();
1283 let message = |action| {
1285 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1288 if candidates_len == 1 { "trait defines" } else { "traits define" },
1290 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1294 // Obtain the span for `param` and use it for a structured suggestion.
1295 if let (Some(ref param), Some(ref table)) =
1296 (param_type, self.in_progress_typeck_results)
1298 let table_owner = table.borrow().hir_owner;
1299 let generics = self.tcx.generics_of(table_owner.to_def_id());
1300 let type_param = generics.type_param(param, self.tcx);
1301 let hir = &self.tcx.hir();
1302 if let Some(def_id) = type_param.def_id.as_local() {
1303 let id = hir.local_def_id_to_hir_id(def_id);
1304 // Get the `hir::Param` to verify whether it already has any bounds.
1305 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1306 // instead we suggest `T: Foo + Bar` in that case.
1308 Node::GenericParam(ref param) => {
1309 let mut impl_trait = false;
1311 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1314 // We've found `fn foo(x: impl Trait)` instead of
1315 // `fn foo<T>(x: T)`. We want to suggest the correct
1316 // `fn foo(x: impl Trait + TraitBound)` instead of
1317 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1323 let sp = hir.span(id);
1324 let sp = if let Some(first_bound) = has_bounds {
1325 // `sp` only covers `T`, change it so that it covers
1326 // `T:` when appropriate
1327 sp.until(first_bound.span())
1331 let trait_def_ids: FxHashSet<DefId> = param
1334 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1336 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1337 err.span_suggestions(
1340 "restrict type parameter `{}` with",
1343 candidates.iter().map(|t| {
1347 if impl_trait { " +" } else { ":" },
1348 self.tcx.def_path_str(t.def_id),
1349 if has_bounds.is_some() { " + " } else { "" },
1352 Applicability::MaybeIncorrect,
1357 Node::Item(hir::Item {
1358 kind: hir::ItemKind::Trait(.., bounds, _),
1362 let (sp, sep, article) = if bounds.is_empty() {
1363 (ident.span.shrink_to_hi(), ":", "a")
1365 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1367 err.span_suggestions(
1369 &message(format!("add {} supertrait for", article)),
1370 candidates.iter().map(|t| {
1371 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1373 Applicability::MaybeIncorrect,
1382 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1383 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1384 // cases where a positive bound implies a negative impl.
1385 (candidates, Vec::new())
1386 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1387 let mut potential_candidates = Vec::new();
1388 let mut explicitly_negative = Vec::new();
1389 for candidate in candidates {
1390 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1393 .all_impls(candidate.def_id)
1395 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1398 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1399 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1400 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1403 explicitly_negative.push(candidate);
1405 potential_candidates.push(candidate);
1408 (potential_candidates, explicitly_negative)
1410 // We don't know enough about `recv_ty` to make proper suggestions.
1411 (candidates, Vec::new())
1414 let action = if let Some(param) = param_type {
1415 format!("restrict type parameter `{}` with", param)
1417 // FIXME: it might only need to be imported into scope, not implemented.
1418 "implement".to_string()
1420 match &potential_candidates[..] {
1422 [trait_info] if trait_info.def_id.is_local() => {
1423 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1425 self.tcx.sess.source_map().guess_head_span(span),
1427 "`{}` defines an item `{}`, perhaps you need to {} it",
1428 self.tcx.def_path_str(trait_info.def_id),
1435 let mut msg = message(action);
1436 for (i, trait_info) in trait_infos.iter().enumerate() {
1437 msg.push_str(&format!(
1438 "\ncandidate #{}: `{}`",
1440 self.tcx.def_path_str(trait_info.def_id),
1446 match &explicitly_negative[..] {
1450 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1451 self.tcx.def_path_str(trait_info.def_id),
1457 let mut msg = format!(
1458 "the following traits define an item `{}`, but are explicitely unimplemented:",
1461 for trait_info in trait_infos {
1462 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1470 /// Checks whether there is a local type somewhere in the chain of
1471 /// autoderefs of `rcvr_ty`.
1472 fn type_derefs_to_local(
1476 source: SelfSource<'tcx>,
1478 fn is_local(ty: Ty<'_>) -> bool {
1480 ty::Adt(def, _) => def.did.is_local(),
1481 ty::Foreign(did) => did.is_local(),
1482 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1483 ty::Param(_) => true,
1485 // Everything else (primitive types, etc.) is effectively
1486 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1487 // the noise from these sort of types is usually just really
1488 // annoying, rather than any sort of help).
1493 // This occurs for UFCS desugaring of `T::method`, where there is no
1494 // receiver expression for the method call, and thus no autoderef.
1495 if let SelfSource::QPath(_) = source {
1496 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1499 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1503 #[derive(Copy, Clone, Debug)]
1504 pub enum SelfSource<'a> {
1505 QPath(&'a hir::Ty<'a>),
1506 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1509 #[derive(Copy, Clone)]
1510 pub struct TraitInfo {
1514 impl PartialEq for TraitInfo {
1515 fn eq(&self, other: &TraitInfo) -> bool {
1516 self.cmp(other) == Ordering::Equal
1519 impl Eq for TraitInfo {}
1520 impl PartialOrd for TraitInfo {
1521 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1522 Some(self.cmp(other))
1525 impl Ord for TraitInfo {
1526 fn cmp(&self, other: &TraitInfo) -> Ordering {
1527 // Local crates are more important than remote ones (local:
1528 // `cnum == 0`), and otherwise we throw in the defid for totality.
1530 let lhs = (other.def_id.krate, other.def_id);
1531 let rhs = (self.def_id.krate, self.def_id);
1536 /// Retrieves all traits in this crate and any dependent crates.
1537 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1538 tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
1541 /// Computes all traits in this crate and any dependent crates.
1542 fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
1543 use hir::itemlikevisit;
1545 let mut traits = vec![];
1549 struct Visitor<'a> {
1550 traits: &'a mut Vec<DefId>,
1553 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1554 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1556 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1557 self.traits.push(i.def_id.to_def_id());
1563 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1565 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1567 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1570 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1574 let mut external_mods = FxHashSet::default();
1575 fn handle_external_res(
1577 traits: &mut Vec<DefId>,
1578 external_mods: &mut FxHashSet<DefId>,
1582 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1583 traits.push(def_id);
1585 Res::Def(DefKind::Mod, def_id) => {
1586 if !external_mods.insert(def_id) {
1589 for child in tcx.item_children(def_id).iter() {
1590 handle_external_res(tcx, traits, external_mods, child.res)
1596 for &cnum in tcx.crates(()).iter() {
1597 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1598 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1601 tcx.arena.alloc_from_iter(traits)
1604 pub fn provide(providers: &mut ty::query::Providers) {
1605 providers.all_traits = compute_all_traits;
1608 struct UsePlacementFinder<'tcx> {
1609 target_module: hir::HirId,
1615 impl UsePlacementFinder<'tcx> {
1616 fn check(tcx: TyCtxt<'tcx>, target_module: hir::HirId) -> (Option<Span>, bool) {
1617 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1618 tcx.hir().walk_crate(&mut finder);
1619 (finder.span, finder.found_use)
1623 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1624 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1625 if self.span.is_some() {
1628 if hir_id != self.target_module {
1629 intravisit::walk_mod(self, module, hir_id);
1632 // Find a `use` statement.
1633 for &item_id in module.item_ids {
1634 let item = self.tcx.hir().item(item_id);
1636 hir::ItemKind::Use(..) => {
1637 // Don't suggest placing a `use` before the prelude
1638 // import or other generated ones.
1639 if !item.span.from_expansion() {
1640 self.span = Some(item.span.shrink_to_lo());
1641 self.found_use = true;
1645 // Don't place `use` before `extern crate`...
1646 hir::ItemKind::ExternCrate(_) => {}
1647 // ...but do place them before the first other item.
1649 if self.span.map_or(true, |span| item.span < span) {
1650 if !item.span.from_expansion() {
1651 self.span = Some(item.span.shrink_to_lo());
1652 // Don't insert between attributes and an item.
1653 let attrs = self.tcx.hir().attrs(item.hir_id());
1654 // Find the first attribute on the item.
1655 // FIXME: This is broken for active attributes.
1657 if !attr.span.is_dummy()
1658 && self.span.map_or(true, |span| attr.span < span)
1660 self.span = Some(attr.span.shrink_to_lo());
1670 type Map = intravisit::ErasedMap<'tcx>;
1672 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1673 intravisit::NestedVisitorMap::None
1677 fn print_disambiguation_help(
1679 args: Option<&'tcx [hir::Expr<'tcx>]>,
1680 err: &mut DiagnosticBuilder<'_>,
1683 kind: ty::AssocKind,
1686 candidate: Option<usize>,
1687 source_map: &source_map::SourceMap,
1689 let mut applicability = Applicability::MachineApplicable;
1690 let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1693 if rcvr_ty.is_region_ptr() {
1694 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1699 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1700 applicability = Applicability::HasPlaceholders;
1703 .collect::<Vec<_>>()
1706 (span, format!("{}::{}{}", trait_name, item_name, args))
1708 (span.with_hi(item_name.span.lo()), format!("{}::", trait_name))
1710 err.span_suggestion_verbose(
1713 "disambiguate the {} for {}",
1714 kind.as_def_kind().descr(def_id),
1715 if let Some(candidate) = candidate {
1716 format!("candidate #{}", candidate)
1718 "the candidate".to_string()