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_ast::util::lev_distance;
6 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
9 use rustc_hir::def::{DefKind, Namespace, Res};
10 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
11 use rustc_hir::intravisit;
12 use rustc_hir::lang_items::FnOnceTraitLangItem;
13 use rustc_hir::{ExprKind, Node, QPath};
14 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
15 use rustc_middle::hir::map as hir_map;
16 use rustc_middle::ty::print::with_crate_prefix;
17 use rustc_middle::ty::{
18 self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
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(FnOnceTraitLangItem) {
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(_, ref 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(),
396 tcx.sess.confused_type_with_std_module.borrow().get(&span)
398 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
401 "you are looking for the module in `std`, \
402 not the primitive type",
403 format!("std::{}", snippet),
404 Applicability::MachineApplicable,
408 if let ty::RawPtr(_) = &actual.kind {
410 "try using `<*const T>::as_ref()` to get a reference to the \
411 type behind the pointer: https://doc.rust-lang.org/std/\
412 primitive.pointer.html#method.as_ref",
415 "using `<*const T>::as_ref()` on a pointer \
416 which is unaligned or points to invalid \
417 or uninitialized memory is undefined behavior",
423 tcx.sess.diagnostic().struct_dummy()
426 if let Some(def) = actual.ty_adt_def() {
427 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
428 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
432 "{} `{}` not found {}",
435 if def.is_enum() && !is_method { "here" } else { "for this" }
441 // If the method name is the name of a field with a function or closure type,
442 // give a helping note that it has to be called as `(x.f)(...)`.
443 if let SelfSource::MethodCall(expr) = source {
445 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind {
446 ty::Adt(def, substs) if !def.is_enum() => {
447 let variant = &def.non_enum_variant();
448 self.tcx.find_field_index(item_name, variant).map(|index| {
449 let field = &variant.fields[index];
450 let field_ty = field.ty(tcx, substs);
457 if let Some((field, field_ty)) = field_receiver {
458 let scope = self.tcx.parent_module(self.body_id).to_def_id();
459 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
462 if self.is_fn_ty(&field_ty, span) {
463 let expr_span = expr.span.to(item_name.span);
464 err.multipart_suggestion(
466 "to call the function stored in `{}`, \
467 surround the field access with parentheses",
471 (expr_span.shrink_to_lo(), '('.to_string()),
472 (expr_span.shrink_to_hi(), ')'.to_string()),
474 Applicability::MachineApplicable,
480 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
482 if let Some(span) = call_expr.span.trim_start(item_name.span) {
485 "remove the arguments",
487 Applicability::MaybeIncorrect,
493 let field_kind = if is_accessible { "field" } else { "private field" };
494 err.span_label(item_name.span, format!("{}, not a method", field_kind));
495 } else if lev_candidate.is_none() && static_sources.is_empty() {
496 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
497 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
500 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
501 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
504 if self.is_fn_ty(&rcvr_ty, span) {
505 macro_rules! report_function {
506 ($span:expr, $name:expr) => {
508 "`{}` is a function, perhaps you wish to call it",
514 if let SelfSource::MethodCall(expr) = source {
515 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
516 report_function!(expr.span, expr_string);
517 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
518 if let Some(segment) = path.segments.last() {
519 report_function!(expr.span, segment.ident);
525 if !static_sources.is_empty() {
527 "found the following associated functions; to be used as methods, \
528 functions must have a `self` parameter",
530 err.span_label(span, "this is an associated function, not a method");
532 if static_sources.len() == 1 {
533 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
534 static_sources.get(0)
536 // When the "method" is resolved through dereferencing, we really want the
537 // original type that has the associated function for accurate suggestions.
539 let ty = tcx.at(span).type_of(*impl_did);
540 match (&ty.peel_refs().kind, &actual.peel_refs().kind) {
541 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
542 // Use `actual` as it will have more `substs` filled in.
543 self.ty_to_value_string(actual.peel_refs())
545 _ => self.ty_to_value_string(ty.peel_refs()),
548 self.ty_to_value_string(actual.peel_refs())
550 if let SelfSource::MethodCall(expr) = source {
553 "use associated function syntax instead",
554 format!("{}::{}", ty_str, item_name),
555 Applicability::MachineApplicable,
558 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
561 report_candidates(span, &mut err, static_sources, sugg_span);
562 } else if static_sources.len() > 1 {
563 report_candidates(span, &mut err, static_sources, sugg_span);
566 let mut restrict_type_params = false;
567 if !unsatisfied_predicates.is_empty() {
568 let def_span = |def_id| {
569 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
571 let mut type_params = FxHashMap::default();
572 let mut bound_spans = vec![];
574 let mut collect_type_param_suggestions = {
575 // We need to move `tcx` while only borrowing the rest,
576 // this is kind of ugly.
577 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
578 // We don't care about regions here, so it's fine to skip the binder here.
579 if let (ty::Param(_), ty::PredicateAtom::Trait(p, _)) =
580 (&self_ty.kind, parent_pred.skip_binders())
582 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind {
583 let node = def.did.as_local().map(|def_id| {
584 self.tcx.hir().get(self.tcx.hir().as_local_hir_id(def_id))
586 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
587 if let Some(g) = kind.generics() {
588 let key = match &g.where_clause.predicates[..] {
589 [.., pred] => (pred.span().shrink_to_hi(), false),
592 .span_for_predicates_or_empty_place(),
598 .or_insert_with(FxHashSet::default)
599 .insert(obligation.to_owned());
606 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
608 "doesn't satisfy `{}`",
609 if obligation.len() > 50 { quiet } else { obligation }
611 match &self_ty.kind {
612 // Point at the type that couldn't satisfy the bound.
613 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
614 // Point at the trait object that couldn't satisfy the bound.
615 ty::Dynamic(preds, _) => {
616 for pred in preds.skip_binder() {
618 ty::ExistentialPredicate::Trait(tr) => {
619 bound_spans.push((def_span(tr.def_id), msg.clone()))
621 ty::ExistentialPredicate::Projection(_)
622 | ty::ExistentialPredicate::AutoTrait(_) => {}
626 // Point at the closure that couldn't satisfy the bound.
627 ty::Closure(def_id, _) => bound_spans
628 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
632 let mut format_pred = |pred: ty::Predicate<'tcx>| {
633 match pred.skip_binders() {
634 ty::PredicateAtom::Projection(pred) => {
635 let pred = ty::Binder::bind(pred);
636 // `<Foo as Iterator>::Item = String`.
638 pred.skip_binder().projection_ty.trait_ref(self.tcx);
641 .associated_item(pred.skip_binder().projection_ty.item_def_id);
642 let ty = pred.skip_binder().ty;
643 let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty);
645 "<_ as {}>::{} = {}",
646 trait_ref.print_only_trait_path(),
650 bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
651 Some((obligation, trait_ref.self_ty()))
653 ty::PredicateAtom::Trait(poly_trait_ref, _) => {
654 let poly_trait_ref = ty::Binder::bind(poly_trait_ref);
655 let p = poly_trait_ref.skip_binder().trait_ref;
656 let self_ty = p.self_ty();
657 let path = p.print_only_trait_path();
658 let obligation = format!("{}: {}", self_ty, path);
659 let quiet = format!("_: {}", path);
660 bound_span_label(self_ty, &obligation, &quiet);
661 Some((obligation, self_ty))
666 let mut bound_list = unsatisfied_predicates
668 .filter_map(|(pred, parent_pred)| {
669 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
670 None => format!("`{}`", p),
671 Some(parent_pred) => match format_pred(*parent_pred) {
672 None => format!("`{}`", p),
673 Some((parent_p, _)) => {
674 collect_type_param_suggestions(self_ty, parent_pred, &p);
675 format!("`{}`\nwhich is required by `{}`", p, parent_p)
681 .collect::<Vec<(usize, String)>>();
682 for ((span, empty_where), obligations) in type_params.into_iter() {
683 restrict_type_params = true;
684 err.span_suggestion_verbose(
687 "consider restricting the type parameter{s} to satisfy the \
689 s = pluralize!(obligations.len())
693 if empty_where { " where" } else { "," },
694 obligations.into_iter().collect::<Vec<_>>().join(", ")
696 Applicability::MaybeIncorrect,
700 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
701 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
702 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
705 for (span, msg) in bound_spans.into_iter() {
706 err.span_label(span, &msg);
708 if !bound_list.is_empty() {
709 let bound_list = bound_list
711 .map(|(_, path)| path)
715 "the method `{}` exists but the following trait bounds were not \
717 item_name, bound_list
722 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
724 self.suggest_traits_to_import(
731 &unsatisfied_predicates,
735 if actual.is_enum() {
736 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
737 if let Some(suggestion) = lev_distance::find_best_match_for_name(
738 adt_def.variants.iter().map(|s| &s.ident.name),
744 "there is a variant with a similar name",
745 suggestion.to_string(),
746 Applicability::MaybeIncorrect,
751 let mut fallback_span = true;
752 let msg = "remove this method call";
753 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
754 if let SelfSource::MethodCall(expr) = source {
756 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
757 if let Some(span) = call_expr.span.trim_start(expr.span) {
762 Applicability::MachineApplicable,
764 fallback_span = false;
768 err.span_label(span, msg);
770 } else if let Some(lev_candidate) = lev_candidate {
771 let def_kind = lev_candidate.kind.as_def_kind();
775 "there is {} {} with a similar name",
777 def_kind.descr(lev_candidate.def_id),
779 lev_candidate.ident.to_string(),
780 Applicability::MaybeIncorrect,
787 MethodError::Ambiguity(sources) => {
788 let mut err = struct_span_err!(
792 "multiple applicable items in scope"
794 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
796 report_candidates(span, &mut err, sources, sugg_span);
800 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
801 let kind = kind.descr(def_id);
802 let mut err = struct_span_err!(
806 "{} `{}` is private",
810 err.span_label(item_name.span, &format!("private {}", kind));
811 self.suggest_valid_traits(&mut err, out_of_scope_traits);
815 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
816 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
817 let mut err = self.sess().struct_span_err(span, &msg);
818 err.span_label(bound_span, "this has a `Sized` requirement");
819 if !candidates.is_empty() {
821 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
822 add a `use` for {one_of_them}:",
823 an = if candidates.len() == 1 { "an" } else { "" },
824 s = pluralize!(candidates.len()),
825 were = if candidates.len() == 1 { "was" } else { "were" },
826 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
828 self.suggest_use_candidates(&mut err, help, candidates);
830 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind {
832 let trait_type = self.tcx.mk_ref(
834 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
836 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
842 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
847 /// Print out the type for use in value namespace.
848 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
850 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
851 _ => self.ty_to_string(ty),
855 fn suggest_use_candidates(
857 err: &mut DiagnosticBuilder<'_>,
859 candidates: Vec<DefId>,
861 let module_did = self.tcx.parent_module(self.body_id);
862 let module_id = self.tcx.hir().as_local_hir_id(module_did);
863 let krate = self.tcx.hir().krate();
864 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
865 if let Some(span) = span {
866 let path_strings = candidates.iter().map(|did| {
867 // Produce an additional newline to separate the new use statement
868 // from the directly following item.
869 let additional_newline = if found_use { "" } else { "\n" };
872 with_crate_prefix(|| self.tcx.def_path_str(*did)),
877 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
879 let limit = if candidates.len() == 5 { 5 } else { 4 };
880 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
881 if candidates.len() > 1 {
882 msg.push_str(&format!(
883 "\ncandidate #{}: `use {};`",
885 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
888 msg.push_str(&format!(
890 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
894 if candidates.len() > limit {
895 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
901 fn suggest_valid_traits(
903 err: &mut DiagnosticBuilder<'_>,
904 valid_out_of_scope_traits: Vec<DefId>,
906 if !valid_out_of_scope_traits.is_empty() {
907 let mut candidates = valid_out_of_scope_traits;
910 err.help("items from traits can only be used if the trait is in scope");
912 "the following {traits_are} implemented but not in scope; \
913 perhaps add a `use` for {one_of_them}:",
914 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
915 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
918 self.suggest_use_candidates(err, msg, candidates);
925 fn suggest_traits_to_import<'b>(
927 err: &mut DiagnosticBuilder<'_>,
931 source: SelfSource<'b>,
932 valid_out_of_scope_traits: Vec<DefId>,
933 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
935 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
939 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
941 let mut arbitrary_rcvr = vec![];
942 // There are no traits implemented, so lets suggest some traits to
943 // implement, by finding ones that have the item name, and are
944 // legal to implement.
945 let mut candidates = all_traits(self.tcx)
947 // Don't issue suggestions for unstable traits since they're
948 // unlikely to be implementable anyway
949 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
950 Some(attr) => attr.level.is_stable(),
954 // We approximate the coherence rules to only suggest
955 // traits that are legal to implement by requiring that
956 // either the type or trait is local. Multi-dispatch means
957 // this isn't perfect (that is, there are cases when
958 // implementing a trait would be legal but is rejected
960 unsatisfied_predicates.iter().all(|(p, _)| {
961 match p.skip_binders() {
962 // Hide traits if they are present in predicates as they can be fixed without
963 // having to implement them.
964 ty::PredicateAtom::Trait(t, _) => t.def_id() == info.def_id,
965 ty::PredicateAtom::Projection(p) => {
966 p.projection_ty.item_def_id == info.def_id
970 }) && (type_is_local || info.def_id.is_local())
972 .associated_item(info.def_id, item_name, Namespace::ValueNS)
974 if let ty::AssocKind::Fn = item.kind {
978 .map(|def_id| self.tcx.hir().as_local_hir_id(def_id));
979 if let Some(hir::Node::TraitItem(hir::TraitItem {
980 kind: hir::TraitItemKind::Fn(fn_sig, method),
982 })) = id.map(|id| self.tcx.hir().get(id))
984 let self_first_arg = match method {
985 hir::TraitFn::Required([ident, ..]) => {
986 ident.name == kw::SelfLower
988 hir::TraitFn::Provided(body_id) => {
989 self.tcx.hir().body(*body_id).params.first().map_or(
994 hir::PatKind::Binding(_, _, ident, _)
995 if ident.name == kw::SelfLower
1003 if !fn_sig.decl.implicit_self.has_implicit_self()
1006 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1007 arbitrary_rcvr.push(ty.span);
1013 // We only want to suggest public or local traits (#45781).
1014 item.vis == ty::Visibility::Public || info.def_id.is_local()
1018 .collect::<Vec<_>>();
1019 for span in &arbitrary_rcvr {
1022 "the method might not be found because of this arbitrary self type",
1026 if !candidates.is_empty() {
1027 // Sort from most relevant to least relevant.
1028 candidates.sort_by(|a, b| a.cmp(b).reverse());
1031 let param_type = match rcvr_ty.kind {
1032 ty::Param(param) => Some(param),
1033 ty::Ref(_, ty, _) => match ty.kind {
1034 ty::Param(param) => Some(param),
1039 err.help(if param_type.is_some() {
1040 "items from traits can only be used if the type parameter is bounded by the trait"
1042 "items from traits can only be used if the trait is implemented and in scope"
1044 let message = |action| {
1046 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1049 if candidates.len() == 1 { "trait defines" } else { "traits define" },
1051 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1055 // Obtain the span for `param` and use it for a structured suggestion.
1056 let mut suggested = false;
1057 if let (Some(ref param), Some(ref table)) =
1058 (param_type, self.in_progress_typeck_results)
1060 let table_owner = table.borrow().hir_owner;
1061 let generics = self.tcx.generics_of(table_owner.to_def_id());
1062 let type_param = generics.type_param(param, self.tcx);
1063 let hir = &self.tcx.hir();
1064 if let Some(def_id) = type_param.def_id.as_local() {
1065 let id = hir.as_local_hir_id(def_id);
1066 // Get the `hir::Param` to verify whether it already has any bounds.
1067 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1068 // instead we suggest `T: Foo + Bar` in that case.
1070 Node::GenericParam(ref param) => {
1071 let mut impl_trait = false;
1073 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1076 // We've found `fn foo(x: impl Trait)` instead of
1077 // `fn foo<T>(x: T)`. We want to suggest the correct
1078 // `fn foo(x: impl Trait + TraitBound)` instead of
1079 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1085 let sp = hir.span(id);
1086 let sp = if let Some(first_bound) = has_bounds {
1087 // `sp` only covers `T`, change it so that it covers
1088 // `T:` when appropriate
1089 sp.until(first_bound.span())
1093 let trait_def_ids: FxHashSet<DefId> = param
1096 .filter_map(|bound| Some(bound.trait_ref()?.trait_def_id()?))
1098 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1099 err.span_suggestions(
1102 "restrict type parameter `{}` with",
1105 candidates.iter().map(|t| {
1109 if impl_trait { " +" } else { ":" },
1110 self.tcx.def_path_str(t.def_id),
1111 if has_bounds.is_some() { " + " } else { "" },
1114 Applicability::MaybeIncorrect,
1119 Node::Item(hir::Item {
1120 kind: hir::ItemKind::Trait(.., bounds, _),
1124 let (sp, sep, article) = if bounds.is_empty() {
1125 (ident.span.shrink_to_hi(), ":", "a")
1127 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1129 err.span_suggestions(
1131 &message(format!("add {} supertrait for", article)),
1132 candidates.iter().map(|t| {
1133 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1135 Applicability::MaybeIncorrect,
1145 let action = if let Some(param) = param_type {
1146 format!("restrict type parameter `{}` with", param)
1148 // FIXME: it might only need to be imported into scope, not implemented.
1149 "implement".to_string()
1151 let mut use_note = true;
1152 if let [trait_info] = &candidates[..] {
1153 if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) {
1155 self.tcx.sess.source_map().guess_head_span(span),
1157 "`{}` defines an item `{}`, perhaps you need to {} it",
1158 self.tcx.def_path_str(trait_info.def_id),
1167 let mut msg = message(action);
1168 for (i, trait_info) in candidates.iter().enumerate() {
1169 msg.push_str(&format!(
1170 "\ncandidate #{}: `{}`",
1172 self.tcx.def_path_str(trait_info.def_id),
1181 /// Checks whether there is a local type somewhere in the chain of
1182 /// autoderefs of `rcvr_ty`.
1183 fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
1184 fn is_local(ty: Ty<'_>) -> bool {
1186 ty::Adt(def, _) => def.did.is_local(),
1187 ty::Foreign(did) => did.is_local(),
1189 ty::Dynamic(ref tr, ..) => {
1190 tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false)
1193 ty::Param(_) => true,
1195 // Everything else (primitive types, etc.) is effectively
1196 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1197 // the noise from these sort of types is usually just really
1198 // annoying, rather than any sort of help).
1203 // This occurs for UFCS desugaring of `T::method`, where there is no
1204 // receiver expression for the method call, and thus no autoderef.
1205 if let SelfSource::QPath(_) = source {
1206 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1209 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1213 #[derive(Copy, Clone)]
1214 pub enum SelfSource<'a> {
1215 QPath(&'a hir::Ty<'a>),
1216 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1219 #[derive(Copy, Clone)]
1220 pub struct TraitInfo {
1224 impl PartialEq for TraitInfo {
1225 fn eq(&self, other: &TraitInfo) -> bool {
1226 self.cmp(other) == Ordering::Equal
1229 impl Eq for TraitInfo {}
1230 impl PartialOrd for TraitInfo {
1231 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1232 Some(self.cmp(other))
1235 impl Ord for TraitInfo {
1236 fn cmp(&self, other: &TraitInfo) -> Ordering {
1237 // Local crates are more important than remote ones (local:
1238 // `cnum == 0`), and otherwise we throw in the defid for totality.
1240 let lhs = (other.def_id.krate, other.def_id);
1241 let rhs = (self.def_id.krate, self.def_id);
1246 /// Retrieves all traits in this crate and any dependent crates.
1247 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1248 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
1251 /// Computes all traits in this crate and any dependent crates.
1252 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
1253 use hir::itemlikevisit;
1255 let mut traits = vec![];
1259 struct Visitor<'a, 'tcx> {
1260 map: &'a hir_map::Map<'tcx>,
1261 traits: &'a mut Vec<DefId>,
1264 impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
1265 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1267 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1268 let def_id = self.map.local_def_id(i.hir_id);
1269 self.traits.push(def_id.to_def_id());
1275 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1277 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1280 tcx.hir().krate().visit_all_item_likes(&mut Visitor { map: &tcx.hir(), traits: &mut traits });
1284 let mut external_mods = FxHashSet::default();
1285 fn handle_external_res(
1287 traits: &mut Vec<DefId>,
1288 external_mods: &mut FxHashSet<DefId>,
1292 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1293 traits.push(def_id);
1295 Res::Def(DefKind::Mod, def_id) => {
1296 if !external_mods.insert(def_id) {
1299 for child in tcx.item_children(def_id).iter() {
1300 handle_external_res(tcx, traits, external_mods, child.res)
1306 for &cnum in tcx.crates().iter() {
1307 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1308 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1314 pub fn provide(providers: &mut ty::query::Providers) {
1315 providers.all_traits = |tcx, cnum| {
1316 assert_eq!(cnum, LOCAL_CRATE);
1317 &tcx.arena.alloc(compute_all_traits(tcx))[..]
1321 struct UsePlacementFinder<'tcx> {
1322 target_module: hir::HirId,
1328 impl UsePlacementFinder<'tcx> {
1331 krate: &'tcx hir::Crate<'tcx>,
1332 target_module: hir::HirId,
1333 ) -> (Option<Span>, bool) {
1334 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1335 intravisit::walk_crate(&mut finder, krate);
1336 (finder.span, finder.found_use)
1340 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1341 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1342 if self.span.is_some() {
1345 if hir_id != self.target_module {
1346 intravisit::walk_mod(self, module, hir_id);
1349 // Find a `use` statement.
1350 for item_id in module.item_ids {
1351 let item = self.tcx.hir().expect_item(item_id.id);
1353 hir::ItemKind::Use(..) => {
1354 // Don't suggest placing a `use` before the prelude
1355 // import or other generated ones.
1356 if !item.span.from_expansion() {
1357 self.span = Some(item.span.shrink_to_lo());
1358 self.found_use = true;
1362 // Don't place `use` before `extern crate`...
1363 hir::ItemKind::ExternCrate(_) => {}
1364 // ...but do place them before the first other item.
1366 if self.span.map_or(true, |span| item.span < span) {
1367 if !item.span.from_expansion() {
1368 // Don't insert between attributes and an item.
1369 if item.attrs.is_empty() {
1370 self.span = Some(item.span.shrink_to_lo());
1372 // Find the first attribute on the item.
1373 for attr in item.attrs {
1374 if self.span.map_or(true, |span| attr.span < span) {
1375 self.span = Some(attr.span.shrink_to_lo());
1386 type Map = intravisit::ErasedMap<'tcx>;
1388 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1389 intravisit::NestedVisitorMap::None
1393 fn print_disambiguation_help(
1395 args: Option<&'tcx [hir::Expr<'tcx>]>,
1396 err: &mut DiagnosticBuilder<'_>,
1399 kind: ty::AssocKind,
1402 candidate: Option<usize>,
1403 source_map: &source_map::SourceMap,
1405 let mut applicability = Applicability::MachineApplicable;
1406 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1409 if rcvr_ty.is_region_ptr() {
1410 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1415 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1416 applicability = Applicability::HasPlaceholders;
1419 .collect::<Vec<_>>()
1425 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1426 err.span_suggestion(
1429 "disambiguate the {} for {}",
1430 kind.as_def_kind().descr(def_id),
1431 if let Some(candidate) = candidate {
1432 format!("candidate #{}", candidate)
1434 "the candidate".to_string()