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 crate::middle::lang_items::FnOnceTraitLangItem;
6 use rustc::hir::map as hir_map;
7 use rustc::hir::map::Map;
8 use rustc::ty::print::with_crate_prefix;
9 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
10 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
13 use rustc_hir::def::{DefKind, Namespace, Res};
14 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
15 use rustc_hir::intravisit;
16 use rustc_hir::{ExprKind, Node, QPath};
17 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
18 use rustc_infer::traits::Obligation;
19 use rustc_span::symbol::kw;
20 use rustc_span::{source_map, FileName, Span};
22 use syntax::util::lev_distance;
24 use std::cmp::Ordering;
26 use super::probe::Mode;
27 use super::{CandidateSource, MethodError, NoMatchData};
29 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
33 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
34 // so we look for these beforehand.
35 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
36 // If it's not a simple function, look for things which implement `FnOnce`.
38 let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) {
39 Ok(fn_once) => fn_once,
40 Err(..) => return false,
43 self.autoderef(span, ty).any(|(ty, _)| {
45 let fn_once_substs = tcx.mk_substs_trait(
48 .next_ty_var(TypeVariableOrigin {
49 kind: TypeVariableOriginKind::MiscVariable,
54 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
55 let poly_trait_ref = trait_ref.to_poly_trait_ref();
56 let obligation = Obligation::misc(
60 poly_trait_ref.without_const().to_predicate(),
62 self.predicate_may_hold(&obligation)
69 pub fn report_method_error<'b>(
73 item_name: ast::Ident,
74 source: SelfSource<'b>,
75 error: MethodError<'tcx>,
76 args: Option<&'tcx [hir::Expr<'tcx>]>,
77 ) -> Option<DiagnosticBuilder<'_>> {
80 // Avoid suggestions when we don't know what's going on.
81 if rcvr_ty.references_error() {
85 let report_candidates = |span: Span,
86 err: &mut DiagnosticBuilder<'_>,
87 mut sources: Vec<CandidateSource>,
91 // Dynamic limit to avoid hiding just one candidate, which is silly.
92 let limit = if sources.len() == 5 { 5 } else { 4 };
94 for (idx, source) in sources.iter().take(limit).enumerate() {
96 CandidateSource::ImplSource(impl_did) => {
97 // Provide the best span we can. Use the item, if local to crate, else
98 // the impl, if local to crate (item may be defaulted), else nothing.
100 .associated_item(impl_did, item_name, Namespace::ValueNS)
102 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
103 self.associated_item(
104 impl_trait_ref.def_id,
115 .span_if_local(item.def_id)
116 .or_else(|| self.tcx.hir().span_if_local(impl_did));
118 let impl_ty = self.impl_self_ty(span, impl_did).ty;
120 let insertion = match self.tcx.impl_trait_ref(impl_did) {
121 None => String::new(),
122 Some(trait_ref) => format!(
123 " of the trait `{}`",
124 self.tcx.def_path_str(trait_ref.def_id)
128 let (note_str, idx) = if sources.len() > 1 {
131 "candidate #{} is defined in an impl{} for the type `{}`",
141 "the candidate is defined in an impl{} for the type `{}`",
147 if let Some(note_span) = note_span {
148 // We have a span pointing to the method. Show note with snippet.
150 self.tcx.sess.source_map().def_span(note_span),
156 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
157 let path = self.tcx.def_path_str(trait_ref.def_id);
159 let ty = match item.kind {
161 | ty::AssocKind::Type
162 | ty::AssocKind::OpaqueTy => rcvr_ty,
163 ty::AssocKind::Method => self
169 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
173 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) {
193 self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id));
194 let idx = if sources.len() > 1 {
196 "candidate #{} is defined in the trait `{}`",
198 self.tcx.def_path_str(trait_did)
200 err.span_note(item_span, msg);
204 "the candidate is defined in the trait `{}`",
205 self.tcx.def_path_str(trait_did)
207 err.span_note(item_span, msg);
210 let path = self.tcx.def_path_str(trait_did);
211 print_disambiguation_help(
220 self.tcx.sess.source_map(),
225 if sources.len() > limit {
226 err.note(&format!("and {} others", sources.len() - limit));
230 let sugg_span = if let SelfSource::MethodCall(expr) = source {
231 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
232 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
238 MethodError::NoMatch(NoMatchData {
239 static_candidates: static_sources,
240 unsatisfied_predicates,
247 let actual = self.resolve_vars_if_possible(&rcvr_ty);
248 let ty_str = self.ty_to_string(actual);
249 let is_method = mode == Mode::MethodCall;
250 let item_kind = if is_method {
252 } else if actual.is_enum() {
253 "variant or associated item"
255 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
256 (Some(name), false) if name.is_lowercase() => "function or associated item",
257 (Some(_), false) => "associated item",
258 (Some(_), true) | (None, false) => "variant or associated item",
259 (None, true) => "variant",
262 let mut err = if !actual.references_error() {
263 // Suggest clamping down the type if the method that is being attempted to
264 // be used exists at all, and the type is an ambiguous numeric type
265 // ({integer}/{float}).
266 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
267 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
269 if let (true, false, SelfSource::MethodCall(expr), Some(_)) = (
271 actual.has_concrete_skeleton(),
275 let mut err = struct_span_err!(
279 "can't call {} `{}` on ambiguous numeric type `{}`",
284 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
286 ExprKind::Lit(ref lit) => {
291 .span_to_snippet(lit.span)
292 .unwrap_or_else(|_| "<numeric literal>".to_owned());
297 "you must specify a concrete type for \
298 this numeric value, like `{}`",
301 format!("{}_{}", snippet, concrete_type),
302 Applicability::MaybeIncorrect,
305 ExprKind::Path(ref qpath) => {
307 if let &QPath::Resolved(_, ref path) = &qpath {
308 if let hir::def::Res::Local(hir_id) = path.res {
309 let span = tcx.hir().span(hir_id);
310 let snippet = tcx.sess.source_map().span_to_snippet(span);
311 let filename = tcx.sess.source_map().span_to_filename(span);
313 let parent_node = self
316 .get(self.tcx.hir().get_parent_node(hir_id));
318 "you must specify a type for this binding, like `{}`",
322 match (filename, parent_node, snippet) {
325 Node::Local(hir::Local {
326 source: hir::LocalSource::Normal,
333 // account for `let x: _ = 42;`
340 format!("{}: {}", snippet, concrete_type),
341 Applicability::MaybeIncorrect,
345 err.span_label(span, msg);
356 span = item_name.span;
357 let mut err = struct_span_err!(
361 "no {} named `{}` found for {} `{}` in the current scope",
364 actual.prefix_string(),
368 tcx.sess.confused_type_with_std_module.borrow().get(&span)
370 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
373 "you are looking for the module in `std`, \
374 not the primitive type",
375 format!("std::{}", snippet),
376 Applicability::MachineApplicable,
380 if let ty::RawPtr(_) = &actual.kind {
382 "try using `<*const T>::as_ref()` to get a reference to the \
383 type behind the pointer: https://doc.rust-lang.org/std/\
384 primitive.pointer.html#method.as_ref",
387 "using `<*const T>::as_ref()` on a pointer \
388 which is unaligned or points to invalid \
389 or uninitialized memory is undefined behavior",
395 tcx.sess.diagnostic().struct_dummy()
398 if let Some(def) = actual.ty_adt_def() {
399 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
400 let def_sp = tcx.sess.source_map().def_span(full_sp);
404 "{} `{}` not found {}",
407 if def.is_enum() && !is_method { "here" } else { "for this" }
413 // If the method name is the name of a field with a function or closure type,
414 // give a helping note that it has to be called as `(x.f)(...)`.
415 if let SelfSource::MethodCall(expr) = source {
417 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind {
418 ty::Adt(def, substs) if !def.is_enum() => {
419 let variant = &def.non_enum_variant();
420 self.tcx.find_field_index(item_name, variant).map(|index| {
421 let field = &variant.fields[index];
422 let field_ty = field.ty(tcx, substs);
429 if let Some((field, field_ty)) = field_receiver {
430 let scope = self.tcx.hir().get_module_parent(self.body_id);
431 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
434 if self.is_fn_ty(&field_ty, span) {
435 let expr_span = expr.span.to(item_name.span);
436 err.multipart_suggestion(
438 "to call the function stored in `{}`, \
439 surround the field access with parentheses",
443 (expr_span.shrink_to_lo(), '('.to_string()),
444 (expr_span.shrink_to_hi(), ')'.to_string()),
446 Applicability::MachineApplicable,
452 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
454 if let Some(span) = call_expr.span.trim_start(item_name.span) {
457 "remove the arguments",
459 Applicability::MaybeIncorrect,
465 let field_kind = if is_accessible { "field" } else { "private field" };
466 err.span_label(item_name.span, format!("{}, not a method", field_kind));
467 } else if lev_candidate.is_none() && static_sources.is_empty() {
468 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
469 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
472 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
473 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
476 if self.is_fn_ty(&rcvr_ty, span) {
477 macro_rules! report_function {
478 ($span:expr, $name:expr) => {
480 "`{}` is a function, perhaps you wish to call it",
486 if let SelfSource::MethodCall(expr) = source {
487 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
488 report_function!(expr.span, expr_string);
489 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
490 if let Some(segment) = path.segments.last() {
491 report_function!(expr.span, segment.ident);
497 if !static_sources.is_empty() {
499 "found the following associated functions; to be used as methods, \
500 functions must have a `self` parameter",
502 err.span_label(span, "this is an associated function, not a method");
504 if static_sources.len() == 1 {
505 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
506 static_sources.get(0)
508 // When the "method" is resolved through dereferencing, we really want the
509 // original type that has the associated function for accurate suggestions.
511 let ty = self.impl_self_ty(span, *impl_did).ty;
512 match (&ty.peel_refs().kind, &actual.peel_refs().kind) {
513 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
514 // Use `actual` as it will have more `substs` filled in.
515 self.ty_to_value_string(actual.peel_refs())
517 _ => self.ty_to_value_string(ty.peel_refs()),
520 self.ty_to_value_string(actual.peel_refs())
522 if let SelfSource::MethodCall(expr) = source {
525 "use associated function syntax instead",
526 format!("{}::{}", ty_str, item_name),
527 Applicability::MachineApplicable,
530 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
533 report_candidates(span, &mut err, static_sources, sugg_span);
534 } else if static_sources.len() > 1 {
535 report_candidates(span, &mut err, static_sources, sugg_span);
538 let mut restrict_type_params = false;
539 if !unsatisfied_predicates.is_empty() {
541 |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id));
542 let mut type_params = FxHashMap::default();
543 let mut bound_spans = vec![];
544 let mut collect_type_param_suggestions =
545 |self_ty: Ty<'_>, parent_pred: &ty::Predicate<'_>, obligation: &str| {
546 if let (ty::Param(_), ty::Predicate::Trait(p, _)) =
547 (&self_ty.kind, parent_pred)
549 if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind {
550 let id = self.tcx.hir().as_local_hir_id(def.did).unwrap();
551 let node = self.tcx.hir().get(id);
553 hir::Node::Item(hir::Item { kind, .. }) => {
554 if let Some(g) = kind.generics() {
555 let key = match &g.where_clause.predicates[..] {
557 (pred.span().shrink_to_hi(), false)
561 .span_for_predicates_or_empty_place(),
567 .or_insert_with(FxHashSet::default)
568 .insert(obligation.to_owned());
576 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
578 "doesn't satisfy `{}`",
579 if obligation.len() > 50 { quiet } else { obligation }
581 match &self_ty.kind {
582 // Point at the type that couldn't satisfy the bound.
583 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
584 // Point at the trait object that couldn't satisfy the bound.
585 ty::Dynamic(preds, _) => {
586 for pred in *preds.skip_binder() {
588 ty::ExistentialPredicate::Trait(tr) => {
589 bound_spans.push((def_span(tr.def_id), msg.clone()))
591 ty::ExistentialPredicate::Projection(_)
592 | ty::ExistentialPredicate::AutoTrait(_) => {}
596 // Point at the closure that couldn't satisfy the bound.
597 ty::Closure(def_id, _) => bound_spans
598 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
602 let mut format_pred = |pred| {
604 ty::Predicate::Projection(pred) => {
605 // `<Foo as Iterator>::Item = String`.
607 pred.skip_binder().projection_ty.trait_ref(self.tcx);
610 .associated_item(pred.skip_binder().projection_ty.item_def_id);
611 let ty = pred.skip_binder().ty;
612 let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty);
614 "<_ as {}>::{} = {}",
615 trait_ref.print_only_trait_path(),
619 bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
620 Some((obligation, trait_ref.self_ty()))
622 ty::Predicate::Trait(poly_trait_ref, _) => {
623 let p = poly_trait_ref.skip_binder().trait_ref;
624 let self_ty = p.self_ty();
625 let path = p.print_only_trait_path();
626 let obligation = format!("{}: {}", self_ty, path);
627 let quiet = format!("_: {}", path);
628 bound_span_label(self_ty, &obligation, &quiet);
629 Some((obligation, self_ty))
634 let mut bound_list = unsatisfied_predicates
636 .filter_map(|(pred, parent_pred)| {
637 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
638 None => format!("`{}`", p),
639 Some(parent_pred) => match format_pred(*parent_pred) {
640 None => format!("`{}`", p),
641 Some((parent_p, _)) => {
642 collect_type_param_suggestions(self_ty, parent_pred, &p);
643 format!("`{}`\nwhich is required by `{}`", p, parent_p)
649 .collect::<Vec<(usize, String)>>();
650 for ((span, empty_where), obligations) in type_params.into_iter() {
651 restrict_type_params = true;
652 err.span_suggestion_verbose(
655 "consider restricting the type parameter{s} to satisfy the \
657 s = pluralize!(obligations.len())
661 if empty_where { " where" } else { "," },
662 obligations.into_iter().collect::<Vec<_>>().join(", ")
664 Applicability::MaybeIncorrect,
668 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
669 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
670 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
673 for (span, msg) in bound_spans.into_iter() {
674 err.span_label(span, &msg);
676 if !bound_list.is_empty() {
677 let bound_list = bound_list
679 .map(|(_, path)| path)
683 "the method `{}` exists but the following trait bounds were not \
685 item_name, bound_list
690 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
692 self.suggest_traits_to_import(
702 if actual.is_enum() {
703 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
704 if let Some(suggestion) = lev_distance::find_best_match_for_name(
705 adt_def.variants.iter().map(|s| &s.ident.name),
711 "there is a variant with a similar name",
712 suggestion.to_string(),
713 Applicability::MaybeIncorrect,
718 let mut fallback_span = true;
719 let msg = "remove this method call";
720 if item_name.as_str() == "as_str" && actual.peel_refs().is_str() {
721 if let SelfSource::MethodCall(expr) = source {
723 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
724 if let Some(span) = call_expr.span.trim_start(expr.span) {
729 Applicability::MachineApplicable,
731 fallback_span = false;
735 err.span_label(span, msg);
737 } else if let Some(lev_candidate) = lev_candidate {
738 let def_kind = lev_candidate.def_kind();
742 "there is {} {} with a similar name",
744 def_kind.descr(lev_candidate.def_id),
746 lev_candidate.ident.to_string(),
747 Applicability::MaybeIncorrect,
754 MethodError::Ambiguity(sources) => {
755 let mut err = struct_span_err!(
759 "multiple applicable items in scope"
761 err.span_label(span, format!("multiple `{}` found", item_name));
763 report_candidates(span, &mut err, sources, sugg_span);
767 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
768 let mut err = struct_span_err!(
772 "{} `{}` is private",
776 self.suggest_valid_traits(&mut err, out_of_scope_traits);
780 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
781 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
782 let mut err = self.sess().struct_span_err(span, &msg);
783 err.span_label(bound_span, "this has a `Sized` requirement");
784 if !candidates.is_empty() {
786 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
787 add a `use` for {one_of_them}:",
788 an = if candidates.len() == 1 { "an" } else { "" },
789 s = pluralize!(candidates.len()),
790 were = if candidates.len() == 1 { "was" } else { "were" },
791 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
793 self.suggest_use_candidates(&mut err, help, candidates);
795 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind {
797 let trait_type = self.tcx.mk_ref(
799 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
801 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
807 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
812 /// Print out the type for use in value namespace.
813 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
815 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
816 _ => self.ty_to_string(ty),
820 fn suggest_use_candidates(
822 err: &mut DiagnosticBuilder<'_>,
824 candidates: Vec<DefId>,
826 let module_did = self.tcx.hir().get_module_parent(self.body_id);
827 let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
828 let krate = self.tcx.hir().krate();
829 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
830 if let Some(span) = span {
831 let path_strings = candidates.iter().map(|did| {
832 // Produce an additional newline to separate the new use statement
833 // from the directly following item.
834 let additional_newline = if found_use { "" } else { "\n" };
837 with_crate_prefix(|| self.tcx.def_path_str(*did)),
842 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
844 let limit = if candidates.len() == 5 { 5 } else { 4 };
845 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
846 if candidates.len() > 1 {
847 msg.push_str(&format!(
848 "\ncandidate #{}: `use {};`",
850 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
853 msg.push_str(&format!(
855 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
859 if candidates.len() > limit {
860 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
866 fn suggest_valid_traits(
868 err: &mut DiagnosticBuilder<'_>,
869 valid_out_of_scope_traits: Vec<DefId>,
871 if !valid_out_of_scope_traits.is_empty() {
872 let mut candidates = valid_out_of_scope_traits;
875 err.help("items from traits can only be used if the trait is in scope");
877 "the following {traits_are} implemented but not in scope; \
878 perhaps add a `use` for {one_of_them}:",
879 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
880 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
883 self.suggest_use_candidates(err, msg, candidates);
890 fn suggest_traits_to_import<'b>(
892 err: &mut DiagnosticBuilder<'_>,
895 item_name: ast::Ident,
896 source: SelfSource<'b>,
897 valid_out_of_scope_traits: Vec<DefId>,
899 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
903 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
905 let mut arbitrary_rcvr = vec![];
906 // There are no traits implemented, so lets suggest some traits to
907 // implement, by finding ones that have the item name, and are
908 // legal to implement.
909 let mut candidates = all_traits(self.tcx)
912 // We approximate the coherence rules to only suggest
913 // traits that are legal to implement by requiring that
914 // either the type or trait is local. Multi-dispatch means
915 // this isn't perfect (that is, there are cases when
916 // implementing a trait would be legal but is rejected
918 (type_is_local || info.def_id.is_local())
920 .associated_item(info.def_id, item_name, Namespace::ValueNS)
922 if let ty::AssocKind::Method = item.kind {
923 let id = self.tcx.hir().as_local_hir_id(item.def_id);
924 if let Some(hir::Node::TraitItem(hir::TraitItem {
925 kind: hir::TraitItemKind::Method(fn_sig, method),
927 })) = id.map(|id| self.tcx.hir().get(id))
929 let self_first_arg = match method {
930 hir::TraitMethod::Required([ident, ..]) => {
931 ident.name == kw::SelfLower
933 hir::TraitMethod::Provided(body_id) => {
934 match &self.tcx.hir().body(*body_id).params[..] {
939 hir::PatKind::Binding(
948 }, ..] => ident.name == kw::SelfLower,
955 if !fn_sig.decl.implicit_self.has_implicit_self()
958 if let Some(ty) = fn_sig.decl.inputs.get(0) {
959 arbitrary_rcvr.push(ty.span);
965 // We only want to suggest public or local traits (#45781).
966 item.vis == ty::Visibility::Public || info.def_id.is_local()
970 .collect::<Vec<_>>();
971 for span in &arbitrary_rcvr {
974 "the method might not be found because of this arbitrary self type",
978 if !candidates.is_empty() {
979 // Sort from most relevant to least relevant.
980 candidates.sort_by(|a, b| a.cmp(b).reverse());
983 let param_type = match rcvr_ty.kind {
984 ty::Param(param) => Some(param),
985 ty::Ref(_, ty, _) => match ty.kind {
986 ty::Param(param) => Some(param),
991 err.help(if param_type.is_some() {
992 "items from traits can only be used if the type parameter is bounded by the trait"
994 "items from traits can only be used if the trait is implemented and in scope"
996 let message = |action| {
998 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1001 if candidates.len() == 1 { "trait defines" } else { "traits define" },
1003 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1007 // Obtain the span for `param` and use it for a structured suggestion.
1008 let mut suggested = false;
1009 if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) {
1010 let table = table.borrow();
1011 if let Some(did) = table.local_id_root {
1012 let generics = self.tcx.generics_of(did);
1013 let type_param = generics.type_param(param, self.tcx);
1014 let hir = &self.tcx.hir();
1015 if let Some(id) = hir.as_local_hir_id(type_param.def_id) {
1016 // Get the `hir::Param` to verify whether it already has any bounds.
1017 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1018 // instead we suggest `T: Foo + Bar` in that case.
1020 Node::GenericParam(ref param) => {
1021 let mut impl_trait = false;
1022 let has_bounds = if let hir::GenericParamKind::Type {
1027 // We've found `fn foo(x: impl Trait)` instead of
1028 // `fn foo<T>(x: T)`. We want to suggest the correct
1029 // `fn foo(x: impl Trait + TraitBound)` instead of
1030 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1036 let sp = hir.span(id);
1037 let sp = if let Some(first_bound) = has_bounds {
1038 // `sp` only covers `T`, change it so that it covers
1039 // `T:` when appropriate
1040 sp.until(first_bound.span())
1044 let trait_def_ids: FxHashSet<DefId> = param
1047 .filter_map(|bound| bound.trait_def_id())
1049 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1050 err.span_suggestions(
1053 "restrict type parameter `{}` with",
1056 candidates.iter().map(|t| {
1060 if impl_trait { " +" } else { ":" },
1061 self.tcx.def_path_str(t.def_id),
1062 if has_bounds.is_some() { " + " } else { "" },
1065 Applicability::MaybeIncorrect,
1070 Node::Item(hir::Item {
1071 kind: hir::ItemKind::Trait(.., bounds, _),
1075 let (sp, sep, article) = if bounds.is_empty() {
1076 (ident.span.shrink_to_hi(), ":", "a")
1078 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1080 err.span_suggestions(
1082 &message(format!("add {} supertrait for", article)),
1083 candidates.iter().map(|t| {
1084 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1086 Applicability::MaybeIncorrect,
1097 let action = if let Some(param) = param_type {
1098 format!("restrict type parameter `{}` with", param)
1100 // FIXME: it might only need to be imported into scope, not implemented.
1101 "implement".to_string()
1103 let mut use_note = true;
1104 if let [trait_info] = &candidates[..] {
1105 if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) {
1107 self.tcx.sess.source_map().def_span(span),
1109 "`{}` defines an item `{}`, perhaps you need to {} it",
1110 self.tcx.def_path_str(trait_info.def_id),
1119 let mut msg = message(action);
1120 for (i, trait_info) in candidates.iter().enumerate() {
1121 msg.push_str(&format!(
1122 "\ncandidate #{}: `{}`",
1124 self.tcx.def_path_str(trait_info.def_id),
1133 /// Checks whether there is a local type somewhere in the chain of
1134 /// autoderefs of `rcvr_ty`.
1135 fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
1136 fn is_local(ty: Ty<'_>) -> bool {
1138 ty::Adt(def, _) => def.did.is_local(),
1139 ty::Foreign(did) => did.is_local(),
1141 ty::Dynamic(ref tr, ..) => {
1142 tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false)
1145 ty::Param(_) => true,
1147 // Everything else (primitive types, etc.) is effectively
1148 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1149 // the noise from these sort of types is usually just really
1150 // annoying, rather than any sort of help).
1155 // This occurs for UFCS desugaring of `T::method`, where there is no
1156 // receiver expression for the method call, and thus no autoderef.
1157 if let SelfSource::QPath(_) = source {
1158 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1161 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1165 #[derive(Copy, Clone)]
1166 pub enum SelfSource<'a> {
1167 QPath(&'a hir::Ty<'a>),
1168 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1171 #[derive(Copy, Clone)]
1172 pub struct TraitInfo {
1176 impl PartialEq for TraitInfo {
1177 fn eq(&self, other: &TraitInfo) -> bool {
1178 self.cmp(other) == Ordering::Equal
1181 impl Eq for TraitInfo {}
1182 impl PartialOrd for TraitInfo {
1183 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1184 Some(self.cmp(other))
1187 impl Ord for TraitInfo {
1188 fn cmp(&self, other: &TraitInfo) -> Ordering {
1189 // Local crates are more important than remote ones (local:
1190 // `cnum == 0`), and otherwise we throw in the defid for totality.
1192 let lhs = (other.def_id.krate, other.def_id);
1193 let rhs = (self.def_id.krate, self.def_id);
1198 /// Retrieves all traits in this crate and any dependent crates.
1199 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1200 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
1203 /// Computes all traits in this crate and any dependent crates.
1204 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
1205 use hir::itemlikevisit;
1207 let mut traits = vec![];
1211 struct Visitor<'a, 'tcx> {
1212 map: &'a hir_map::Map<'tcx>,
1213 traits: &'a mut Vec<DefId>,
1216 impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
1217 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1219 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1220 let def_id = self.map.local_def_id(i.hir_id);
1221 self.traits.push(def_id);
1227 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1229 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1232 tcx.hir().krate().visit_all_item_likes(&mut Visitor { map: &tcx.hir(), traits: &mut traits });
1236 let mut external_mods = FxHashSet::default();
1237 fn handle_external_res(
1239 traits: &mut Vec<DefId>,
1240 external_mods: &mut FxHashSet<DefId>,
1244 Res::Def(DefKind::Trait, def_id) | Res::Def(DefKind::TraitAlias, def_id) => {
1245 traits.push(def_id);
1247 Res::Def(DefKind::Mod, def_id) => {
1248 if !external_mods.insert(def_id) {
1251 for child in tcx.item_children(def_id).iter() {
1252 handle_external_res(tcx, traits, external_mods, child.res)
1258 for &cnum in tcx.crates().iter() {
1259 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1260 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1266 pub fn provide(providers: &mut ty::query::Providers<'_>) {
1267 providers.all_traits = |tcx, cnum| {
1268 assert_eq!(cnum, LOCAL_CRATE);
1269 &tcx.arena.alloc(compute_all_traits(tcx))[..]
1273 struct UsePlacementFinder<'tcx> {
1274 target_module: hir::HirId,
1280 impl UsePlacementFinder<'tcx> {
1283 krate: &'tcx hir::Crate<'tcx>,
1284 target_module: hir::HirId,
1285 ) -> (Option<Span>, bool) {
1286 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1287 intravisit::walk_crate(&mut finder, krate);
1288 (finder.span, finder.found_use)
1292 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1293 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1294 if self.span.is_some() {
1297 if hir_id != self.target_module {
1298 intravisit::walk_mod(self, module, hir_id);
1301 // Find a `use` statement.
1302 for item_id in module.item_ids {
1303 let item = self.tcx.hir().expect_item(item_id.id);
1305 hir::ItemKind::Use(..) => {
1306 // Don't suggest placing a `use` before the prelude
1307 // import or other generated ones.
1308 if !item.span.from_expansion() {
1309 self.span = Some(item.span.shrink_to_lo());
1310 self.found_use = true;
1314 // Don't place `use` before `extern crate`...
1315 hir::ItemKind::ExternCrate(_) => {}
1316 // ...but do place them before the first other item.
1318 if self.span.map_or(true, |span| item.span < span) {
1319 if !item.span.from_expansion() {
1320 // Don't insert between attributes and an item.
1321 if item.attrs.is_empty() {
1322 self.span = Some(item.span.shrink_to_lo());
1324 // Find the first attribute on the item.
1325 for attr in item.attrs {
1326 if self.span.map_or(true, |span| attr.span < span) {
1327 self.span = Some(attr.span.shrink_to_lo());
1338 type Map = Map<'tcx>;
1340 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
1341 intravisit::NestedVisitorMap::None
1345 fn print_disambiguation_help(
1346 item_name: ast::Ident,
1347 args: Option<&'tcx [hir::Expr<'tcx>]>,
1348 err: &mut DiagnosticBuilder<'_>,
1351 kind: ty::AssocKind,
1353 candidate: Option<usize>,
1354 source_map: &source_map::SourceMap,
1356 let mut applicability = Applicability::MachineApplicable;
1357 let sugg_args = if let (ty::AssocKind::Method, Some(args)) = (kind, args) {
1360 if rcvr_ty.is_region_ptr() {
1361 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1366 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1367 applicability = Applicability::HasPlaceholders;
1370 .collect::<Vec<_>>()
1376 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1377 err.span_suggestion(
1380 "disambiguate the {} for {}",
1381 kind.suggestion_descr(),
1382 if let Some(candidate) = candidate {
1383 format!("candidate #{}", candidate)
1385 "the candidate".to_string()