1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
4 use crate::check::FnCtxt;
5 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
8 use rustc_hir::def::{DefKind, Namespace, Res};
9 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
10 use rustc_hir::intravisit;
11 use rustc_hir::lang_items::LangItem;
12 use rustc_hir::{ExprKind, Node, QPath};
13 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
14 use rustc_middle::ty::fast_reject::simplify_type;
15 use rustc_middle::ty::print::with_crate_prefix;
16 use rustc_middle::ty::{
17 self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
19 use rustc_span::lev_distance;
20 use rustc_span::symbol::{kw, sym, Ident};
21 use rustc_span::{source_map, FileName, Span};
22 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
23 use rustc_trait_selection::traits::Obligation;
25 use std::cmp::Ordering;
28 use super::probe::Mode;
29 use super::{CandidateSource, MethodError, NoMatchData};
31 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
35 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
36 // so we look for these beforehand.
37 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
38 // If it's not a simple function, look for things which implement `FnOnce`.
40 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
41 Ok(fn_once) => fn_once,
42 Err(..) => return false,
45 self.autoderef(span, ty).any(|(ty, _)| {
47 let fn_once_substs = tcx.mk_substs_trait(
50 .next_ty_var(TypeVariableOrigin {
51 kind: TypeVariableOriginKind::MiscVariable,
56 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
57 let poly_trait_ref = trait_ref.to_poly_trait_ref();
58 let obligation = Obligation::misc(
62 poly_trait_ref.without_const().to_predicate(tcx),
64 self.predicate_may_hold(&obligation)
71 pub fn report_method_error(
76 source: SelfSource<'tcx>,
77 error: MethodError<'tcx>,
78 args: Option<&'tcx [hir::Expr<'tcx>]>,
79 ) -> Option<DiagnosticBuilder<'_>> {
82 // Avoid suggestions when we don't know what's going on.
83 if rcvr_ty.references_error() {
87 let report_candidates = |span: Span,
88 err: &mut DiagnosticBuilder<'_>,
89 mut sources: Vec<CandidateSource>,
93 // Dynamic limit to avoid hiding just one candidate, which is silly.
94 let limit = if sources.len() == 5 { 5 } else { 4 };
96 for (idx, source) in sources.iter().take(limit).enumerate() {
98 CandidateSource::ImplSource(impl_did) => {
99 // Provide the best span we can. Use the item, if local to crate, else
100 // the impl, if local to crate (item may be defaulted), else nothing.
101 let item = match self
102 .associated_item(impl_did, item_name, Namespace::ValueNS)
104 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
105 self.associated_item(
106 impl_trait_ref.def_id,
117 .span_if_local(item.def_id)
118 .or_else(|| self.tcx.hir().span_if_local(impl_did));
120 let impl_ty = self.tcx.at(span).type_of(impl_did);
122 let insertion = match self.tcx.impl_trait_ref(impl_did) {
123 None => String::new(),
124 Some(trait_ref) => format!(
125 " of the trait `{}`",
126 self.tcx.def_path_str(trait_ref.def_id)
130 let (note_str, idx) = if sources.len() > 1 {
133 "candidate #{} is defined in an impl{} for the type `{}`",
143 "the candidate is defined in an impl{} for the type `{}`",
149 if let Some(note_span) = note_span {
150 // We have a span pointing to the method. Show note with snippet.
152 self.tcx.sess.source_map().guess_head_span(note_span),
158 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
159 let path = self.tcx.def_path_str(trait_ref.def_id);
161 let ty = match item.kind {
162 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
163 ty::AssocKind::Fn => self
169 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
173 print_disambiguation_help(
183 self.tcx.sess.source_map(),
187 CandidateSource::TraitSource(trait_did) => {
189 match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
197 .guess_head_span(self.tcx.def_span(item.def_id));
198 let idx = if sources.len() > 1 {
200 "candidate #{} is defined in the trait `{}`",
202 self.tcx.def_path_str(trait_did)
204 err.span_note(item_span, msg);
208 "the candidate is defined in the trait `{}`",
209 self.tcx.def_path_str(trait_did)
211 err.span_note(item_span, msg);
214 let path = self.tcx.def_path_str(trait_did);
215 print_disambiguation_help(
225 self.tcx.sess.source_map(),
230 if sources.len() > limit {
231 err.note(&format!("and {} others", sources.len() - limit));
235 let sugg_span = if let SelfSource::MethodCall(expr) = source {
236 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
237 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
243 MethodError::NoMatch(NoMatchData {
244 static_candidates: static_sources,
245 unsatisfied_predicates,
252 let actual = self.resolve_vars_if_possible(rcvr_ty);
253 let ty_str = self.ty_to_string(actual);
254 let is_method = mode == Mode::MethodCall;
255 let item_kind = if is_method {
257 } else if actual.is_enum() {
258 "variant or associated item"
260 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
261 (Some(name), false) if name.is_lowercase() => "function or associated item",
262 (Some(_), false) => "associated item",
263 (Some(_), true) | (None, false) => "variant or associated item",
264 (None, true) => "variant",
267 let mut err = if !actual.references_error() {
268 // Suggest clamping down the type if the method that is being attempted to
269 // be used exists at all, and the type is an ambiguous numeric type
270 // ({integer}/{float}).
271 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
272 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
274 // There are methods that are defined on the primitive types and won't be
275 // found when exploring `all_traits`, but we also need them to be acurate on
276 // our suggestions (#47759).
277 let fund_assoc = |opt_def_id: Option<DefId>| {
279 .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
282 let lang_items = tcx.lang_items();
283 let found_candidate = candidates.next().is_some()
284 || fund_assoc(lang_items.i8_impl())
285 || fund_assoc(lang_items.i16_impl())
286 || fund_assoc(lang_items.i32_impl())
287 || fund_assoc(lang_items.i64_impl())
288 || fund_assoc(lang_items.i128_impl())
289 || fund_assoc(lang_items.u8_impl())
290 || fund_assoc(lang_items.u16_impl())
291 || fund_assoc(lang_items.u32_impl())
292 || fund_assoc(lang_items.u64_impl())
293 || fund_assoc(lang_items.u128_impl())
294 || fund_assoc(lang_items.f32_impl())
295 || fund_assoc(lang_items.f32_runtime_impl())
296 || fund_assoc(lang_items.f64_impl())
297 || fund_assoc(lang_items.f64_runtime_impl());
298 if let (true, false, SelfSource::MethodCall(expr), true) = (
300 actual.has_concrete_skeleton(),
304 let mut err = struct_span_err!(
308 "can't call {} `{}` on ambiguous numeric type `{}`",
313 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
315 ExprKind::Lit(ref lit) => {
320 .span_to_snippet(lit.span)
321 .unwrap_or_else(|_| "<numeric literal>".to_owned());
326 "you must specify a concrete type for this numeric value, \
330 format!("{}_{}", snippet, concrete_type),
331 Applicability::MaybeIncorrect,
334 ExprKind::Path(ref qpath) => {
336 if let QPath::Resolved(_, path) = qpath {
337 if let hir::def::Res::Local(hir_id) = path.res {
338 let span = tcx.hir().span(hir_id);
339 let snippet = tcx.sess.source_map().span_to_snippet(span);
340 let filename = tcx.sess.source_map().span_to_filename(span);
342 let parent_node = self
345 .get(self.tcx.hir().get_parent_node(hir_id));
347 "you must specify a type for this binding, like `{}`",
351 match (filename, parent_node, snippet) {
354 Node::Local(hir::Local {
355 source: hir::LocalSource::Normal,
362 // account for `let x: _ = 42;`
369 format!("{}: {}", snippet, concrete_type),
370 Applicability::MaybeIncorrect,
374 err.span_label(span, msg);
385 span = item_name.span;
386 let mut err = struct_span_err!(
390 "no {} named `{}` found for {} `{}` in the current scope",
393 actual.prefix_string(self.tcx),
396 if let Mode::MethodCall = mode {
397 if let SelfSource::MethodCall(call) = source {
398 self.suggest_await_before_method(
399 &mut err, item_name, actual, call, span,
404 tcx.sess.confused_type_with_std_module.borrow().get(&span)
406 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
409 "you are looking for the module in `std`, \
410 not the primitive type",
411 format!("std::{}", snippet),
412 Applicability::MachineApplicable,
416 if let ty::RawPtr(_) = &actual.kind() {
418 "try using `<*const T>::as_ref()` to get a reference to the \
419 type behind the pointer: https://doc.rust-lang.org/std/\
420 primitive.pointer.html#method.as_ref",
423 "using `<*const T>::as_ref()` on a pointer \
424 which is unaligned or points to invalid \
425 or uninitialized memory is undefined behavior",
431 tcx.sess.diagnostic().struct_dummy()
434 if let Some(def) = actual.ty_adt_def() {
435 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
436 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
440 "{} `{}` not found {}",
443 if def.is_enum() && !is_method { "here" } else { "for this" }
449 let mut label_span_not_found = || {
450 if unsatisfied_predicates.is_empty() {
451 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
453 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
455 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
458 // If the method name is the name of a field with a function or closure type,
459 // give a helping note that it has to be called as `(x.f)(...)`.
460 if let SelfSource::MethodCall(expr) = source {
462 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
463 ty::Adt(def, substs) if !def.is_enum() => {
464 let variant = &def.non_enum_variant();
465 self.tcx.find_field_index(item_name, variant).map(|index| {
466 let field = &variant.fields[index];
467 let field_ty = field.ty(tcx, substs);
474 if let Some((field, field_ty)) = field_receiver {
475 let scope = self.tcx.parent_module(self.body_id).to_def_id();
476 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
479 if self.is_fn_ty(&field_ty, span) {
480 let expr_span = expr.span.to(item_name.span);
481 err.multipart_suggestion(
483 "to call the function stored in `{}`, \
484 surround the field access with parentheses",
488 (expr_span.shrink_to_lo(), '('.to_string()),
489 (expr_span.shrink_to_hi(), ')'.to_string()),
491 Applicability::MachineApplicable,
497 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
499 if let Some(span) = call_expr.span.trim_start(item_name.span) {
502 "remove the arguments",
504 Applicability::MaybeIncorrect,
510 let field_kind = if is_accessible { "field" } else { "private field" };
511 err.span_label(item_name.span, format!("{}, not a method", field_kind));
512 } else if lev_candidate.is_none() && static_sources.is_empty() {
513 label_span_not_found();
516 label_span_not_found();
519 if self.is_fn_ty(&rcvr_ty, span) {
520 fn report_function<T: std::fmt::Display>(
521 err: &mut DiagnosticBuilder<'_>,
525 &format!("`{}` is a function, perhaps you wish to call it", name,),
529 if let SelfSource::MethodCall(expr) = source {
530 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
531 report_function(&mut err, expr_string);
532 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
533 if let Some(segment) = path.segments.last() {
534 report_function(&mut err, segment.ident);
540 if !static_sources.is_empty() {
542 "found the following associated functions; to be used as methods, \
543 functions must have a `self` parameter",
545 err.span_label(span, "this is an associated function, not a method");
547 if static_sources.len() == 1 {
548 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
549 static_sources.get(0)
551 // When the "method" is resolved through dereferencing, we really want the
552 // original type that has the associated function for accurate suggestions.
554 let ty = tcx.at(span).type_of(*impl_did);
555 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
556 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
557 // Use `actual` as it will have more `substs` filled in.
558 self.ty_to_value_string(actual.peel_refs())
560 _ => self.ty_to_value_string(ty.peel_refs()),
563 self.ty_to_value_string(actual.peel_refs())
565 if let SelfSource::MethodCall(expr) = source {
568 "use associated function syntax instead",
569 format!("{}::{}", ty_str, item_name),
570 Applicability::MachineApplicable,
573 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
576 report_candidates(span, &mut err, static_sources, sugg_span);
577 } else if static_sources.len() > 1 {
578 report_candidates(span, &mut err, static_sources, sugg_span);
581 let mut restrict_type_params = false;
582 let mut unsatisfied_bounds = false;
583 if !unsatisfied_predicates.is_empty() {
584 let def_span = |def_id| {
585 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
587 let mut type_params = FxHashMap::default();
588 let mut bound_spans = vec![];
590 let mut collect_type_param_suggestions =
591 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
592 // We don't care about regions here, so it's fine to skip the binder here.
593 if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
594 (self_ty.kind(), parent_pred.kind().skip_binder())
596 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
597 let node = def.did.as_local().map(|def_id| {
600 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
602 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
603 if let Some(g) = kind.generics() {
604 let key = match g.where_clause.predicates {
605 [.., pred] => (pred.span().shrink_to_hi(), false),
608 .span_for_predicates_or_empty_place(),
614 .or_insert_with(FxHashSet::default)
615 .insert(obligation.to_owned());
621 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
623 "doesn't satisfy `{}`",
624 if obligation.len() > 50 { quiet } else { obligation }
626 match &self_ty.kind() {
627 // Point at the type that couldn't satisfy the bound.
628 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
629 // Point at the trait object that couldn't satisfy the bound.
630 ty::Dynamic(preds, _) => {
631 for pred in preds.iter() {
632 match pred.skip_binder() {
633 ty::ExistentialPredicate::Trait(tr) => {
634 bound_spans.push((def_span(tr.def_id), msg.clone()))
636 ty::ExistentialPredicate::Projection(_)
637 | ty::ExistentialPredicate::AutoTrait(_) => {}
641 // Point at the closure that couldn't satisfy the bound.
642 ty::Closure(def_id, _) => bound_spans
643 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
647 let mut format_pred = |pred: ty::Predicate<'tcx>| {
648 let bound_predicate = pred.kind();
649 match bound_predicate.skip_binder() {
650 ty::PredicateKind::Projection(pred) => {
651 let pred = bound_predicate.rebind(pred);
652 // `<Foo as Iterator>::Item = String`.
653 let projection_ty = pred.skip_binder().projection_ty;
655 let substs_with_infer_self = tcx.mk_substs(
656 iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
657 .chain(projection_ty.substs.iter().skip(1)),
660 let quiet_projection_ty = ty::ProjectionTy {
661 substs: substs_with_infer_self,
662 item_def_id: projection_ty.item_def_id,
665 let ty = pred.skip_binder().ty;
667 let obligation = format!("{} = {}", projection_ty, ty);
668 let quiet = format!("{} = {}", quiet_projection_ty, ty);
670 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
671 Some((obligation, projection_ty.self_ty()))
673 ty::PredicateKind::Trait(poly_trait_ref, _) => {
674 let p = poly_trait_ref.trait_ref;
675 let self_ty = p.self_ty();
676 let path = p.print_only_trait_path();
677 let obligation = format!("{}: {}", self_ty, path);
678 let quiet = format!("_: {}", path);
679 bound_span_label(self_ty, &obligation, &quiet);
680 Some((obligation, self_ty))
685 let mut bound_list = unsatisfied_predicates
687 .filter_map(|(pred, parent_pred)| {
688 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
689 None => format!("`{}`", &p),
690 Some(parent_pred) => match format_pred(*parent_pred) {
691 None => format!("`{}`", &p),
692 Some((parent_p, _)) => {
693 collect_type_param_suggestions(self_ty, parent_pred, &p);
694 format!("`{}`\nwhich is required by `{}`", p, parent_p)
700 .collect::<Vec<(usize, String)>>();
701 for ((span, empty_where), obligations) in type_params.into_iter() {
702 restrict_type_params = true;
703 // #74886: Sort here so that the output is always the same.
704 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
706 err.span_suggestion_verbose(
709 "consider restricting the type parameter{s} to satisfy the \
711 s = pluralize!(obligations.len())
715 if empty_where { " where" } else { "," },
716 obligations.join(", ")
718 Applicability::MaybeIncorrect,
722 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
723 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
724 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
727 for (span, msg) in bound_spans.into_iter() {
728 err.span_label(span, &msg);
730 if !bound_list.is_empty() {
731 let bound_list = bound_list
733 .map(|(_, path)| path)
736 let actual_prefix = actual.prefix_string(self.tcx);
737 err.set_primary_message(&format!(
738 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
741 "the following trait bounds were not satisfied:\n{bound_list}"
743 unsatisfied_bounds = true;
747 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
749 self.suggest_traits_to_import(
756 &unsatisfied_predicates,
761 // Don't emit a suggestion if we found an actual method
762 // that had unsatisfied trait bounds
763 if unsatisfied_predicates.is_empty() && actual.is_enum() {
764 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
765 if let Some(suggestion) = lev_distance::find_best_match_for_name(
766 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
772 "there is a variant with a similar name",
773 suggestion.to_string(),
774 Applicability::MaybeIncorrect,
779 let mut fallback_span = true;
780 let msg = "remove this method call";
781 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
782 if let SelfSource::MethodCall(expr) = source {
784 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
785 if let Some(span) = call_expr.span.trim_start(expr.span) {
790 Applicability::MachineApplicable,
792 fallback_span = false;
796 err.span_label(span, msg);
798 } else if let Some(lev_candidate) = lev_candidate {
799 // Don't emit a suggestion if we found an actual method
800 // that had unsatisfied trait bounds
801 if unsatisfied_predicates.is_empty() {
802 let def_kind = lev_candidate.kind.as_def_kind();
806 "there is {} {} with a similar name",
808 def_kind.descr(lev_candidate.def_id),
810 lev_candidate.ident.to_string(),
811 Applicability::MaybeIncorrect,
819 MethodError::Ambiguity(sources) => {
820 let mut err = struct_span_err!(
824 "multiple applicable items in scope"
826 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
828 report_candidates(span, &mut err, sources, sugg_span);
832 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
833 let kind = kind.descr(def_id);
834 let mut err = struct_span_err!(
838 "{} `{}` is private",
842 err.span_label(item_name.span, &format!("private {}", kind));
843 self.suggest_valid_traits(&mut err, out_of_scope_traits);
847 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
848 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
849 let mut err = self.sess().struct_span_err(span, &msg);
850 err.span_label(bound_span, "this has a `Sized` requirement");
851 if !candidates.is_empty() {
853 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
854 add a `use` for {one_of_them}:",
855 an = if candidates.len() == 1 { "an" } else { "" },
856 s = pluralize!(candidates.len()),
857 were = if candidates.len() == 1 { "was" } else { "were" },
858 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
860 self.suggest_use_candidates(&mut err, help, candidates);
862 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
864 let trait_type = self.tcx.mk_ref(
866 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
868 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
874 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
879 /// Print out the type for use in value namespace.
880 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
882 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
883 _ => self.ty_to_string(ty),
887 fn suggest_await_before_method(
889 err: &mut DiagnosticBuilder<'_>,
892 call: &hir::Expr<'_>,
895 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
896 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
899 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
900 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
902 err.span_suggestion_verbose(
904 "consider `await`ing on the `Future` and calling the method on its `Output`",
905 "await.".to_string(),
906 Applicability::MaybeIncorrect,
911 fn suggest_use_candidates(
913 err: &mut DiagnosticBuilder<'_>,
915 candidates: Vec<DefId>,
917 let module_did = self.tcx.parent_module(self.body_id);
918 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
919 let krate = self.tcx.hir().krate();
920 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
921 if let Some(span) = span {
922 let path_strings = candidates.iter().map(|did| {
923 // Produce an additional newline to separate the new use statement
924 // from the directly following item.
925 let additional_newline = if found_use { "" } else { "\n" };
928 with_crate_prefix(|| self.tcx.def_path_str(*did)),
933 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
935 let limit = if candidates.len() == 5 { 5 } else { 4 };
936 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
937 if candidates.len() > 1 {
938 msg.push_str(&format!(
939 "\ncandidate #{}: `use {};`",
941 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
944 msg.push_str(&format!(
946 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
950 if candidates.len() > limit {
951 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
957 fn suggest_valid_traits(
959 err: &mut DiagnosticBuilder<'_>,
960 valid_out_of_scope_traits: Vec<DefId>,
962 if !valid_out_of_scope_traits.is_empty() {
963 let mut candidates = valid_out_of_scope_traits;
966 err.help("items from traits can only be used if the trait is in scope");
968 "the following {traits_are} implemented but not in scope; \
969 perhaps add a `use` for {one_of_them}:",
970 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
971 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
974 self.suggest_use_candidates(err, msg, candidates);
981 fn suggest_traits_to_import(
983 err: &mut DiagnosticBuilder<'_>,
987 source: SelfSource<'tcx>,
988 valid_out_of_scope_traits: Vec<DefId>,
989 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
990 unsatisfied_bounds: bool,
992 let mut alt_rcvr_sugg = false;
993 if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
994 debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
996 self.tcx.lang_items().clone_trait(),
997 self.tcx.lang_items().deref_trait(),
998 self.tcx.lang_items().deref_mut_trait(),
999 self.tcx.lang_items().drop_trait(),
1001 // Try alternative arbitrary self types that could fulfill this call.
1002 // FIXME: probe for all types that *could* be arbitrary self-types, not
1004 for (rcvr_ty, post) in &[
1006 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
1007 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
1009 if let Ok(pick) = self.lookup_probe(
1014 crate::check::method::probe::ProbeScope::AllTraits,
1016 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1017 // We point at the method, but we just skip the rest of the check for arbitrary
1018 // self types and rely on the suggestion to `use` the trait from
1019 // `suggest_valid_traits`.
1020 let did = Some(pick.item.container.id());
1021 let skip = skippable.contains(&did);
1022 if pick.autoderefs == 0 && !skip {
1024 pick.item.ident.span,
1025 &format!("the method is available for `{}` here", rcvr_ty),
1030 for (rcvr_ty, pre) in &[
1031 (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1032 (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1033 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1034 (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1036 if let Some(new_rcvr_t) = *rcvr_ty {
1037 if let Ok(pick) = self.lookup_probe(
1042 crate::check::method::probe::ProbeScope::AllTraits,
1044 debug!("try_alt_rcvr: pick candidate {:?}", pick);
1045 let did = Some(pick.item.container.id());
1046 // We don't want to suggest a container type when the missing
1047 // method is `.clone()` or `.deref()` otherwise we'd suggest
1048 // `Arc::new(foo).clone()`, which is far from what the user wants.
1049 let skip = skippable.contains(&did);
1050 // Make sure the method is defined for the *actual* receiver: we don't
1051 // want to treat `Box<Self>` as a receiver if it only works because of
1052 // an autoderef to `&self`
1053 if pick.autoderefs == 0 && !skip {
1055 pick.item.ident.span,
1056 &format!("the method is available for `{}` here", new_rcvr_t),
1058 err.multipart_suggestion(
1059 "consider wrapping the receiver expression with the \
1062 (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1063 (rcvr.span.shrink_to_hi(), ")".to_string()),
1065 Applicability::MaybeIncorrect,
1067 // We don't care about the other suggestions.
1068 alt_rcvr_sugg = true;
1075 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1079 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1081 let mut arbitrary_rcvr = vec![];
1082 // There are no traits implemented, so lets suggest some traits to
1083 // implement, by finding ones that have the item name, and are
1084 // legal to implement.
1085 let mut candidates = all_traits(self.tcx)
1087 // Don't issue suggestions for unstable traits since they're
1088 // unlikely to be implementable anyway
1089 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1090 Some(attr) => attr.level.is_stable(),
1094 // We approximate the coherence rules to only suggest
1095 // traits that are legal to implement by requiring that
1096 // either the type or trait is local. Multi-dispatch means
1097 // this isn't perfect (that is, there are cases when
1098 // implementing a trait would be legal but is rejected
1100 unsatisfied_predicates.iter().all(|(p, _)| {
1101 match p.kind().skip_binder() {
1102 // Hide traits if they are present in predicates as they can be fixed without
1103 // having to implement them.
1104 ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
1105 ty::PredicateKind::Projection(p) => {
1106 p.projection_ty.item_def_id == info.def_id
1110 }) && (type_is_local || info.def_id.is_local())
1112 .associated_item(info.def_id, item_name, Namespace::ValueNS)
1114 if let ty::AssocKind::Fn = item.kind {
1118 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1119 if let Some(hir::Node::TraitItem(hir::TraitItem {
1120 kind: hir::TraitItemKind::Fn(fn_sig, method),
1122 })) = id.map(|id| self.tcx.hir().get(id))
1124 let self_first_arg = match method {
1125 hir::TraitFn::Required([ident, ..]) => {
1126 ident.name == kw::SelfLower
1128 hir::TraitFn::Provided(body_id) => {
1129 self.tcx.hir().body(*body_id).params.first().map_or(
1134 hir::PatKind::Binding(_, _, ident, _)
1135 if ident.name == kw::SelfLower
1143 if !fn_sig.decl.implicit_self.has_implicit_self()
1146 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1147 arbitrary_rcvr.push(ty.span);
1153 // We only want to suggest public or local traits (#45781).
1154 item.vis == ty::Visibility::Public || info.def_id.is_local()
1158 .collect::<Vec<_>>();
1159 for span in &arbitrary_rcvr {
1162 "the method might not be found because of this arbitrary self type",
1169 if !candidates.is_empty() {
1170 // Sort from most relevant to least relevant.
1171 candidates.sort_by(|a, b| a.cmp(b).reverse());
1174 let param_type = match rcvr_ty.kind() {
1175 ty::Param(param) => Some(param),
1176 ty::Ref(_, ty, _) => match ty.kind() {
1177 ty::Param(param) => Some(param),
1182 err.help(if param_type.is_some() {
1183 "items from traits can only be used if the type parameter is bounded by the trait"
1185 "items from traits can only be used if the trait is implemented and in scope"
1187 let candidates_len = candidates.len();
1188 let message = |action| {
1190 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1193 if candidates_len == 1 { "trait defines" } else { "traits define" },
1195 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1199 // Obtain the span for `param` and use it for a structured suggestion.
1200 if let (Some(ref param), Some(ref table)) =
1201 (param_type, self.in_progress_typeck_results)
1203 let table_owner = table.borrow().hir_owner;
1204 let generics = self.tcx.generics_of(table_owner.to_def_id());
1205 let type_param = generics.type_param(param, self.tcx);
1206 let hir = &self.tcx.hir();
1207 if let Some(def_id) = type_param.def_id.as_local() {
1208 let id = hir.local_def_id_to_hir_id(def_id);
1209 // Get the `hir::Param` to verify whether it already has any bounds.
1210 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1211 // instead we suggest `T: Foo + Bar` in that case.
1213 Node::GenericParam(ref param) => {
1214 let mut impl_trait = false;
1216 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1219 // We've found `fn foo(x: impl Trait)` instead of
1220 // `fn foo<T>(x: T)`. We want to suggest the correct
1221 // `fn foo(x: impl Trait + TraitBound)` instead of
1222 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1228 let sp = hir.span(id);
1229 let sp = if let Some(first_bound) = has_bounds {
1230 // `sp` only covers `T`, change it so that it covers
1231 // `T:` when appropriate
1232 sp.until(first_bound.span())
1236 let trait_def_ids: FxHashSet<DefId> = param
1239 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1241 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1242 err.span_suggestions(
1245 "restrict type parameter `{}` with",
1248 candidates.iter().map(|t| {
1252 if impl_trait { " +" } else { ":" },
1253 self.tcx.def_path_str(t.def_id),
1254 if has_bounds.is_some() { " + " } else { "" },
1257 Applicability::MaybeIncorrect,
1262 Node::Item(hir::Item {
1263 kind: hir::ItemKind::Trait(.., bounds, _),
1267 let (sp, sep, article) = if bounds.is_empty() {
1268 (ident.span.shrink_to_hi(), ":", "a")
1270 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1272 err.span_suggestions(
1274 &message(format!("add {} supertrait for", article)),
1275 candidates.iter().map(|t| {
1276 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1278 Applicability::MaybeIncorrect,
1287 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1288 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1289 // cases where a positive bound implies a negative impl.
1290 (candidates, Vec::new())
1291 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1292 let mut potential_candidates = Vec::new();
1293 let mut explicitly_negative = Vec::new();
1294 for candidate in candidates {
1295 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1298 .all_impls(candidate.def_id)
1300 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1303 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1304 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1305 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1308 explicitly_negative.push(candidate);
1310 potential_candidates.push(candidate);
1313 (potential_candidates, explicitly_negative)
1315 // We don't know enough about `recv_ty` to make proper suggestions.
1316 (candidates, Vec::new())
1319 let action = if let Some(param) = param_type {
1320 format!("restrict type parameter `{}` with", param)
1322 // FIXME: it might only need to be imported into scope, not implemented.
1323 "implement".to_string()
1325 match &potential_candidates[..] {
1327 [trait_info] if trait_info.def_id.is_local() => {
1328 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1330 self.tcx.sess.source_map().guess_head_span(span),
1332 "`{}` defines an item `{}`, perhaps you need to {} it",
1333 self.tcx.def_path_str(trait_info.def_id),
1340 let mut msg = message(action);
1341 for (i, trait_info) in trait_infos.iter().enumerate() {
1342 msg.push_str(&format!(
1343 "\ncandidate #{}: `{}`",
1345 self.tcx.def_path_str(trait_info.def_id),
1351 match &explicitly_negative[..] {
1355 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1356 self.tcx.def_path_str(trait_info.def_id),
1362 let mut msg = format!(
1363 "the following traits define an item `{}`, but are explicitely unimplemented:",
1366 for trait_info in trait_infos {
1367 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1375 /// Checks whether there is a local type somewhere in the chain of
1376 /// autoderefs of `rcvr_ty`.
1377 fn type_derefs_to_local(
1381 source: SelfSource<'tcx>,
1383 fn is_local(ty: Ty<'_>) -> bool {
1385 ty::Adt(def, _) => def.did.is_local(),
1386 ty::Foreign(did) => did.is_local(),
1387 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1388 ty::Param(_) => true,
1390 // Everything else (primitive types, etc.) is effectively
1391 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1392 // the noise from these sort of types is usually just really
1393 // annoying, rather than any sort of help).
1398 // This occurs for UFCS desugaring of `T::method`, where there is no
1399 // receiver expression for the method call, and thus no autoderef.
1400 if let SelfSource::QPath(_) = source {
1401 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1404 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1408 #[derive(Copy, Clone, Debug)]
1409 pub enum SelfSource<'a> {
1410 QPath(&'a hir::Ty<'a>),
1411 MethodCall(&'a hir::Expr<'a> /* rcvr */),
1414 #[derive(Copy, Clone)]
1415 pub struct TraitInfo {
1419 impl PartialEq for TraitInfo {
1420 fn eq(&self, other: &TraitInfo) -> bool {
1421 self.cmp(other) == Ordering::Equal
1424 impl Eq for TraitInfo {}
1425 impl PartialOrd for TraitInfo {
1426 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1427 Some(self.cmp(other))
1430 impl Ord for TraitInfo {
1431 fn cmp(&self, other: &TraitInfo) -> Ordering {
1432 // Local crates are more important than remote ones (local:
1433 // `cnum == 0`), and otherwise we throw in the defid for totality.
1435 let lhs = (other.def_id.krate, other.def_id);
1436 let rhs = (self.def_id.krate, self.def_id);
1441 /// Retrieves all traits in this crate and any dependent crates.
1442 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1443 tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
1446 /// Computes all traits in this crate and any dependent crates.
1447 fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
1448 use hir::itemlikevisit;
1450 let mut traits = vec![];
1454 struct Visitor<'a> {
1455 traits: &'a mut Vec<DefId>,
1458 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1459 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1461 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1462 self.traits.push(i.def_id.to_def_id());
1468 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1470 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1472 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1475 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1479 let mut external_mods = FxHashSet::default();
1480 fn handle_external_res(
1482 traits: &mut Vec<DefId>,
1483 external_mods: &mut FxHashSet<DefId>,
1487 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1488 traits.push(def_id);
1490 Res::Def(DefKind::Mod, def_id) => {
1491 if !external_mods.insert(def_id) {
1494 for child in tcx.item_children(def_id).iter() {
1495 handle_external_res(tcx, traits, external_mods, child.res)
1501 for &cnum in tcx.crates().iter() {
1502 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1503 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1506 tcx.arena.alloc_from_iter(traits)
1509 pub fn provide(providers: &mut ty::query::Providers) {
1510 providers.all_traits = compute_all_traits;
1513 struct UsePlacementFinder<'tcx> {
1514 target_module: hir::HirId,
1520 impl UsePlacementFinder<'tcx> {
1523 krate: &'tcx hir::Crate<'tcx>,
1524 target_module: hir::HirId,
1525 ) -> (Option<Span>, bool) {
1526 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1527 intravisit::walk_crate(&mut finder, krate);
1528 (finder.span, finder.found_use)
1532 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1533 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1534 if self.span.is_some() {
1537 if hir_id != self.target_module {
1538 intravisit::walk_mod(self, module, hir_id);
1541 // Find a `use` statement.
1542 for &item_id in module.item_ids {
1543 let item = self.tcx.hir().item(item_id);
1545 hir::ItemKind::Use(..) => {
1546 // Don't suggest placing a `use` before the prelude
1547 // import or other generated ones.
1548 if !item.span.from_expansion() {
1549 self.span = Some(item.span.shrink_to_lo());
1550 self.found_use = true;
1554 // Don't place `use` before `extern crate`...
1555 hir::ItemKind::ExternCrate(_) => {}
1556 // ...but do place them before the first other item.
1558 if self.span.map_or(true, |span| item.span < span) {
1559 if !item.span.from_expansion() {
1560 // Don't insert between attributes and an item.
1561 let attrs = self.tcx.hir().attrs(item.hir_id());
1562 if attrs.is_empty() {
1563 self.span = Some(item.span.shrink_to_lo());
1565 // Find the first attribute on the item.
1567 if self.span.map_or(true, |span| attr.span < span) {
1568 self.span = Some(attr.span.shrink_to_lo());
1579 type Map = intravisit::ErasedMap<'tcx>;
1581 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1582 intravisit::NestedVisitorMap::None
1586 fn print_disambiguation_help(
1588 args: Option<&'tcx [hir::Expr<'tcx>]>,
1589 err: &mut DiagnosticBuilder<'_>,
1592 kind: ty::AssocKind,
1595 candidate: Option<usize>,
1596 source_map: &source_map::SourceMap,
1598 let mut applicability = Applicability::MachineApplicable;
1599 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1602 if rcvr_ty.is_region_ptr() {
1603 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1608 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1609 applicability = Applicability::HasPlaceholders;
1612 .collect::<Vec<_>>()
1618 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1619 err.span_suggestion(
1622 "disambiguate the {} for {}",
1623 kind.as_def_kind().descr(def_id),
1624 if let Some(candidate) = candidate {
1625 format!("candidate #{}", candidate)
1627 "the candidate".to_string()