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;
27 use super::probe::Mode;
28 use super::{CandidateSource, MethodError, NoMatchData};
30 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
34 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
35 // so we look for these beforehand.
36 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
37 // If it's not a simple function, look for things which implement `FnOnce`.
39 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
40 Ok(fn_once) => fn_once,
41 Err(..) => return false,
44 self.autoderef(span, ty).any(|(ty, _)| {
46 let fn_once_substs = tcx.mk_substs_trait(
49 .next_ty_var(TypeVariableOrigin {
50 kind: TypeVariableOriginKind::MiscVariable,
55 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
56 let poly_trait_ref = trait_ref.to_poly_trait_ref();
57 let obligation = Obligation::misc(
61 poly_trait_ref.without_const().to_predicate(tcx),
63 self.predicate_may_hold(&obligation)
70 pub fn report_method_error<'b>(
75 source: SelfSource<'b>,
76 error: MethodError<'tcx>,
77 args: Option<&'tcx [hir::Expr<'tcx>]>,
78 ) -> Option<DiagnosticBuilder<'_>> {
81 // Avoid suggestions when we don't know what's going on.
82 if rcvr_ty.references_error() {
86 let report_candidates = |span: Span,
87 err: &mut DiagnosticBuilder<'_>,
88 mut sources: Vec<CandidateSource>,
92 // Dynamic limit to avoid hiding just one candidate, which is silly.
93 let limit = if sources.len() == 5 { 5 } else { 4 };
95 for (idx, source) in sources.iter().take(limit).enumerate() {
97 CandidateSource::ImplSource(impl_did) => {
98 // Provide the best span we can. Use the item, if local to crate, else
99 // the impl, if local to crate (item may be defaulted), else nothing.
100 let item = match self
101 .associated_item(impl_did, item_name, Namespace::ValueNS)
103 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
104 self.associated_item(
105 impl_trait_ref.def_id,
116 .span_if_local(item.def_id)
117 .or_else(|| self.tcx.hir().span_if_local(impl_did));
119 let impl_ty = self.tcx.at(span).type_of(impl_did);
121 let insertion = match self.tcx.impl_trait_ref(impl_did) {
122 None => String::new(),
123 Some(trait_ref) => format!(
124 " of the trait `{}`",
125 self.tcx.def_path_str(trait_ref.def_id)
129 let (note_str, idx) = if sources.len() > 1 {
132 "candidate #{} is defined in an impl{} for the type `{}`",
142 "the candidate is defined in an impl{} for the type `{}`",
148 if let Some(note_span) = note_span {
149 // We have a span pointing to the method. Show note with snippet.
151 self.tcx.sess.source_map().guess_head_span(note_span),
157 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
158 let path = self.tcx.def_path_str(trait_ref.def_id);
160 let ty = match item.kind {
161 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
162 ty::AssocKind::Fn => self
168 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
172 print_disambiguation_help(
182 self.tcx.sess.source_map(),
186 CandidateSource::TraitSource(trait_did) => {
188 match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
196 .guess_head_span(self.tcx.def_span(item.def_id));
197 let idx = if sources.len() > 1 {
199 "candidate #{} is defined in the trait `{}`",
201 self.tcx.def_path_str(trait_did)
203 err.span_note(item_span, msg);
207 "the candidate is defined in the trait `{}`",
208 self.tcx.def_path_str(trait_did)
210 err.span_note(item_span, msg);
213 let path = self.tcx.def_path_str(trait_did);
214 print_disambiguation_help(
224 self.tcx.sess.source_map(),
229 if sources.len() > limit {
230 err.note(&format!("and {} others", sources.len() - limit));
234 let sugg_span = if let SelfSource::MethodCall(expr) = source {
235 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
236 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
242 MethodError::NoMatch(NoMatchData {
243 static_candidates: static_sources,
244 unsatisfied_predicates,
251 let actual = self.resolve_vars_if_possible(rcvr_ty);
252 let ty_str = self.ty_to_string(actual);
253 let is_method = mode == Mode::MethodCall;
254 let item_kind = if is_method {
256 } else if actual.is_enum() {
257 "variant or associated item"
259 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
260 (Some(name), false) if name.is_lowercase() => "function or associated item",
261 (Some(_), false) => "associated item",
262 (Some(_), true) | (None, false) => "variant or associated item",
263 (None, true) => "variant",
266 let mut err = if !actual.references_error() {
267 // Suggest clamping down the type if the method that is being attempted to
268 // be used exists at all, and the type is an ambiguous numeric type
269 // ({integer}/{float}).
270 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
271 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
273 // There are methods that are defined on the primitive types and won't be
274 // found when exploring `all_traits`, but we also need them to be acurate on
275 // our suggestions (#47759).
276 let fund_assoc = |opt_def_id: Option<DefId>| {
278 .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
281 let lang_items = tcx.lang_items();
282 let found_candidate = candidates.next().is_some()
283 || fund_assoc(lang_items.i8_impl())
284 || fund_assoc(lang_items.i16_impl())
285 || fund_assoc(lang_items.i32_impl())
286 || fund_assoc(lang_items.i64_impl())
287 || fund_assoc(lang_items.i128_impl())
288 || fund_assoc(lang_items.u8_impl())
289 || fund_assoc(lang_items.u16_impl())
290 || fund_assoc(lang_items.u32_impl())
291 || fund_assoc(lang_items.u64_impl())
292 || fund_assoc(lang_items.u128_impl())
293 || fund_assoc(lang_items.f32_impl())
294 || fund_assoc(lang_items.f32_runtime_impl())
295 || fund_assoc(lang_items.f64_impl())
296 || fund_assoc(lang_items.f64_runtime_impl());
297 if let (true, false, SelfSource::MethodCall(expr), true) = (
299 actual.has_concrete_skeleton(),
303 let mut err = struct_span_err!(
307 "can't call {} `{}` on ambiguous numeric type `{}`",
312 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
314 ExprKind::Lit(ref lit) => {
319 .span_to_snippet(lit.span)
320 .unwrap_or_else(|_| "<numeric literal>".to_owned());
325 "you must specify a concrete type for \
326 this numeric value, like `{}`",
329 format!("{}_{}", snippet, concrete_type),
330 Applicability::MaybeIncorrect,
333 ExprKind::Path(ref qpath) => {
335 if let QPath::Resolved(_, path) = qpath {
336 if let hir::def::Res::Local(hir_id) = path.res {
337 let span = tcx.hir().span(hir_id);
338 let snippet = tcx.sess.source_map().span_to_snippet(span);
339 let filename = tcx.sess.source_map().span_to_filename(span);
341 let parent_node = self
344 .get(self.tcx.hir().get_parent_node(hir_id));
346 "you must specify a type for this binding, like `{}`",
350 match (filename, parent_node, snippet) {
353 Node::Local(hir::Local {
354 source: hir::LocalSource::Normal,
361 // account for `let x: _ = 42;`
368 format!("{}: {}", snippet, concrete_type),
369 Applicability::MaybeIncorrect,
373 err.span_label(span, msg);
384 span = item_name.span;
385 let mut err = struct_span_err!(
389 "no {} named `{}` found for {} `{}` in the current scope",
392 actual.prefix_string(),
395 if let Mode::MethodCall = mode {
396 if let SelfSource::MethodCall(call) = source {
397 self.suggest_await_before_method(
398 &mut err, item_name, actual, call, span,
403 tcx.sess.confused_type_with_std_module.borrow().get(&span)
405 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
408 "you are looking for the module in `std`, \
409 not the primitive type",
410 format!("std::{}", snippet),
411 Applicability::MachineApplicable,
415 if let ty::RawPtr(_) = &actual.kind() {
417 "try using `<*const T>::as_ref()` to get a reference to the \
418 type behind the pointer: https://doc.rust-lang.org/std/\
419 primitive.pointer.html#method.as_ref",
422 "using `<*const T>::as_ref()` on a pointer \
423 which is unaligned or points to invalid \
424 or uninitialized memory is undefined behavior",
430 tcx.sess.diagnostic().struct_dummy()
433 if let Some(def) = actual.ty_adt_def() {
434 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
435 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
439 "{} `{}` not found {}",
442 if def.is_enum() && !is_method { "here" } else { "for this" }
448 let mut label_span_not_found = || {
449 if unsatisfied_predicates.is_empty() {
450 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
452 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
454 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
457 // If the method name is the name of a field with a function or closure type,
458 // give a helping note that it has to be called as `(x.f)(...)`.
459 if let SelfSource::MethodCall(expr) = source {
461 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
462 ty::Adt(def, substs) if !def.is_enum() => {
463 let variant = &def.non_enum_variant();
464 self.tcx.find_field_index(item_name, variant).map(|index| {
465 let field = &variant.fields[index];
466 let field_ty = field.ty(tcx, substs);
473 if let Some((field, field_ty)) = field_receiver {
474 let scope = self.tcx.parent_module(self.body_id).to_def_id();
475 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
478 if self.is_fn_ty(&field_ty, span) {
479 let expr_span = expr.span.to(item_name.span);
480 err.multipart_suggestion(
482 "to call the function stored in `{}`, \
483 surround the field access with parentheses",
487 (expr_span.shrink_to_lo(), '('.to_string()),
488 (expr_span.shrink_to_hi(), ')'.to_string()),
490 Applicability::MachineApplicable,
496 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
498 if let Some(span) = call_expr.span.trim_start(item_name.span) {
501 "remove the arguments",
503 Applicability::MaybeIncorrect,
509 let field_kind = if is_accessible { "field" } else { "private field" };
510 err.span_label(item_name.span, format!("{}, not a method", field_kind));
511 } else if lev_candidate.is_none() && static_sources.is_empty() {
512 label_span_not_found();
515 label_span_not_found();
518 if self.is_fn_ty(&rcvr_ty, span) {
519 macro_rules! report_function {
520 ($span:expr, $name:expr) => {
522 "`{}` is a function, perhaps you wish to call it",
528 if let SelfSource::MethodCall(expr) = source {
529 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
530 report_function!(expr.span, expr_string);
531 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
532 if let Some(segment) = path.segments.last() {
533 report_function!(expr.span, segment.ident);
539 if !static_sources.is_empty() {
541 "found the following associated functions; to be used as methods, \
542 functions must have a `self` parameter",
544 err.span_label(span, "this is an associated function, not a method");
546 if static_sources.len() == 1 {
547 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
548 static_sources.get(0)
550 // When the "method" is resolved through dereferencing, we really want the
551 // original type that has the associated function for accurate suggestions.
553 let ty = tcx.at(span).type_of(*impl_did);
554 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
555 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
556 // Use `actual` as it will have more `substs` filled in.
557 self.ty_to_value_string(actual.peel_refs())
559 _ => self.ty_to_value_string(ty.peel_refs()),
562 self.ty_to_value_string(actual.peel_refs())
564 if let SelfSource::MethodCall(expr) = source {
567 "use associated function syntax instead",
568 format!("{}::{}", ty_str, item_name),
569 Applicability::MachineApplicable,
572 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
575 report_candidates(span, &mut err, static_sources, sugg_span);
576 } else if static_sources.len() > 1 {
577 report_candidates(span, &mut err, static_sources, sugg_span);
580 let mut restrict_type_params = false;
581 if !unsatisfied_predicates.is_empty() {
582 let def_span = |def_id| {
583 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
585 let mut type_params = FxHashMap::default();
586 let mut bound_spans = vec![];
588 let mut collect_type_param_suggestions =
589 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
590 // We don't care about regions here, so it's fine to skip the binder here.
591 if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
592 (self_ty.kind(), parent_pred.kind().skip_binder())
594 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
595 let node = def.did.as_local().map(|def_id| {
598 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
600 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
601 if let Some(g) = kind.generics() {
602 let key = match g.where_clause.predicates {
603 [.., pred] => (pred.span().shrink_to_hi(), false),
606 .span_for_predicates_or_empty_place(),
612 .or_insert_with(FxHashSet::default)
613 .insert(obligation.to_owned());
619 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
621 "doesn't satisfy `{}`",
622 if obligation.len() > 50 { quiet } else { obligation }
624 match &self_ty.kind() {
625 // Point at the type that couldn't satisfy the bound.
626 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
627 // Point at the trait object that couldn't satisfy the bound.
628 ty::Dynamic(preds, _) => {
629 for pred in preds.iter() {
630 match pred.skip_binder() {
631 ty::ExistentialPredicate::Trait(tr) => {
632 bound_spans.push((def_span(tr.def_id), msg.clone()))
634 ty::ExistentialPredicate::Projection(_)
635 | ty::ExistentialPredicate::AutoTrait(_) => {}
639 // Point at the closure that couldn't satisfy the bound.
640 ty::Closure(def_id, _) => bound_spans
641 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
645 let mut format_pred = |pred: ty::Predicate<'tcx>| {
646 let bound_predicate = pred.kind();
647 match bound_predicate.skip_binder() {
648 ty::PredicateKind::Projection(pred) => {
649 let pred = bound_predicate.rebind(pred);
650 // `<Foo as Iterator>::Item = String`.
652 pred.skip_binder().projection_ty.trait_ref(self.tcx);
655 .associated_item(pred.skip_binder().projection_ty.item_def_id);
656 let ty = pred.skip_binder().ty;
657 let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty);
659 "<_ as {}>::{} = {}",
660 trait_ref.print_only_trait_path(),
664 bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
665 Some((obligation, trait_ref.self_ty()))
667 ty::PredicateKind::Trait(poly_trait_ref, _) => {
668 let p = poly_trait_ref.trait_ref;
669 let self_ty = p.self_ty();
670 let path = p.print_only_trait_path();
671 let obligation = format!("{}: {}", self_ty, path);
672 let quiet = format!("_: {}", path);
673 bound_span_label(self_ty, &obligation, &quiet);
674 Some((obligation, self_ty))
679 let mut bound_list = unsatisfied_predicates
681 .filter_map(|(pred, parent_pred)| {
682 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
683 None => format!("`{}`", &p),
684 Some(parent_pred) => match format_pred(*parent_pred) {
685 None => format!("`{}`", &p),
686 Some((parent_p, _)) => {
687 collect_type_param_suggestions(self_ty, parent_pred, &p);
688 format!("`{}`\nwhich is required by `{}`", p, parent_p)
694 .collect::<Vec<(usize, String)>>();
695 for ((span, empty_where), obligations) in type_params.into_iter() {
696 restrict_type_params = true;
697 // #74886: Sort here so that the output is always the same.
698 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
700 err.span_suggestion_verbose(
703 "consider restricting the type parameter{s} to satisfy the \
705 s = pluralize!(obligations.len())
709 if empty_where { " where" } else { "," },
710 obligations.join(", ")
712 Applicability::MaybeIncorrect,
716 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
717 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
718 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
721 for (span, msg) in bound_spans.into_iter() {
722 err.span_label(span, &msg);
724 if !bound_list.is_empty() {
725 let bound_list = bound_list
727 .map(|(_, path)| path)
730 let actual_prefix = actual.prefix_string();
731 err.set_primary_message(&format!(
732 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
735 "the following trait bounds were not satisfied:\n{bound_list}"
740 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
742 self.suggest_traits_to_import(
749 &unsatisfied_predicates,
753 // Don't emit a suggestion if we found an actual method
754 // that had unsatisfied trait bounds
755 if unsatisfied_predicates.is_empty() && actual.is_enum() {
756 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
757 if let Some(suggestion) = lev_distance::find_best_match_for_name(
758 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
764 "there is a variant with a similar name",
765 suggestion.to_string(),
766 Applicability::MaybeIncorrect,
771 let mut fallback_span = true;
772 let msg = "remove this method call";
773 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
774 if let SelfSource::MethodCall(expr) = source {
776 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
777 if let Some(span) = call_expr.span.trim_start(expr.span) {
782 Applicability::MachineApplicable,
784 fallback_span = false;
788 err.span_label(span, msg);
790 } else if let Some(lev_candidate) = lev_candidate {
791 // Don't emit a suggestion if we found an actual method
792 // that had unsatisfied trait bounds
793 if unsatisfied_predicates.is_empty() {
794 let def_kind = lev_candidate.kind.as_def_kind();
798 "there is {} {} with a similar name",
800 def_kind.descr(lev_candidate.def_id),
802 lev_candidate.ident.to_string(),
803 Applicability::MaybeIncorrect,
811 MethodError::Ambiguity(sources) => {
812 let mut err = struct_span_err!(
816 "multiple applicable items in scope"
818 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
820 report_candidates(span, &mut err, sources, sugg_span);
824 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
825 let kind = kind.descr(def_id);
826 let mut err = struct_span_err!(
830 "{} `{}` is private",
834 err.span_label(item_name.span, &format!("private {}", kind));
835 self.suggest_valid_traits(&mut err, out_of_scope_traits);
839 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
840 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
841 let mut err = self.sess().struct_span_err(span, &msg);
842 err.span_label(bound_span, "this has a `Sized` requirement");
843 if !candidates.is_empty() {
845 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
846 add a `use` for {one_of_them}:",
847 an = if candidates.len() == 1 { "an" } else { "" },
848 s = pluralize!(candidates.len()),
849 were = if candidates.len() == 1 { "was" } else { "were" },
850 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
852 self.suggest_use_candidates(&mut err, help, candidates);
854 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
856 let trait_type = self.tcx.mk_ref(
858 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
860 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
866 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
871 /// Print out the type for use in value namespace.
872 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
874 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
875 _ => self.ty_to_string(ty),
879 fn suggest_await_before_method(
881 err: &mut DiagnosticBuilder<'_>,
884 call: &hir::Expr<'_>,
887 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
888 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
891 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
892 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
894 err.span_suggestion_verbose(
896 "consider `await`ing on the `Future` and calling the method on its `Output`",
897 "await.".to_string(),
898 Applicability::MaybeIncorrect,
903 fn suggest_use_candidates(
905 err: &mut DiagnosticBuilder<'_>,
907 candidates: Vec<DefId>,
909 let module_did = self.tcx.parent_module(self.body_id);
910 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
911 let krate = self.tcx.hir().krate();
912 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
913 if let Some(span) = span {
914 let path_strings = candidates.iter().map(|did| {
915 // Produce an additional newline to separate the new use statement
916 // from the directly following item.
917 let additional_newline = if found_use { "" } else { "\n" };
920 with_crate_prefix(|| self.tcx.def_path_str(*did)),
925 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
927 let limit = if candidates.len() == 5 { 5 } else { 4 };
928 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
929 if candidates.len() > 1 {
930 msg.push_str(&format!(
931 "\ncandidate #{}: `use {};`",
933 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
936 msg.push_str(&format!(
938 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
942 if candidates.len() > limit {
943 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
949 fn suggest_valid_traits(
951 err: &mut DiagnosticBuilder<'_>,
952 valid_out_of_scope_traits: Vec<DefId>,
954 if !valid_out_of_scope_traits.is_empty() {
955 let mut candidates = valid_out_of_scope_traits;
958 err.help("items from traits can only be used if the trait is in scope");
960 "the following {traits_are} implemented but not in scope; \
961 perhaps add a `use` for {one_of_them}:",
962 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
963 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
966 self.suggest_use_candidates(err, msg, candidates);
973 fn suggest_traits_to_import<'b>(
975 err: &mut DiagnosticBuilder<'_>,
979 source: SelfSource<'b>,
980 valid_out_of_scope_traits: Vec<DefId>,
981 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
983 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
987 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
989 let mut arbitrary_rcvr = vec![];
990 // There are no traits implemented, so lets suggest some traits to
991 // implement, by finding ones that have the item name, and are
992 // legal to implement.
993 let mut candidates = all_traits(self.tcx)
995 // Don't issue suggestions for unstable traits since they're
996 // unlikely to be implementable anyway
997 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
998 Some(attr) => attr.level.is_stable(),
1002 // We approximate the coherence rules to only suggest
1003 // traits that are legal to implement by requiring that
1004 // either the type or trait is local. Multi-dispatch means
1005 // this isn't perfect (that is, there are cases when
1006 // implementing a trait would be legal but is rejected
1008 unsatisfied_predicates.iter().all(|(p, _)| {
1009 match p.kind().skip_binder() {
1010 // Hide traits if they are present in predicates as they can be fixed without
1011 // having to implement them.
1012 ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
1013 ty::PredicateKind::Projection(p) => {
1014 p.projection_ty.item_def_id == info.def_id
1018 }) && (type_is_local || info.def_id.is_local())
1020 .associated_item(info.def_id, item_name, Namespace::ValueNS)
1022 if let ty::AssocKind::Fn = item.kind {
1026 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1027 if let Some(hir::Node::TraitItem(hir::TraitItem {
1028 kind: hir::TraitItemKind::Fn(fn_sig, method),
1030 })) = id.map(|id| self.tcx.hir().get(id))
1032 let self_first_arg = match method {
1033 hir::TraitFn::Required([ident, ..]) => {
1034 ident.name == kw::SelfLower
1036 hir::TraitFn::Provided(body_id) => {
1037 self.tcx.hir().body(*body_id).params.first().map_or(
1042 hir::PatKind::Binding(_, _, ident, _)
1043 if ident.name == kw::SelfLower
1051 if !fn_sig.decl.implicit_self.has_implicit_self()
1054 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1055 arbitrary_rcvr.push(ty.span);
1061 // We only want to suggest public or local traits (#45781).
1062 item.vis == ty::Visibility::Public || info.def_id.is_local()
1066 .collect::<Vec<_>>();
1067 for span in &arbitrary_rcvr {
1070 "the method might not be found because of this arbitrary self type",
1074 if !candidates.is_empty() {
1075 // Sort from most relevant to least relevant.
1076 candidates.sort_by(|a, b| a.cmp(b).reverse());
1079 let param_type = match rcvr_ty.kind() {
1080 ty::Param(param) => Some(param),
1081 ty::Ref(_, ty, _) => match ty.kind() {
1082 ty::Param(param) => Some(param),
1087 err.help(if param_type.is_some() {
1088 "items from traits can only be used if the type parameter is bounded by the trait"
1090 "items from traits can only be used if the trait is implemented and in scope"
1092 let candidates_len = candidates.len();
1093 let message = |action| {
1095 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1098 if candidates_len == 1 { "trait defines" } else { "traits define" },
1100 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1104 // Obtain the span for `param` and use it for a structured suggestion.
1105 if let (Some(ref param), Some(ref table)) =
1106 (param_type, self.in_progress_typeck_results)
1108 let table_owner = table.borrow().hir_owner;
1109 let generics = self.tcx.generics_of(table_owner.to_def_id());
1110 let type_param = generics.type_param(param, self.tcx);
1111 let hir = &self.tcx.hir();
1112 if let Some(def_id) = type_param.def_id.as_local() {
1113 let id = hir.local_def_id_to_hir_id(def_id);
1114 // Get the `hir::Param` to verify whether it already has any bounds.
1115 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1116 // instead we suggest `T: Foo + Bar` in that case.
1118 Node::GenericParam(ref param) => {
1119 let mut impl_trait = false;
1121 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1124 // We've found `fn foo(x: impl Trait)` instead of
1125 // `fn foo<T>(x: T)`. We want to suggest the correct
1126 // `fn foo(x: impl Trait + TraitBound)` instead of
1127 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1133 let sp = hir.span(id);
1134 let sp = if let Some(first_bound) = has_bounds {
1135 // `sp` only covers `T`, change it so that it covers
1136 // `T:` when appropriate
1137 sp.until(first_bound.span())
1141 let trait_def_ids: FxHashSet<DefId> = param
1144 .filter_map(|bound| Some(bound.trait_ref()?.trait_def_id()?))
1146 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1147 err.span_suggestions(
1150 "restrict type parameter `{}` with",
1153 candidates.iter().map(|t| {
1157 if impl_trait { " +" } else { ":" },
1158 self.tcx.def_path_str(t.def_id),
1159 if has_bounds.is_some() { " + " } else { "" },
1162 Applicability::MaybeIncorrect,
1167 Node::Item(hir::Item {
1168 kind: hir::ItemKind::Trait(.., bounds, _),
1172 let (sp, sep, article) = if bounds.is_empty() {
1173 (ident.span.shrink_to_hi(), ":", "a")
1175 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1177 err.span_suggestions(
1179 &message(format!("add {} supertrait for", article)),
1180 candidates.iter().map(|t| {
1181 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1183 Applicability::MaybeIncorrect,
1192 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1193 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1194 // cases where a positive bound implies a negative impl.
1195 (candidates, Vec::new())
1196 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1197 let mut potential_candidates = Vec::new();
1198 let mut explicitly_negative = Vec::new();
1199 for candidate in candidates {
1200 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1203 .all_impls(candidate.def_id)
1205 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1208 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1209 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1210 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1213 explicitly_negative.push(candidate);
1215 potential_candidates.push(candidate);
1218 (potential_candidates, explicitly_negative)
1220 // We don't know enough about `recv_ty` to make proper suggestions.
1221 (candidates, Vec::new())
1224 let action = if let Some(param) = param_type {
1225 format!("restrict type parameter `{}` with", param)
1227 // FIXME: it might only need to be imported into scope, not implemented.
1228 "implement".to_string()
1230 match &potential_candidates[..] {
1232 [trait_info] if trait_info.def_id.is_local() => {
1233 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1235 self.tcx.sess.source_map().guess_head_span(span),
1237 "`{}` defines an item `{}`, perhaps you need to {} it",
1238 self.tcx.def_path_str(trait_info.def_id),
1245 let mut msg = message(action);
1246 for (i, trait_info) in trait_infos.iter().enumerate() {
1247 msg.push_str(&format!(
1248 "\ncandidate #{}: `{}`",
1250 self.tcx.def_path_str(trait_info.def_id),
1256 match &explicitly_negative[..] {
1260 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1261 self.tcx.def_path_str(trait_info.def_id),
1267 let mut msg = format!(
1268 "the following traits define an item `{}`, but are explicitely unimplemented:",
1271 for trait_info in trait_infos {
1272 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1280 /// Checks whether there is a local type somewhere in the chain of
1281 /// autoderefs of `rcvr_ty`.
1282 fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
1283 fn is_local(ty: Ty<'_>) -> bool {
1285 ty::Adt(def, _) => def.did.is_local(),
1286 ty::Foreign(did) => did.is_local(),
1287 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1288 ty::Param(_) => true,
1290 // Everything else (primitive types, etc.) is effectively
1291 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1292 // the noise from these sort of types is usually just really
1293 // annoying, rather than any sort of help).
1298 // This occurs for UFCS desugaring of `T::method`, where there is no
1299 // receiver expression for the method call, and thus no autoderef.
1300 if let SelfSource::QPath(_) = source {
1301 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1304 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1308 #[derive(Copy, Clone)]
1309 pub enum SelfSource<'a> {
1310 QPath(&'a hir::Ty<'a>),
1311 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1314 #[derive(Copy, Clone)]
1315 pub struct TraitInfo {
1319 impl PartialEq for TraitInfo {
1320 fn eq(&self, other: &TraitInfo) -> bool {
1321 self.cmp(other) == Ordering::Equal
1324 impl Eq for TraitInfo {}
1325 impl PartialOrd for TraitInfo {
1326 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1327 Some(self.cmp(other))
1330 impl Ord for TraitInfo {
1331 fn cmp(&self, other: &TraitInfo) -> Ordering {
1332 // Local crates are more important than remote ones (local:
1333 // `cnum == 0`), and otherwise we throw in the defid for totality.
1335 let lhs = (other.def_id.krate, other.def_id);
1336 let rhs = (self.def_id.krate, self.def_id);
1341 /// Retrieves all traits in this crate and any dependent crates.
1342 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1343 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
1346 /// Computes all traits in this crate and any dependent crates.
1347 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
1348 use hir::itemlikevisit;
1350 let mut traits = vec![];
1354 struct Visitor<'a> {
1355 traits: &'a mut Vec<DefId>,
1358 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1359 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1361 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1362 self.traits.push(i.def_id.to_def_id());
1368 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1370 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1372 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1375 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1379 let mut external_mods = FxHashSet::default();
1380 fn handle_external_res(
1382 traits: &mut Vec<DefId>,
1383 external_mods: &mut FxHashSet<DefId>,
1387 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1388 traits.push(def_id);
1390 Res::Def(DefKind::Mod, def_id) => {
1391 if !external_mods.insert(def_id) {
1394 for child in tcx.item_children(def_id).iter() {
1395 handle_external_res(tcx, traits, external_mods, child.res)
1401 for &cnum in tcx.crates().iter() {
1402 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1403 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1409 pub fn provide(providers: &mut ty::query::Providers) {
1410 providers.all_traits = |tcx, cnum| {
1411 assert_eq!(cnum, LOCAL_CRATE);
1412 &tcx.arena.alloc(compute_all_traits(tcx))[..]
1416 struct UsePlacementFinder<'tcx> {
1417 target_module: hir::HirId,
1423 impl UsePlacementFinder<'tcx> {
1426 krate: &'tcx hir::Crate<'tcx>,
1427 target_module: hir::HirId,
1428 ) -> (Option<Span>, bool) {
1429 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1430 intravisit::walk_crate(&mut finder, krate);
1431 (finder.span, finder.found_use)
1435 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1436 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1437 if self.span.is_some() {
1440 if hir_id != self.target_module {
1441 intravisit::walk_mod(self, module, hir_id);
1444 // Find a `use` statement.
1445 for &item_id in module.item_ids {
1446 let item = self.tcx.hir().item(item_id);
1448 hir::ItemKind::Use(..) => {
1449 // Don't suggest placing a `use` before the prelude
1450 // import or other generated ones.
1451 if !item.span.from_expansion() {
1452 self.span = Some(item.span.shrink_to_lo());
1453 self.found_use = true;
1457 // Don't place `use` before `extern crate`...
1458 hir::ItemKind::ExternCrate(_) => {}
1459 // ...but do place them before the first other item.
1461 if self.span.map_or(true, |span| item.span < span) {
1462 if !item.span.from_expansion() {
1463 // Don't insert between attributes and an item.
1464 if item.attrs.is_empty() {
1465 self.span = Some(item.span.shrink_to_lo());
1467 // Find the first attribute on the item.
1468 for attr in item.attrs {
1469 if self.span.map_or(true, |span| attr.span < span) {
1470 self.span = Some(attr.span.shrink_to_lo());
1481 type Map = intravisit::ErasedMap<'tcx>;
1483 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1484 intravisit::NestedVisitorMap::None
1488 fn print_disambiguation_help(
1490 args: Option<&'tcx [hir::Expr<'tcx>]>,
1491 err: &mut DiagnosticBuilder<'_>,
1494 kind: ty::AssocKind,
1497 candidate: Option<usize>,
1498 source_map: &source_map::SourceMap,
1500 let mut applicability = Applicability::MachineApplicable;
1501 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1504 if rcvr_ty.is_region_ptr() {
1505 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1510 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1511 applicability = Applicability::HasPlaceholders;
1514 .collect::<Vec<_>>()
1520 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1521 err.span_suggestion(
1524 "disambiguate the {} for {}",
1525 kind.as_def_kind().descr(def_id),
1526 if let Some(candidate) = candidate {
1527 format!("candidate #{}", candidate)
1529 "the candidate".to_string()