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, LOCAL_CRATE};
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;
386 let mut err = struct_span_err!(
390 "no {} named `{}` found for {} `{}` in the current scope",
393 actual.prefix_string(self.tcx),
396 if let Mode::MethodCall = mode {
397 if let SelfSource::MethodCall(call) = source {
398 self.suggest_await_before_method(
399 &mut err, item_name, actual, call, span,
404 tcx.sess.confused_type_with_std_module.borrow().get(&span)
406 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
409 "you are looking for the module in `std`, \
410 not the primitive type",
411 format!("std::{}", snippet),
412 Applicability::MachineApplicable,
416 if let ty::RawPtr(_) = &actual.kind() {
418 "try using `<*const T>::as_ref()` to get a reference to the \
419 type behind the pointer: https://doc.rust-lang.org/std/\
420 primitive.pointer.html#method.as_ref",
423 "using `<*const T>::as_ref()` on a pointer \
424 which is unaligned or points to invalid \
425 or uninitialized memory is undefined behavior",
431 tcx.sess.diagnostic().struct_dummy()
434 if let Some(def) = actual.ty_adt_def() {
435 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
436 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
440 "{} `{}` not found {}",
443 if def.is_enum() && !is_method { "here" } else { "for this" }
449 let mut label_span_not_found = || {
450 if unsatisfied_predicates.is_empty() {
451 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
453 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
455 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
458 // If the method name is the name of a field with a function or closure type,
459 // give a helping note that it has to be called as `(x.f)(...)`.
460 if let SelfSource::MethodCall(expr) = source {
462 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
463 ty::Adt(def, substs) if !def.is_enum() => {
464 let variant = &def.non_enum_variant();
465 self.tcx.find_field_index(item_name, variant).map(|index| {
466 let field = &variant.fields[index];
467 let field_ty = field.ty(tcx, substs);
474 if let Some((field, field_ty)) = field_receiver {
475 let scope = self.tcx.parent_module(self.body_id).to_def_id();
476 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
479 if self.is_fn_ty(&field_ty, span) {
480 let expr_span = expr.span.to(item_name.span);
481 err.multipart_suggestion(
483 "to call the function stored in `{}`, \
484 surround the field access with parentheses",
488 (expr_span.shrink_to_lo(), '('.to_string()),
489 (expr_span.shrink_to_hi(), ')'.to_string()),
491 Applicability::MachineApplicable,
497 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
499 if let Some(span) = call_expr.span.trim_start(item_name.span) {
502 "remove the arguments",
504 Applicability::MaybeIncorrect,
510 let field_kind = if is_accessible { "field" } else { "private field" };
511 err.span_label(item_name.span, format!("{}, not a method", field_kind));
512 } else if lev_candidate.is_none() && static_sources.is_empty() {
513 label_span_not_found();
516 label_span_not_found();
519 if self.is_fn_ty(&rcvr_ty, span) {
520 fn report_function<T: std::fmt::Display>(
521 err: &mut DiagnosticBuilder<'_>,
525 &format!("`{}` is a function, perhaps you wish to call it", name,),
529 if let SelfSource::MethodCall(expr) = source {
530 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
531 report_function(&mut err, expr_string);
532 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
533 if let Some(segment) = path.segments.last() {
534 report_function(&mut err, segment.ident);
540 if !static_sources.is_empty() {
542 "found the following associated functions; to be used as methods, \
543 functions must have a `self` parameter",
545 err.span_label(span, "this is an associated function, not a method");
547 if static_sources.len() == 1 {
548 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
549 static_sources.get(0)
551 // When the "method" is resolved through dereferencing, we really want the
552 // original type that has the associated function for accurate suggestions.
554 let ty = tcx.at(span).type_of(*impl_did);
555 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
556 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
557 // Use `actual` as it will have more `substs` filled in.
558 self.ty_to_value_string(actual.peel_refs())
560 _ => self.ty_to_value_string(ty.peel_refs()),
563 self.ty_to_value_string(actual.peel_refs())
565 if let SelfSource::MethodCall(expr) = source {
568 "use associated function syntax instead",
569 format!("{}::{}", ty_str, item_name),
570 Applicability::MachineApplicable,
573 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
576 report_candidates(span, &mut err, static_sources, sugg_span);
577 } else if static_sources.len() > 1 {
578 report_candidates(span, &mut err, static_sources, sugg_span);
581 let mut restrict_type_params = false;
582 if !unsatisfied_predicates.is_empty() {
583 let def_span = |def_id| {
584 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
586 let mut type_params = FxHashMap::default();
587 let mut bound_spans = vec![];
589 let mut collect_type_param_suggestions =
590 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
591 // We don't care about regions here, so it's fine to skip the binder here.
592 if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
593 (self_ty.kind(), parent_pred.kind().skip_binder())
595 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
596 let node = def.did.as_local().map(|def_id| {
599 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
601 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
602 if let Some(g) = kind.generics() {
603 let key = match g.where_clause.predicates {
604 [.., pred] => (pred.span().shrink_to_hi(), false),
607 .span_for_predicates_or_empty_place(),
613 .or_insert_with(FxHashSet::default)
614 .insert(obligation.to_owned());
620 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
622 "doesn't satisfy `{}`",
623 if obligation.len() > 50 { quiet } else { obligation }
625 match &self_ty.kind() {
626 // Point at the type that couldn't satisfy the bound.
627 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
628 // Point at the trait object that couldn't satisfy the bound.
629 ty::Dynamic(preds, _) => {
630 for pred in preds.iter() {
631 match pred.skip_binder() {
632 ty::ExistentialPredicate::Trait(tr) => {
633 bound_spans.push((def_span(tr.def_id), msg.clone()))
635 ty::ExistentialPredicate::Projection(_)
636 | ty::ExistentialPredicate::AutoTrait(_) => {}
640 // Point at the closure that couldn't satisfy the bound.
641 ty::Closure(def_id, _) => bound_spans
642 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
646 let mut format_pred = |pred: ty::Predicate<'tcx>| {
647 let bound_predicate = pred.kind();
648 match bound_predicate.skip_binder() {
649 ty::PredicateKind::Projection(pred) => {
650 let pred = bound_predicate.rebind(pred);
651 // `<Foo as Iterator>::Item = String`.
652 let projection_ty = pred.skip_binder().projection_ty;
654 let substs_with_infer_self = tcx.mk_substs(
655 iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
656 .chain(projection_ty.substs.iter().skip(1)),
659 let quiet_projection_ty = ty::ProjectionTy {
660 substs: substs_with_infer_self,
661 item_def_id: projection_ty.item_def_id,
664 let ty = pred.skip_binder().ty;
666 let obligation = format!("{} = {}", projection_ty, ty);
667 let quiet = format!("{} = {}", quiet_projection_ty, ty);
669 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
670 Some((obligation, projection_ty.self_ty()))
672 ty::PredicateKind::Trait(poly_trait_ref, _) => {
673 let p = poly_trait_ref.trait_ref;
674 let self_ty = p.self_ty();
675 let path = p.print_only_trait_path();
676 let obligation = format!("{}: {}", self_ty, path);
677 let quiet = format!("_: {}", path);
678 bound_span_label(self_ty, &obligation, &quiet);
679 Some((obligation, self_ty))
684 let mut bound_list = unsatisfied_predicates
686 .filter_map(|(pred, parent_pred)| {
687 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
688 None => format!("`{}`", &p),
689 Some(parent_pred) => match format_pred(*parent_pred) {
690 None => format!("`{}`", &p),
691 Some((parent_p, _)) => {
692 collect_type_param_suggestions(self_ty, parent_pred, &p);
693 format!("`{}`\nwhich is required by `{}`", p, parent_p)
699 .collect::<Vec<(usize, String)>>();
700 for ((span, empty_where), obligations) in type_params.into_iter() {
701 restrict_type_params = true;
702 // #74886: Sort here so that the output is always the same.
703 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
705 err.span_suggestion_verbose(
708 "consider restricting the type parameter{s} to satisfy the \
710 s = pluralize!(obligations.len())
714 if empty_where { " where" } else { "," },
715 obligations.join(", ")
717 Applicability::MaybeIncorrect,
721 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
722 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
723 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
726 for (span, msg) in bound_spans.into_iter() {
727 err.span_label(span, &msg);
729 if !bound_list.is_empty() {
730 let bound_list = bound_list
732 .map(|(_, path)| path)
735 let actual_prefix = actual.prefix_string(self.tcx);
736 err.set_primary_message(&format!(
737 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
740 "the following trait bounds were not satisfied:\n{bound_list}"
745 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
747 self.suggest_traits_to_import(
754 &unsatisfied_predicates,
758 // Don't emit a suggestion if we found an actual method
759 // that had unsatisfied trait bounds
760 if unsatisfied_predicates.is_empty() && actual.is_enum() {
761 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
762 if let Some(suggestion) = lev_distance::find_best_match_for_name(
763 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
769 "there is a variant with a similar name",
770 suggestion.to_string(),
771 Applicability::MaybeIncorrect,
776 let mut fallback_span = true;
777 let msg = "remove this method call";
778 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
779 if let SelfSource::MethodCall(expr) = source {
781 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
782 if let Some(span) = call_expr.span.trim_start(expr.span) {
787 Applicability::MachineApplicable,
789 fallback_span = false;
793 err.span_label(span, msg);
795 } else if let Some(lev_candidate) = lev_candidate {
796 // Don't emit a suggestion if we found an actual method
797 // that had unsatisfied trait bounds
798 if unsatisfied_predicates.is_empty() {
799 let def_kind = lev_candidate.kind.as_def_kind();
803 "there is {} {} with a similar name",
805 def_kind.descr(lev_candidate.def_id),
807 lev_candidate.ident.to_string(),
808 Applicability::MaybeIncorrect,
816 MethodError::Ambiguity(sources) => {
817 let mut err = struct_span_err!(
821 "multiple applicable items in scope"
823 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
825 report_candidates(span, &mut err, sources, sugg_span);
829 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
830 let kind = kind.descr(def_id);
831 let mut err = struct_span_err!(
835 "{} `{}` is private",
839 err.span_label(item_name.span, &format!("private {}", kind));
840 self.suggest_valid_traits(&mut err, out_of_scope_traits);
844 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
845 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
846 let mut err = self.sess().struct_span_err(span, &msg);
847 err.span_label(bound_span, "this has a `Sized` requirement");
848 if !candidates.is_empty() {
850 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
851 add a `use` for {one_of_them}:",
852 an = if candidates.len() == 1 { "an" } else { "" },
853 s = pluralize!(candidates.len()),
854 were = if candidates.len() == 1 { "was" } else { "were" },
855 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
857 self.suggest_use_candidates(&mut err, help, candidates);
859 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
861 let trait_type = self.tcx.mk_ref(
863 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
865 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
871 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
876 /// Print out the type for use in value namespace.
877 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
879 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
880 _ => self.ty_to_string(ty),
884 fn suggest_await_before_method(
886 err: &mut DiagnosticBuilder<'_>,
889 call: &hir::Expr<'_>,
892 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
893 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
896 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
897 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
899 err.span_suggestion_verbose(
901 "consider `await`ing on the `Future` and calling the method on its `Output`",
902 "await.".to_string(),
903 Applicability::MaybeIncorrect,
908 fn suggest_use_candidates(
910 err: &mut DiagnosticBuilder<'_>,
912 candidates: Vec<DefId>,
914 let module_did = self.tcx.parent_module(self.body_id);
915 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
916 let krate = self.tcx.hir().krate();
917 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
918 if let Some(span) = span {
919 let path_strings = candidates.iter().map(|did| {
920 // Produce an additional newline to separate the new use statement
921 // from the directly following item.
922 let additional_newline = if found_use { "" } else { "\n" };
925 with_crate_prefix(|| self.tcx.def_path_str(*did)),
930 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
932 let limit = if candidates.len() == 5 { 5 } else { 4 };
933 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
934 if candidates.len() > 1 {
935 msg.push_str(&format!(
936 "\ncandidate #{}: `use {};`",
938 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
941 msg.push_str(&format!(
943 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
947 if candidates.len() > limit {
948 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
954 fn suggest_valid_traits(
956 err: &mut DiagnosticBuilder<'_>,
957 valid_out_of_scope_traits: Vec<DefId>,
959 if !valid_out_of_scope_traits.is_empty() {
960 let mut candidates = valid_out_of_scope_traits;
963 err.help("items from traits can only be used if the trait is in scope");
965 "the following {traits_are} implemented but not in scope; \
966 perhaps add a `use` for {one_of_them}:",
967 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
968 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
971 self.suggest_use_candidates(err, msg, candidates);
978 fn suggest_traits_to_import(
980 err: &mut DiagnosticBuilder<'_>,
984 source: SelfSource<'tcx>,
985 valid_out_of_scope_traits: Vec<DefId>,
986 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
988 let mut alt_rcvr_sugg = false;
989 if let SelfSource::MethodCall(rcvr) = source {
990 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
992 self.tcx.lang_items().clone_trait(),
993 self.tcx.lang_items().deref_trait(),
994 self.tcx.lang_items().deref_mut_trait(),
995 self.tcx.lang_items().drop_trait(),
997 // Try alternative arbitrary self types that could fulfill this call.
998 // FIXME: probe for all types that *could* be arbitrary self-types, not
1000 for (rcvr_ty, post) in &[
1002 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
1003 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
1005 if let Ok(pick) = self.lookup_probe(
1010 crate::check::method::probe::ProbeScope::AllTraits,
1012 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1013 // We point at the method, but we just skip the rest of the check for arbitrary
1014 // self types and rely on the suggestion to `use` the trait from
1015 // `suggest_valid_traits`.
1016 let did = Some(pick.item.container.id());
1017 let skip = skippable.contains(&did);
1018 if pick.autoderefs == 0 && !skip {
1020 pick.item.ident.span,
1021 &format!("the method is available for `{}` here", rcvr_ty),
1026 for (rcvr_ty, pre) in &[
1027 (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1028 (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1029 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1030 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1032 if let Some(new_rcvr_t) = *rcvr_ty {
1033 if let Ok(pick) = self.lookup_probe(
1038 crate::check::method::probe::ProbeScope::AllTraits,
1040 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1041 let did = Some(pick.item.container.id());
1042 // We don't want to suggest a container type when the missing
1043 // method is `.clone()` or `.deref()` otherwise we'd suggest
1044 // `Arc::new(foo).clone()`, which is far from what the user wants.
1045 let skip = skippable.contains(&did);
1046 // Make sure the method is defined for the *actual* receiver: we don't
1047 // want to treat `Box<Self>` as a receiver if it only works because of
1048 // an autoderef to `&self`
1049 if pick.autoderefs == 0 && !skip {
1051 pick.item.ident.span,
1052 &format!("the method is available for `{}` here", new_rcvr_t),
1054 err.multipart_suggestion(
1055 "consider wrapping the receiver expression with the \
1058 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1059 (rcvr.span.shrink_to_hi(), ")".to_string()),
1061 Applicability::MaybeIncorrect,
1063 // We don't care about the other suggestions.
1064 alt_rcvr_sugg = true;
1071 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1075 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1077 let mut arbitrary_rcvr = vec![];
1078 // There are no traits implemented, so lets suggest some traits to
1079 // implement, by finding ones that have the item name, and are
1080 // legal to implement.
1081 let mut candidates = all_traits(self.tcx)
1083 // Don't issue suggestions for unstable traits since they're
1084 // unlikely to be implementable anyway
1085 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1086 Some(attr) => attr.level.is_stable(),
1090 // We approximate the coherence rules to only suggest
1091 // traits that are legal to implement by requiring that
1092 // either the type or trait is local. Multi-dispatch means
1093 // this isn't perfect (that is, there are cases when
1094 // implementing a trait would be legal but is rejected
1096 unsatisfied_predicates.iter().all(|(p, _)| {
1097 match p.kind().skip_binder() {
1098 // Hide traits if they are present in predicates as they can be fixed without
1099 // having to implement them.
1100 ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
1101 ty::PredicateKind::Projection(p) => {
1102 p.projection_ty.item_def_id == info.def_id
1106 }) && (type_is_local || info.def_id.is_local())
1108 .associated_item(info.def_id, item_name, Namespace::ValueNS)
1110 if let ty::AssocKind::Fn = item.kind {
1114 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1115 if let Some(hir::Node::TraitItem(hir::TraitItem {
1116 kind: hir::TraitItemKind::Fn(fn_sig, method),
1118 })) = id.map(|id| self.tcx.hir().get(id))
1120 let self_first_arg = match method {
1121 hir::TraitFn::Required([ident, ..]) => {
1122 ident.name == kw::SelfLower
1124 hir::TraitFn::Provided(body_id) => {
1125 self.tcx.hir().body(*body_id).params.first().map_or(
1130 hir::PatKind::Binding(_, _, ident, _)
1131 if ident.name == kw::SelfLower
1139 if !fn_sig.decl.implicit_self.has_implicit_self()
1142 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1143 arbitrary_rcvr.push(ty.span);
1149 // We only want to suggest public or local traits (#45781).
1150 item.vis == ty::Visibility::Public || info.def_id.is_local()
1154 .collect::<Vec<_>>();
1155 for span in &arbitrary_rcvr {
1158 "the method might not be found because of this arbitrary self type",
1165 if !candidates.is_empty() {
1166 // Sort from most relevant to least relevant.
1167 candidates.sort_by(|a, b| a.cmp(b).reverse());
1170 let param_type = match rcvr_ty.kind() {
1171 ty::Param(param) => Some(param),
1172 ty::Ref(_, ty, _) => match ty.kind() {
1173 ty::Param(param) => Some(param),
1178 err.help(if param_type.is_some() {
1179 "items from traits can only be used if the type parameter is bounded by the trait"
1181 "items from traits can only be used if the trait is implemented and in scope"
1183 let candidates_len = candidates.len();
1184 let message = |action| {
1186 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1189 if candidates_len == 1 { "trait defines" } else { "traits define" },
1191 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1195 // Obtain the span for `param` and use it for a structured suggestion.
1196 if let (Some(ref param), Some(ref table)) =
1197 (param_type, self.in_progress_typeck_results)
1199 let table_owner = table.borrow().hir_owner;
1200 let generics = self.tcx.generics_of(table_owner.to_def_id());
1201 let type_param = generics.type_param(param, self.tcx);
1202 let hir = &self.tcx.hir();
1203 if let Some(def_id) = type_param.def_id.as_local() {
1204 let id = hir.local_def_id_to_hir_id(def_id);
1205 // Get the `hir::Param` to verify whether it already has any bounds.
1206 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1207 // instead we suggest `T: Foo + Bar` in that case.
1209 Node::GenericParam(ref param) => {
1210 let mut impl_trait = false;
1212 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1215 // We've found `fn foo(x: impl Trait)` instead of
1216 // `fn foo<T>(x: T)`. We want to suggest the correct
1217 // `fn foo(x: impl Trait + TraitBound)` instead of
1218 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1224 let sp = hir.span(id);
1225 let sp = if let Some(first_bound) = has_bounds {
1226 // `sp` only covers `T`, change it so that it covers
1227 // `T:` when appropriate
1228 sp.until(first_bound.span())
1232 let trait_def_ids: FxHashSet<DefId> = param
1235 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1237 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1238 err.span_suggestions(
1241 "restrict type parameter `{}` with",
1244 candidates.iter().map(|t| {
1248 if impl_trait { " +" } else { ":" },
1249 self.tcx.def_path_str(t.def_id),
1250 if has_bounds.is_some() { " + " } else { "" },
1253 Applicability::MaybeIncorrect,
1258 Node::Item(hir::Item {
1259 kind: hir::ItemKind::Trait(.., bounds, _),
1263 let (sp, sep, article) = if bounds.is_empty() {
1264 (ident.span.shrink_to_hi(), ":", "a")
1266 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1268 err.span_suggestions(
1270 &message(format!("add {} supertrait for", article)),
1271 candidates.iter().map(|t| {
1272 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1274 Applicability::MaybeIncorrect,
1283 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1284 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1285 // cases where a positive bound implies a negative impl.
1286 (candidates, Vec::new())
1287 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1288 let mut potential_candidates = Vec::new();
1289 let mut explicitly_negative = Vec::new();
1290 for candidate in candidates {
1291 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1294 .all_impls(candidate.def_id)
1296 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1299 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1300 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1301 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1304 explicitly_negative.push(candidate);
1306 potential_candidates.push(candidate);
1309 (potential_candidates, explicitly_negative)
1311 // We don't know enough about `recv_ty` to make proper suggestions.
1312 (candidates, Vec::new())
1315 let action = if let Some(param) = param_type {
1316 format!("restrict type parameter `{}` with", param)
1318 // FIXME: it might only need to be imported into scope, not implemented.
1319 "implement".to_string()
1321 match &potential_candidates[..] {
1323 [trait_info] if trait_info.def_id.is_local() => {
1324 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1326 self.tcx.sess.source_map().guess_head_span(span),
1328 "`{}` defines an item `{}`, perhaps you need to {} it",
1329 self.tcx.def_path_str(trait_info.def_id),
1336 let mut msg = message(action);
1337 for (i, trait_info) in trait_infos.iter().enumerate() {
1338 msg.push_str(&format!(
1339 "\ncandidate #{}: `{}`",
1341 self.tcx.def_path_str(trait_info.def_id),
1347 match &explicitly_negative[..] {
1351 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1352 self.tcx.def_path_str(trait_info.def_id),
1358 let mut msg = format!(
1359 "the following traits define an item `{}`, but are explicitely unimplemented:",
1362 for trait_info in trait_infos {
1363 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1371 /// Checks whether there is a local type somewhere in the chain of
1372 /// autoderefs of `rcvr_ty`.
1373 fn type_derefs_to_local(
1377 source: SelfSource<'tcx>,
1379 fn is_local(ty: Ty<'_>) -> bool {
1381 ty::Adt(def, _) => def.did.is_local(),
1382 ty::Foreign(did) => did.is_local(),
1383 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1384 ty::Param(_) => true,
1386 // Everything else (primitive types, etc.) is effectively
1387 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1388 // the noise from these sort of types is usually just really
1389 // annoying, rather than any sort of help).
1394 // This occurs for UFCS desugaring of `T::method`, where there is no
1395 // receiver expression for the method call, and thus no autoderef.
1396 if let SelfSource::QPath(_) = source {
1397 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1400 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1404 #[derive(Copy, Clone, Debug)]
1405 pub enum SelfSource<'a> {
1406 QPath(&'a hir::Ty<'a>),
1407 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1410 #[derive(Copy, Clone)]
1411 pub struct TraitInfo {
1415 impl PartialEq for TraitInfo {
1416 fn eq(&self, other: &TraitInfo) -> bool {
1417 self.cmp(other) == Ordering::Equal
1420 impl Eq for TraitInfo {}
1421 impl PartialOrd for TraitInfo {
1422 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1423 Some(self.cmp(other))
1426 impl Ord for TraitInfo {
1427 fn cmp(&self, other: &TraitInfo) -> Ordering {
1428 // Local crates are more important than remote ones (local:
1429 // `cnum == 0`), and otherwise we throw in the defid for totality.
1431 let lhs = (other.def_id.krate, other.def_id);
1432 let rhs = (self.def_id.krate, self.def_id);
1437 /// Retrieves all traits in this crate and any dependent crates.
1438 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1439 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
1442 /// Computes all traits in this crate and any dependent crates.
1443 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
1444 use hir::itemlikevisit;
1446 let mut traits = vec![];
1450 struct Visitor<'a> {
1451 traits: &'a mut Vec<DefId>,
1454 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1455 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1457 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1458 self.traits.push(i.def_id.to_def_id());
1464 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1466 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1468 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1471 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1475 let mut external_mods = FxHashSet::default();
1476 fn handle_external_res(
1478 traits: &mut Vec<DefId>,
1479 external_mods: &mut FxHashSet<DefId>,
1483 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1484 traits.push(def_id);
1486 Res::Def(DefKind::Mod, def_id) => {
1487 if !external_mods.insert(def_id) {
1490 for child in tcx.item_children(def_id).iter() {
1491 handle_external_res(tcx, traits, external_mods, child.res)
1497 for &cnum in tcx.crates().iter() {
1498 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1499 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1505 pub fn provide(providers: &mut ty::query::Providers) {
1506 providers.all_traits = |tcx, cnum| {
1507 assert_eq!(cnum, LOCAL_CRATE);
1508 &tcx.arena.alloc(compute_all_traits(tcx))[..]
1512 struct UsePlacementFinder<'tcx> {
1513 target_module: hir::HirId,
1519 impl UsePlacementFinder<'tcx> {
1522 krate: &'tcx hir::Crate<'tcx>,
1523 target_module: hir::HirId,
1524 ) -> (Option<Span>, bool) {
1525 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1526 intravisit::walk_crate(&mut finder, krate);
1527 (finder.span, finder.found_use)
1531 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1532 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1533 if self.span.is_some() {
1536 if hir_id != self.target_module {
1537 intravisit::walk_mod(self, module, hir_id);
1540 // Find a `use` statement.
1541 for &item_id in module.item_ids {
1542 let item = self.tcx.hir().item(item_id);
1544 hir::ItemKind::Use(..) => {
1545 // Don't suggest placing a `use` before the prelude
1546 // import or other generated ones.
1547 if !item.span.from_expansion() {
1548 self.span = Some(item.span.shrink_to_lo());
1549 self.found_use = true;
1553 // Don't place `use` before `extern crate`...
1554 hir::ItemKind::ExternCrate(_) => {}
1555 // ...but do place them before the first other item.
1557 if self.span.map_or(true, |span| item.span < span) {
1558 if !item.span.from_expansion() {
1559 // Don't insert between attributes and an item.
1560 let attrs = self.tcx.hir().attrs(item.hir_id());
1561 if attrs.is_empty() {
1562 self.span = Some(item.span.shrink_to_lo());
1564 // Find the first attribute on the item.
1566 if self.span.map_or(true, |span| attr.span < span) {
1567 self.span = Some(attr.span.shrink_to_lo());
1578 type Map = intravisit::ErasedMap<'tcx>;
1580 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1581 intravisit::NestedVisitorMap::None
1585 fn print_disambiguation_help(
1587 args: Option<&'tcx [hir::Expr<'tcx>]>,
1588 err: &mut DiagnosticBuilder<'_>,
1591 kind: ty::AssocKind,
1594 candidate: Option<usize>,
1595 source_map: &source_map::SourceMap,
1597 let mut applicability = Applicability::MachineApplicable;
1598 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1601 if rcvr_ty.is_region_ptr() {
1602 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1607 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1608 applicability = Applicability::HasPlaceholders;
1611 .collect::<Vec<_>>()
1617 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1618 err.span_suggestion(
1621 "disambiguate the {} for {}",
1622 kind.as_def_kind().descr(def_id),
1623 if let Some(candidate) = candidate {
1624 format!("candidate #{}", candidate)
1626 "the candidate".to_string()