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}
;
7 pluralize
, struct_span_err
, Applicability
, Diagnostic
, DiagnosticBuilder
, ErrorGuaranteed
,
11 use rustc_hir
::def
::DefKind
;
12 use rustc_hir
::def_id
::DefId
;
13 use rustc_hir
::lang_items
::LangItem
;
14 use rustc_hir
::{ExprKind, Node, QPath}
;
15 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
16 use rustc_middle
::traits
::util
::supertraits
;
17 use rustc_middle
::ty
::fast_reject
::{simplify_type, TreatParams}
;
18 use rustc_middle
::ty
::print
::with_crate_prefix
;
19 use rustc_middle
::ty
::ToPolyTraitRef
;
20 use rustc_middle
::ty
::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable}
;
21 use rustc_span
::symbol
::{kw, sym, Ident}
;
22 use rustc_span
::Symbol
;
23 use rustc_span
::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}
;
24 use rustc_trait_selection
::traits
::error_reporting
::on_unimplemented
::InferCtxtExt
as _
;
25 use rustc_trait_selection
::traits
::query
::evaluate_obligation
::InferCtxtExt
as _
;
26 use rustc_trait_selection
::traits
::{
27 FulfillmentError
, Obligation
, ObligationCause
, ObligationCauseCode
, OnUnimplementedNote
,
30 use std
::cmp
::Ordering
;
33 use super::probe
::{Mode, ProbeScope}
;
34 use super::{super::suggest_call_constructor, CandidateSource, MethodError, NoMatchData}
;
36 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
37 fn is_fn_ty(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
40 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
41 // so we look for these beforehand.
42 ty
::Closure(..) | ty
::FnDef(..) | ty
::FnPtr(_
) => true,
43 // If it's not a simple function, look for things which implement `FnOnce`.
45 let Some(fn_once
) = tcx
.lang_items().fn_once_trait() else {
49 // This conditional prevents us from asking to call errors and unresolved types.
50 // It might seem that we can use `predicate_must_hold_modulo_regions`,
51 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
52 // type resolution always gives a "maybe" here.
53 if self.autoderef(span
, ty
).any(|(ty
, _
)| {
54 info
!("check deref {:?} error", ty
);
55 matches
!(ty
.kind(), ty
::Error(_
) | ty
::Infer(_
))
60 self.autoderef(span
, ty
).any(|(ty
, _
)| {
61 info
!("check deref {:?} impl FnOnce", ty
);
63 let fn_once_substs
= tcx
.mk_substs_trait(
66 .next_ty_var(TypeVariableOrigin
{
67 kind
: TypeVariableOriginKind
::MiscVariable
,
72 let trait_ref
= ty
::TraitRef
::new(fn_once
, fn_once_substs
);
73 let poly_trait_ref
= ty
::Binder
::dummy(trait_ref
);
74 let obligation
= Obligation
::misc(
78 poly_trait_ref
.without_const().to_predicate(tcx
),
80 self.predicate_may_hold(&obligation
)
87 fn is_slice_ty(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
88 self.autoderef(span
, ty
).any(|(ty
, _
)| matches
!(ty
.kind(), ty
::Slice(..) | ty
::Array(..)))
91 pub fn report_method_error(
96 source
: SelfSource
<'tcx
>,
97 error
: MethodError
<'tcx
>,
98 args
: Option
<&'tcx
[hir
::Expr
<'tcx
>]>,
99 ) -> Option
<DiagnosticBuilder
<'_
, ErrorGuaranteed
>> {
100 // Avoid suggestions when we don't know what's going on.
101 if rcvr_ty
.references_error() {
105 let report_candidates
= |span
: Span
,
106 err
: &mut Diagnostic
,
107 mut sources
: Vec
<CandidateSource
>,
111 // Dynamic limit to avoid hiding just one candidate, which is silly.
112 let limit
= if sources
.len() == 5 { 5 }
else { 4 }
;
114 for (idx
, source
) in sources
.iter().take(limit
).enumerate() {
116 CandidateSource
::Impl(impl_did
) => {
117 // Provide the best span we can. Use the item, if local to crate, else
118 // the impl, if local to crate (item may be defaulted), else nothing.
119 let Some(item
) = self.associated_value(impl_did
, item_name
).or_else(|| {
120 let impl_trait_ref
= self.tcx
.impl_trait_ref(impl_did
)?
;
121 self.associated_value(impl_trait_ref
.def_id
, item_name
)
126 let note_span
= if item
.def_id
.is_local() {
127 Some(self.tcx
.def_span(item
.def_id
))
128 } else if impl_did
.is_local() {
129 Some(self.tcx
.def_span(impl_did
))
134 let impl_ty
= self.tcx
.at(span
).type_of(impl_did
);
136 let insertion
= match self.tcx
.impl_trait_ref(impl_did
) {
137 None
=> String
::new(),
138 Some(trait_ref
) => format
!(
139 " of the trait `{}`",
140 self.tcx
.def_path_str(trait_ref
.def_id
)
144 let (note_str
, idx
) = if sources
.len() > 1 {
147 "candidate #{} is defined in an impl{} for the type `{}`",
157 "the candidate is defined in an impl{} for the type `{}`",
163 if let Some(note_span
) = note_span
{
164 // We have a span pointing to the method. Show note with snippet.
165 err
.span_note(note_span
, ¬e_str
);
169 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_did
) {
170 let path
= self.tcx
.def_path_str(trait_ref
.def_id
);
172 let ty
= match item
.kind
{
173 ty
::AssocKind
::Const
| ty
::AssocKind
::Type
=> rcvr_ty
,
174 ty
::AssocKind
::Fn
=> self
180 .filter(|ty
| ty
.is_region_ptr() && !rcvr_ty
.is_region_ptr())
184 print_disambiguation_help(
194 self.tcx
.sess
.source_map(),
195 item
.fn_has_self_parameter
,
199 CandidateSource
::Trait(trait_did
) => {
200 let Some(item
) = self.associated_value(trait_did
, item_name
) else { continue }
;
201 let item_span
= self.tcx
.def_span(item
.def_id
);
202 let idx
= if sources
.len() > 1 {
204 "candidate #{} is defined in the trait `{}`",
206 self.tcx
.def_path_str(trait_did
)
208 err
.span_note(item_span
, msg
);
212 "the candidate is defined in the trait `{}`",
213 self.tcx
.def_path_str(trait_did
)
215 err
.span_note(item_span
, msg
);
218 let path
= self.tcx
.def_path_str(trait_did
);
219 print_disambiguation_help(
229 self.tcx
.sess
.source_map(),
230 item
.fn_has_self_parameter
,
235 if sources
.len() > limit
{
236 err
.note(&format
!("and {} others", sources
.len() - limit
));
240 let sugg_span
= if let SelfSource
::MethodCall(expr
) = source
{
241 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
242 self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
)).span
248 MethodError
::NoMatch(NoMatchData
{
249 static_candidates
: static_sources
,
250 unsatisfied_predicates
,
257 let actual
= self.resolve_vars_if_possible(rcvr_ty
);
258 let ty_str
= self.ty_to_string(actual
);
259 let is_method
= mode
== Mode
::MethodCall
;
260 let item_kind
= if is_method
{
262 } else if actual
.is_enum() {
263 "variant or associated item"
265 match (item_name
.as_str().chars().next(), actual
.is_fresh_ty()) {
266 (Some(name
), false) if name
.is_lowercase() => "function or associated item",
267 (Some(_
), false) => "associated item",
268 (Some(_
), true) | (None
, false) => "variant or associated item",
269 (None
, true) => "variant",
273 if self.suggest_constraining_numerical_ty(
274 tcx
, actual
, source
, span
, item_kind
, item_name
, &ty_str
,
279 span
= item_name
.span
;
281 // Don't show generic arguments when the method can't be found in any implementation (#81576).
282 let mut ty_str_reported
= ty_str
.clone();
283 if let ty
::Adt(_
, generics
) = actual
.kind() {
284 if generics
.len() > 0 {
285 let mut autoderef
= self.autoderef(span
, actual
);
286 let candidate_found
= autoderef
.any(|(ty
, _
)| {
287 if let ty
::Adt(adt_deref
, _
) = ty
.kind() {
289 .inherent_impls(adt_deref
.did())
291 .filter_map(|def_id
| self.associated_value(*def_id
, item_name
))
298 let has_deref
= autoderef
.step_count() > 0;
299 if !candidate_found
&& !has_deref
&& unsatisfied_predicates
.is_empty() {
300 if let Some((path_string
, _
)) = ty_str
.split_once('
<'
) {
301 ty_str_reported
= path_string
.to_string();
307 let mut err
= struct_span_err
!(
311 "no {} named `{}` found for {} `{}` in the current scope",
314 actual
.prefix_string(self.tcx
),
317 if actual
.references_error() {
318 err
.downgrade_to_delayed_bug();
321 if let Mode
::MethodCall
= mode
&& let SelfSource
::MethodCall(cal
) = source
{
322 self.suggest_await_before_method(
323 &mut err
, item_name
, actual
, cal
, span
,
326 if let Some(span
) = tcx
.resolutions(()).confused_type_with_std_module
.get(&span
) {
329 "you are looking for the module in `std`, not the primitive type",
331 Applicability
::MachineApplicable
,
334 if let ty
::RawPtr(_
) = &actual
.kind() {
336 "try using `<*const T>::as_ref()` to get a reference to the \
337 type behind the pointer: https://doc.rust-lang.org/std/\
338 primitive.pointer.html#method.as_ref",
341 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
342 to invalid or uninitialized memory is undefined behavior",
346 let ty_span
= match actual
.kind() {
347 ty
::Param(param_type
) => {
348 let generics
= self.tcx
.generics_of(self.body_id
.owner
.to_def_id());
349 let type_param
= generics
.type_param(param_type
, self.tcx
);
350 Some(self.tcx
.def_span(type_param
.def_id
))
352 ty
::Adt(def
, _
) if def
.did().is_local() => Some(tcx
.def_span(def
.did())),
356 if let Some(span
) = ty_span
{
360 "{item_kind} `{item_name}` not found for this {}",
361 actual
.prefix_string(self.tcx
)
366 if self.is_fn_ty(rcvr_ty
, span
) {
367 if let SelfSource
::MethodCall(expr
) = source
{
368 let suggest
= if let ty
::FnDef(def_id
, _
) = rcvr_ty
.kind() {
369 if let Some(local_id
) = def_id
.as_local() {
370 let hir_id
= tcx
.hir().local_def_id_to_hir_id(local_id
);
371 let node
= tcx
.hir().get(hir_id
);
372 let fields
= node
.tuple_fields();
373 if let Some(fields
) = fields
374 && let Some(DefKind
::Ctor(of
, _
)) = self.tcx
.opt_def_kind(local_id
) {
375 Some((fields
.len(), of
))
380 // The logic here isn't smart but `associated_item_def_ids`
381 // doesn't work nicely on local.
382 if let DefKind
::Ctor(of
, _
) = tcx
.def_kind(def_id
) {
383 let parent_def_id
= tcx
.parent(*def_id
);
384 Some((tcx
.associated_item_def_ids(parent_def_id
).len(), of
))
393 // If the function is a tuple constructor, we recommend that they call it
394 if let Some((fields
, kind
)) = suggest
{
395 suggest_call_constructor(expr
.span
, kind
, fields
, &mut err
);
400 "this is a function, perhaps you wish to call it",
406 let mut custom_span_label
= false;
408 if !static_sources
.is_empty() {
410 "found the following associated functions; to be used as methods, \
411 functions must have a `self` parameter",
413 err
.span_label(span
, "this is an associated function, not a method");
414 custom_span_label
= true;
416 if static_sources
.len() == 1 {
418 if let Some(CandidateSource
::Impl(impl_did
)) = static_sources
.get(0) {
419 // When the "method" is resolved through dereferencing, we really want the
420 // original type that has the associated function for accurate suggestions.
422 let ty
= tcx
.at(span
).type_of(*impl_did
);
423 match (&ty
.peel_refs().kind(), &actual
.peel_refs().kind()) {
424 (ty
::Adt(def
, _
), ty
::Adt(def_actual
, _
)) if def
== def_actual
=> {
425 // Use `actual` as it will have more `substs` filled in.
426 self.ty_to_value_string(actual
.peel_refs())
428 _
=> self.ty_to_value_string(ty
.peel_refs()),
431 self.ty_to_value_string(actual
.peel_refs())
433 if let SelfSource
::MethodCall(expr
) = source
{
436 "use associated function syntax instead",
437 format
!("{}::{}", ty_str
, item_name
),
438 Applicability
::MachineApplicable
,
441 err
.help(&format
!("try with `{}::{}`", ty_str
, item_name
,));
444 report_candidates(span
, &mut err
, static_sources
, sugg_span
);
445 } else if static_sources
.len() > 1 {
446 report_candidates(span
, &mut err
, static_sources
, sugg_span
);
449 let mut bound_spans
= vec
![];
450 let mut restrict_type_params
= false;
451 let mut unsatisfied_bounds
= false;
452 if item_name
.name
== sym
::count
&& self.is_slice_ty(actual
, span
) {
453 let msg
= "consider using `len` instead";
454 if let SelfSource
::MethodCall(_expr
) = source
{
455 err
.span_suggestion_short(
459 Applicability
::MachineApplicable
,
462 err
.span_label(span
, msg
);
464 if let Some(iterator_trait
) = self.tcx
.get_diagnostic_item(sym
::Iterator
) {
465 let iterator_trait
= self.tcx
.def_path_str(iterator_trait
);
466 err
.note(&format
!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
468 } else if !unsatisfied_predicates
.is_empty() {
469 let mut type_params
= FxHashMap
::default();
471 // Pick out the list of unimplemented traits on the receiver.
472 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
473 let mut unimplemented_traits
= FxHashMap
::default();
474 let mut unimplemented_traits_only
= true;
475 for (predicate
, _parent_pred
, cause
) in &unsatisfied_predicates
{
476 if let (ty
::PredicateKind
::Trait(p
), Some(cause
)) =
477 (predicate
.kind().skip_binder(), cause
.as_ref())
479 if p
.trait_ref
.self_ty() != rcvr_ty
{
480 // This is necessary, not just to keep the errors clean, but also
481 // because our derived obligations can wind up with a trait ref that
482 // requires a different param_env to be correctly compared.
485 unimplemented_traits
.entry(p
.trait_ref
.def_id
).or_insert((
486 predicate
.kind().rebind(p
.trait_ref
),
488 cause
: cause
.clone(),
489 param_env
: self.param_env
,
490 predicate
: *predicate
,
497 // Make sure that, if any traits other than the found ones were involved,
498 // we don't don't report an unimplemented trait.
499 // We don't want to say that `iter::Cloned` is not an iterator, just
500 // because of some non-Clone item being iterated over.
501 for (predicate
, _parent_pred
, _cause
) in &unsatisfied_predicates
{
502 match predicate
.kind().skip_binder() {
503 ty
::PredicateKind
::Trait(p
)
504 if unimplemented_traits
.contains_key(&p
.trait_ref
.def_id
) => {}
506 unimplemented_traits_only
= false;
512 let mut collect_type_param_suggestions
=
513 |self_ty
: Ty
<'tcx
>, parent_pred
: ty
::Predicate
<'tcx
>, obligation
: &str| {
514 // We don't care about regions here, so it's fine to skip the binder here.
515 if let (ty
::Param(_
), ty
::PredicateKind
::Trait(p
)) =
516 (self_ty
.kind(), parent_pred
.kind().skip_binder())
518 let node
= match p
.trait_ref
.self_ty().kind() {
520 // Account for `fn` items like in `issue-35677.rs` to
521 // suggest restricting its type params.
522 let did
= self.tcx
.hir().body_owner_def_id(hir
::BodyId
{
523 hir_id
: self.body_id
,
528 .get(self.tcx
.hir().local_def_id_to_hir_id(did
)),
531 ty
::Adt(def
, _
) => def
.did().as_local().map(|def_id
| {
534 .get(self.tcx
.hir().local_def_id_to_hir_id(def_id
))
538 if let Some(hir
::Node
::Item(hir
::Item { kind, .. }
)) = node
{
539 if let Some(g
) = kind
.generics() {
541 g
.tail_span_for_predicate_suggestion(),
542 g
.add_where_or_trailing_comma(),
546 .or_insert_with(FxHashSet
::default)
547 .insert(obligation
.to_owned());
552 let mut bound_span_label
= |self_ty
: Ty
<'_
>, obligation
: &str, quiet
: &str| {
554 "doesn't satisfy `{}`",
555 if obligation
.len() > 50 { quiet }
else { obligation }
557 match &self_ty
.kind() {
558 // Point at the type that couldn't satisfy the bound.
560 bound_spans
.push((self.tcx
.def_span(def
.did()), msg
))
562 // Point at the trait object that couldn't satisfy the bound.
563 ty
::Dynamic(preds
, _
) => {
564 for pred
in preds
.iter() {
565 match pred
.skip_binder() {
566 ty
::ExistentialPredicate
::Trait(tr
) => bound_spans
567 .push((self.tcx
.def_span(tr
.def_id
), msg
.clone())),
568 ty
::ExistentialPredicate
::Projection(_
)
569 | ty
::ExistentialPredicate
::AutoTrait(_
) => {}
573 // Point at the closure that couldn't satisfy the bound.
574 ty
::Closure(def_id
, _
) => bound_spans
.push((
575 tcx
.def_span(*def_id
),
576 format
!("doesn't satisfy `{}`", quiet
),
581 let mut format_pred
= |pred
: ty
::Predicate
<'tcx
>| {
582 let bound_predicate
= pred
.kind();
583 match bound_predicate
.skip_binder() {
584 ty
::PredicateKind
::Projection(pred
) => {
585 let pred
= bound_predicate
.rebind(pred
);
586 // `<Foo as Iterator>::Item = String`.
587 let projection_ty
= pred
.skip_binder().projection_ty
;
589 let substs_with_infer_self
= tcx
.mk_substs(
590 iter
::once(tcx
.mk_ty_var(ty
::TyVid
::from_u32(0)).into())
591 .chain(projection_ty
.substs
.iter().skip(1)),
594 let quiet_projection_ty
= ty
::ProjectionTy
{
595 substs
: substs_with_infer_self
,
596 item_def_id
: projection_ty
.item_def_id
,
599 let term
= pred
.skip_binder().term
;
601 let obligation
= format
!("{} = {}", projection_ty
, term
);
602 let quiet
= format
!("{} = {}", quiet_projection_ty
, term
);
604 bound_span_label(projection_ty
.self_ty(), &obligation
, &quiet
);
605 Some((obligation
, projection_ty
.self_ty()))
607 ty
::PredicateKind
::Trait(poly_trait_ref
) => {
608 let p
= poly_trait_ref
.trait_ref
;
609 let self_ty
= p
.self_ty();
610 let path
= p
.print_only_trait_path();
611 let obligation
= format
!("{}: {}", self_ty
, path
);
612 let quiet
= format
!("_: {}", path
);
613 bound_span_label(self_ty
, &obligation
, &quiet
);
614 Some((obligation
, self_ty
))
620 // Find all the requirements that come from a local `impl` block.
621 let mut skip_list
: FxHashSet
<_
> = Default
::default();
622 let mut spanned_predicates
: FxHashMap
<MultiSpan
, _
> = Default
::default();
623 for (data
, p
, parent_p
, impl_def_id
, cause
) in unsatisfied_predicates
625 .filter_map(|(p
, parent
, c
)| c
.as_ref().map(|c
| (p
, parent
, c
)))
626 .filter_map(|(p
, parent
, c
)| match c
.code() {
627 ObligationCauseCode
::ImplDerivedObligation(ref data
) => {
628 Some((&data
.derived
, p
, parent
, data
.impl_def_id
, data
))
633 let parent_trait_ref
= data
.parent_trait_pred
;
634 let path
= parent_trait_ref
.print_modifiers_and_trait_path();
635 let tr_self_ty
= parent_trait_ref
.skip_binder().self_ty();
636 let unsatisfied_msg
= "unsatisfied trait bound introduced here";
638 "unsatisfied trait bound introduced in this `derive` macro";
639 match self.tcx
.hir().get_if_local(impl_def_id
) {
640 // Unmet obligation comes from a `derive` macro, point at it once to
641 // avoid multiple span labels pointing at the same place.
642 Some(Node
::Item(hir
::Item
{
643 kind
: hir
::ItemKind
::Trait(..),
647 ident
.span
.ctxt().outer_expn_data().kind
,
648 ExpnKind
::Macro(MacroKind
::Derive
, _
)
651 let span
= ident
.span
.ctxt().outer_expn_data().call_site
;
652 let mut spans
: MultiSpan
= span
.into();
653 spans
.push_span_label(span
, derive_msg
);
654 let entry
= spanned_predicates
.entry(spans
);
655 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
658 Some(Node
::Item(hir
::Item
{
659 kind
: hir
::ItemKind
::Impl(hir
::Impl { of_trait, self_ty, .. }
),
662 self_ty
.span
.ctxt().outer_expn_data().kind
,
663 ExpnKind
::Macro(MacroKind
::Derive
, _
)
665 of_trait
.as_ref().map(|t
| t
671 Some(ExpnKind
::Macro(MacroKind
::Derive
, _
))
674 let span
= self_ty
.span
.ctxt().outer_expn_data().call_site
;
675 let mut spans
: MultiSpan
= span
.into();
676 spans
.push_span_label(span
, derive_msg
);
677 let entry
= spanned_predicates
.entry(spans
);
678 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
681 // Unmet obligation coming from a `trait`.
682 Some(Node
::Item(hir
::Item
{
683 kind
: hir
::ItemKind
::Trait(..),
688 ident
.span
.ctxt().outer_expn_data().kind
,
689 ExpnKind
::Macro(MacroKind
::Derive
, _
)
692 if let Some(pred
) = parent_p
{
693 // Done to add the "doesn't satisfy" `span_label`.
694 let _
= format_pred(*pred
);
697 let mut spans
= if cause
.span
!= *item_span
{
698 let mut spans
: MultiSpan
= cause
.span
.into();
699 spans
.push_span_label(cause
.span
, unsatisfied_msg
);
704 spans
.push_span_label(ident
.span
, "in this trait");
705 let entry
= spanned_predicates
.entry(spans
);
706 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
709 // Unmet obligation coming from an `impl`.
710 Some(Node
::Item(hir
::Item
{
712 hir
::ItemKind
::Impl(hir
::Impl
{
713 of_trait
, self_ty
, generics
, ..
718 self_ty
.span
.ctxt().outer_expn_data().kind
,
719 ExpnKind
::Macro(MacroKind
::Derive
, _
)
721 of_trait
.as_ref().map(|t
| t
727 Some(ExpnKind
::Macro(MacroKind
::Derive
, _
))
731 unsatisfied_predicates
.iter().any(|(pred
, _
, _
)| {
732 match pred
.kind().skip_binder() {
733 ty
::PredicateKind
::Trait(pred
) => {
735 == self.tcx
.lang_items().sized_trait()
736 && pred
.polarity
== ty
::ImplPolarity
::Positive
741 for param
in generics
.params
{
742 if param
.span
== cause
.span
&& sized_pred
{
743 let (sp
, sugg
) = match param
.colon_span
{
744 Some(sp
) => (sp
.shrink_to_hi(), " ?Sized +"),
745 None
=> (param
.span
.shrink_to_hi(), ": ?Sized"),
747 err
.span_suggestion_verbose(
749 "consider relaxing the type parameter's implicit \
752 Applicability
::MachineApplicable
,
756 if let Some(pred
) = parent_p
{
757 // Done to add the "doesn't satisfy" `span_label`.
758 let _
= format_pred(*pred
);
761 let mut spans
= if cause
.span
!= *item_span
{
762 let mut spans
: MultiSpan
= cause
.span
.into();
763 spans
.push_span_label(cause
.span
, unsatisfied_msg
);
766 let mut spans
= Vec
::with_capacity(2);
767 if let Some(trait_ref
) = of_trait
{
768 spans
.push(trait_ref
.path
.span
);
770 spans
.push(self_ty
.span
);
773 if let Some(trait_ref
) = of_trait
{
774 spans
.push_span_label(trait_ref
.path
.span
, "");
776 spans
.push_span_label(self_ty
.span
, "");
778 let entry
= spanned_predicates
.entry(spans
);
779 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
784 let mut spanned_predicates
: Vec
<_
> = spanned_predicates
.into_iter().collect();
785 spanned_predicates
.sort_by_key(|(span
, (_
, _
, _
))| span
.primary_span());
786 for (span
, (_path
, _self_ty
, preds
)) in spanned_predicates
{
787 let mut preds
: Vec
<_
> = preds
789 .filter_map(|pred
| format_pred(*pred
))
790 .map(|(p
, _
)| format
!("`{}`", p
))
794 let msg
= if let [pred
] = &preds
[..] {
795 format
!("trait bound {} was not satisfied", pred
)
798 "the following trait bounds were not satisfied:\n{}",
802 err
.span_note(span
, &msg
);
803 unsatisfied_bounds
= true;
806 // The requirements that didn't have an `impl` span to show.
807 let mut bound_list
= unsatisfied_predicates
809 .filter_map(|(pred
, parent_pred
, _cause
)| {
810 format_pred(*pred
).map(|(p
, self_ty
)| {
811 collect_type_param_suggestions(self_ty
, *pred
, &p
);
814 None
=> format
!("`{}`", &p
),
815 Some(parent_pred
) => match format_pred(*parent_pred
) {
816 None
=> format
!("`{}`", &p
),
817 Some((parent_p
, _
)) => {
818 collect_type_param_suggestions(
824 "`{}`\nwhich is required by `{}`",
834 .filter(|(_
, pred
)| !skip_list
.contains(&pred
))
837 .collect
::<Vec
<(usize, String
)>>();
839 for ((span
, add_where_or_comma
), obligations
) in type_params
.into_iter() {
840 restrict_type_params
= true;
841 // #74886: Sort here so that the output is always the same.
842 let mut obligations
= obligations
.into_iter().collect
::<Vec
<_
>>();
844 err
.span_suggestion_verbose(
847 "consider restricting the type parameter{s} to satisfy the \
849 s
= pluralize
!(obligations
.len())
851 format
!("{} {}", add_where_or_comma
, obligations
.join(", ")),
852 Applicability
::MaybeIncorrect
,
856 bound_list
.sort_by(|(_
, a
), (_
, b
)| a
.cmp(b
)); // Sort alphabetically.
857 bound_list
.dedup_by(|(_
, a
), (_
, b
)| a
== b
); // #35677
858 bound_list
.sort_by_key(|(pos
, _
)| *pos
); // Keep the original predicate order.
860 if !bound_list
.is_empty() || !skip_list
.is_empty() {
861 let bound_list
= bound_list
863 .map(|(_
, path
)| path
)
866 let actual_prefix
= actual
.prefix_string(self.tcx
);
867 info
!("unimplemented_traits.len() == {}", unimplemented_traits
.len());
868 let (primary_message
, label
) =
869 if unimplemented_traits
.len() == 1 && unimplemented_traits_only
{
873 .map(|(_
, (trait_ref
, obligation
))| {
874 if trait_ref
.self_ty().references_error()
875 || actual
.references_error()
880 let OnUnimplementedNote { message, label, .. }
=
881 self.on_unimplemented_note(trait_ref
, &obligation
);
884 .unwrap_or((None
, None
))
888 let primary_message
= primary_message
.unwrap_or_else(|| format
!(
889 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
891 err
.set_primary_message(&primary_message
);
892 if let Some(label
) = label
{
893 custom_span_label
= true;
894 err
.span_label(span
, label
);
896 if !bound_list
.is_empty() {
898 "the following trait bounds were not satisfied:\n{bound_list}"
901 self.suggest_derive(&mut err
, &unsatisfied_predicates
);
903 unsatisfied_bounds
= true;
907 let label_span_not_found
= |err
: &mut DiagnosticBuilder
<'_
, _
>| {
908 if unsatisfied_predicates
.is_empty() {
909 err
.span_label(span
, format
!("{item_kind} not found in `{ty_str}`"));
910 let is_string_or_ref_str
= match actual
.kind() {
911 ty
::Ref(_
, ty
, _
) => {
915 ty
::Adt(adt
, _
) if self.tcx
.is_diagnostic_item(sym
::String
, adt
.did())
918 ty
::Adt(adt
, _
) => self.tcx
.is_diagnostic_item(sym
::String
, adt
.did()),
921 if is_string_or_ref_str
&& item_name
.name
== sym
::iter
{
922 err
.span_suggestion_verbose(
924 "because of the in-memory representation of `&str`, to obtain \
925 an `Iterator` over each of its codepoint use method `chars`",
927 Applicability
::MachineApplicable
,
930 if let ty
::Adt(adt
, _
) = rcvr_ty
.kind() {
931 let mut inherent_impls_candidate
= self
933 .inherent_impls(adt
.did())
937 if let Some(assoc
) = self.associated_value(*def_id
, item_name
) {
938 // Check for both mode is the same so we avoid suggesting
939 // incorrect associated item.
940 match (mode
, assoc
.fn_has_self_parameter
, source
) {
941 (Mode
::MethodCall
, true, SelfSource
::MethodCall(_
)) => {
942 // We check that the suggest type is actually
943 // different from the received one
944 // So we avoid suggestion method with Box<Self>
946 self.tcx
.at(span
).type_of(*def_id
) != actual
947 && self.tcx
.at(span
).type_of(*def_id
) != rcvr_ty
949 (Mode
::Path
, false, _
) => true,
956 .collect
::<Vec
<_
>>();
957 if !inherent_impls_candidate
.is_empty() {
958 inherent_impls_candidate
.sort();
959 inherent_impls_candidate
.dedup();
961 // number of type to shows at most.
962 let limit
= if inherent_impls_candidate
.len() == 5 { 5 }
else { 4 }
;
963 let type_candidates
= inherent_impls_candidate
967 format
!("- `{}`", self.tcx
.at(span
).type_of(*impl_item
))
971 let additional_types
= if inherent_impls_candidate
.len() > limit
{
973 "\nand {} more types",
974 inherent_impls_candidate
.len() - limit
980 "the {item_kind} was found for\n{}{}",
981 type_candidates
, additional_types
986 err
.span_label(span
, format
!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
990 // If the method name is the name of a field with a function or closure type,
991 // give a helping note that it has to be called as `(x.f)(...)`.
992 if let SelfSource
::MethodCall(expr
) = source
{
993 if !self.suggest_field_call(span
, rcvr_ty
, expr
, item_name
, &mut err
)
994 && lev_candidate
.is_none()
995 && !custom_span_label
997 label_span_not_found(&mut err
);
999 } else if !custom_span_label
{
1000 label_span_not_found(&mut err
);
1003 self.check_for_field_method(&mut err
, source
, span
, actual
, item_name
);
1005 self.check_for_unwrap_self(&mut err
, source
, span
, actual
, item_name
);
1008 bound_spans
.dedup();
1009 for (span
, msg
) in bound_spans
.into_iter() {
1010 err
.span_label(span
, &msg
);
1013 if actual
.is_numeric() && actual
.is_fresh() || restrict_type_params
{
1015 self.suggest_traits_to_import(
1020 args
.map(|args
| args
.len()),
1022 out_of_scope_traits
,
1023 &unsatisfied_predicates
,
1028 // Don't emit a suggestion if we found an actual method
1029 // that had unsatisfied trait bounds
1030 if unsatisfied_predicates
.is_empty() && actual
.is_enum() {
1031 let adt_def
= actual
.ty_adt_def().expect("enum is not an ADT");
1032 if let Some(suggestion
) = lev_distance
::find_best_match_for_name(
1033 &adt_def
.variants().iter().map(|s
| s
.name
).collect
::<Vec
<_
>>(),
1037 err
.span_suggestion(
1039 "there is a variant with a similar name",
1041 Applicability
::MaybeIncorrect
,
1046 if item_name
.name
== sym
::as_str
&& actual
.peel_refs().is_str() {
1047 let msg
= "remove this method call";
1048 let mut fallback_span
= true;
1049 if let SelfSource
::MethodCall(expr
) = source
{
1051 self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
));
1052 if let Some(span
) = call_expr
.span
.trim_start(expr
.span
) {
1053 err
.span_suggestion(span
, msg
, "", Applicability
::MachineApplicable
);
1054 fallback_span
= false;
1058 err
.span_label(span
, msg
);
1060 } else if let Some(lev_candidate
) = lev_candidate
{
1061 // Don't emit a suggestion if we found an actual method
1062 // that had unsatisfied trait bounds
1063 if unsatisfied_predicates
.is_empty() {
1064 let def_kind
= lev_candidate
.kind
.as_def_kind();
1065 err
.span_suggestion(
1068 "there is {} {} with a similar name",
1070 def_kind
.descr(lev_candidate
.def_id
),
1073 Applicability
::MaybeIncorrect
,
1081 MethodError
::Ambiguity(sources
) => {
1082 let mut err
= struct_span_err
!(
1086 "multiple applicable items in scope"
1088 err
.span_label(item_name
.span
, format
!("multiple `{}` found", item_name
));
1090 report_candidates(span
, &mut err
, sources
, sugg_span
);
1094 MethodError
::PrivateMatch(kind
, def_id
, out_of_scope_traits
) => {
1095 let kind
= kind
.descr(def_id
);
1096 let mut err
= struct_span_err
!(
1100 "{} `{}` is private",
1104 err
.span_label(item_name
.span
, &format
!("private {}", kind
));
1108 .span_if_local(def_id
)
1109 .unwrap_or_else(|| self.tcx
.def_span(def_id
));
1110 err
.span_label(sp
, &format
!("private {} defined here", kind
));
1111 self.suggest_valid_traits(&mut err
, out_of_scope_traits
);
1115 MethodError
::IllegalSizedBound(candidates
, needs_mut
, bound_span
) => {
1116 let msg
= format
!("the `{}` method cannot be invoked on a trait object", item_name
);
1117 let mut err
= self.sess().struct_span_err(span
, &msg
);
1118 err
.span_label(bound_span
, "this has a `Sized` requirement");
1119 if !candidates
.is_empty() {
1121 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1122 add a `use` for {one_of_them}:",
1123 an
= if candidates
.len() == 1 { "an" }
else { "" }
,
1124 s
= pluralize
!(candidates
.len()),
1125 were
= pluralize
!("was", candidates
.len()),
1126 one_of_them
= if candidates
.len() == 1 { "it" }
else { "one_of_them" }
,
1128 self.suggest_use_candidates(&mut err
, help
, candidates
);
1130 if let ty
::Ref(region
, t_type
, mutability
) = rcvr_ty
.kind() {
1132 let trait_type
= self.tcx
.mk_ref(
1134 ty
::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }
,
1136 err
.note(&format
!("you need `{}` instead of `{}`", trait_type
, rcvr_ty
));
1142 MethodError
::BadReturnType
=> bug
!("no return type expectations but got BadReturnType"),
1147 fn suggest_field_call(
1151 expr
: &hir
::Expr
<'_
>,
1153 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1156 let field_receiver
= self.autoderef(span
, rcvr_ty
).find_map(|(ty
, _
)| match ty
.kind() {
1157 ty
::Adt(def
, substs
) if !def
.is_enum() => {
1158 let variant
= &def
.non_enum_variant();
1159 tcx
.find_field_index(item_name
, variant
).map(|index
| {
1160 let field
= &variant
.fields
[index
];
1161 let field_ty
= field
.ty(tcx
, substs
);
1167 if let Some((field
, field_ty
)) = field_receiver
{
1168 let scope
= tcx
.parent_module(self.body_id
).to_def_id();
1169 let is_accessible
= field
.vis
.is_accessible_from(scope
, tcx
);
1172 if self.is_fn_ty(field_ty
, span
) {
1173 let expr_span
= expr
.span
.to(item_name
.span
);
1174 err
.multipart_suggestion(
1176 "to call the function stored in `{}`, \
1177 surround the field access with parentheses",
1181 (expr_span
.shrink_to_lo(), '
('
.to_string()),
1182 (expr_span
.shrink_to_hi(), '
)'
.to_string()),
1184 Applicability
::MachineApplicable
,
1187 let call_expr
= tcx
.hir().expect_expr(tcx
.hir().get_parent_node(expr
.hir_id
));
1189 if let Some(span
) = call_expr
.span
.trim_start(item_name
.span
) {
1190 err
.span_suggestion(
1192 "remove the arguments",
1194 Applicability
::MaybeIncorrect
,
1200 let field_kind
= if is_accessible { "field" }
else { "private field" }
;
1201 err
.span_label(item_name
.span
, format
!("{}, not a method", field_kind
));
1207 fn suggest_constraining_numerical_ty(
1211 source
: SelfSource
<'_
>,
1217 let found_candidate
= all_traits(self.tcx
)
1219 .any(|info
| self.associated_value(info
.def_id
, item_name
).is_some());
1220 let found_assoc
= |ty
: Ty
<'tcx
>| {
1221 simplify_type(tcx
, ty
, TreatParams
::AsInfer
)
1223 tcx
.incoherent_impls(simp
)
1225 .find_map(|&id
| self.associated_value(id
, item_name
))
1229 let found_candidate
= found_candidate
1230 || found_assoc(tcx
.types
.i8)
1231 || found_assoc(tcx
.types
.i16)
1232 || found_assoc(tcx
.types
.i32)
1233 || found_assoc(tcx
.types
.i64)
1234 || found_assoc(tcx
.types
.i128
)
1235 || found_assoc(tcx
.types
.u8)
1236 || found_assoc(tcx
.types
.u16)
1237 || found_assoc(tcx
.types
.u32)
1238 || found_assoc(tcx
.types
.u64)
1239 || found_assoc(tcx
.types
.u128
)
1240 || found_assoc(tcx
.types
.f32)
1241 || found_assoc(tcx
.types
.f32);
1243 && actual
.is_numeric()
1244 && !actual
.has_concrete_skeleton()
1245 && let SelfSource
::MethodCall(expr
) = source
1247 let mut err
= struct_span_err
!(
1251 "can't call {} `{}` on ambiguous numeric type `{}`",
1256 let concrete_type
= if actual
.is_integral() { "i32" }
else { "f32" }
;
1258 ExprKind
::Lit(ref lit
) => {
1263 .span_to_snippet(lit
.span
)
1264 .unwrap_or_else(|_
| "<numeric literal>".to_owned());
1266 // If this is a floating point literal that ends with '.',
1267 // get rid of it to stop this from becoming a member access.
1268 let snippet
= snippet
.strip_suffix('
.'
).unwrap_or(&snippet
);
1270 err
.span_suggestion(
1273 "you must specify a concrete type for this numeric value, \
1277 format
!("{snippet}_{concrete_type}"),
1278 Applicability
::MaybeIncorrect
,
1281 ExprKind
::Path(QPath
::Resolved(_
, path
)) => {
1283 if let hir
::def
::Res
::Local(hir_id
) = path
.res
{
1284 let span
= tcx
.hir().span(hir_id
);
1285 let snippet
= tcx
.sess
.source_map().span_to_snippet(span
);
1286 let filename
= tcx
.sess
.source_map().span_to_filename(span
);
1289 self.tcx
.hir().get(self.tcx
.hir().get_parent_node(hir_id
));
1291 "you must specify a type for this binding, like `{}`",
1295 match (filename
, parent_node
, snippet
) {
1298 Node
::Local(hir
::Local
{
1299 source
: hir
::LocalSource
::Normal
,
1305 err
.span_suggestion(
1306 // account for `let x: _ = 42;`
1308 span
.to(ty
.as_ref().map(|ty
| ty
.span
).unwrap_or(span
)),
1310 format
!("{}: {}", snippet
, concrete_type
),
1311 Applicability
::MaybeIncorrect
,
1315 err
.span_label(span
, msg
);
1328 fn check_for_field_method(
1330 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1331 source
: SelfSource
<'tcx
>,
1336 if let SelfSource
::MethodCall(expr
) = source
1337 && let Some((fields
, substs
)) = self.get_field_candidates(span
, actual
)
1339 let call_expr
= self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
));
1340 for candidate_field
in fields
.iter() {
1341 if let Some(field_path
) = self.check_for_nested_field_satisfying(
1349 ProbeScope
::AllTraits
,
1356 self.tcx
.parent_module(expr
.hir_id
).to_def_id(),
1358 let field_path_str
= field_path
1360 .map(|id
| id
.name
.to_ident_string())
1361 .collect
::<Vec
<String
>>()
1363 debug
!("field_path_str: {:?}", field_path_str
);
1365 err
.span_suggestion_verbose(
1366 item_name
.span
.shrink_to_lo(),
1367 "one of the expressions' fields has a method of the same name",
1368 format
!("{field_path_str}."),
1369 Applicability
::MaybeIncorrect
,
1376 fn check_for_unwrap_self(
1378 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1379 source
: SelfSource
<'tcx
>,
1385 let SelfSource
::MethodCall(expr
) = source
else { return; }
;
1386 let call_expr
= tcx
.hir().expect_expr(tcx
.hir().get_parent_node(expr
.hir_id
));
1388 let ty
::Adt(kind
, substs
) = actual
.kind() else { return; }
;
1389 if !kind
.is_enum() {
1393 let matching_variants
: Vec
<_
> = kind
1396 .flat_map(|variant
| {
1397 let [field
] = &variant
.fields
[..] else { return None; }
;
1398 let field_ty
= field
.ty(tcx
, substs
);
1400 // Skip `_`, since that'll just lead to ambiguity.
1401 if self.resolve_vars_if_possible(field_ty
).is_ty_var() {
1405 self.lookup_probe(span
, item_name
, field_ty
, call_expr
, ProbeScope
::AllTraits
)
1407 .map(|pick
| (variant
, field
, pick
))
1411 let ret_ty_matches
= |diagnostic_item
| {
1412 if let Some(ret_ty
) = self
1415 .map(|c
| self.resolve_vars_if_possible(c
.borrow().expected_ty()))
1416 && let ty
::Adt(kind
, _
) = ret_ty
.kind()
1417 && tcx
.get_diagnostic_item(diagnostic_item
) == Some(kind
.did())
1425 match &matching_variants
[..] {
1426 [(_
, field
, pick
)] => {
1427 let self_ty
= field
.ty(tcx
, substs
);
1429 tcx
.def_span(pick
.item
.def_id
),
1430 &format
!("the method `{item_name}` exists on the type `{self_ty}`"),
1432 let (article
, kind
, variant
, question
) =
1433 if Some(kind
.did()) == tcx
.get_diagnostic_item(sym
::Result
) {
1434 ("a", "Result", "Err", ret_ty_matches(sym
::Result
))
1435 } else if Some(kind
.did()) == tcx
.get_diagnostic_item(sym
::Option
) {
1436 ("an", "Option", "None", ret_ty_matches(sym
::Option
))
1441 err
.span_suggestion_verbose(
1442 expr
.span
.shrink_to_hi(),
1444 "use the `?` operator to extract the `{self_ty}` value, propagating \
1445 {article} `{kind}::{variant}` value to the caller"
1448 Applicability
::MachineApplicable
,
1451 err
.span_suggestion_verbose(
1452 expr
.span
.shrink_to_hi(),
1454 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1455 panicking if the value is {article} `{kind}::{variant}`"
1457 ".expect(\"REASON\")",
1458 Applicability
::HasPlaceholders
,
1462 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1467 pub(crate) fn note_unmet_impls_on_type(
1469 err
: &mut Diagnostic
,
1470 errors
: Vec
<FulfillmentError
<'tcx
>>,
1472 let all_local_types_needing_impls
=
1473 errors
.iter().all(|e
| match e
.obligation
.predicate
.kind().skip_binder() {
1474 ty
::PredicateKind
::Trait(pred
) => match pred
.self_ty().kind() {
1475 ty
::Adt(def
, _
) => def
.did().is_local(),
1480 let mut preds
: Vec
<_
> = errors
1482 .filter_map(|e
| match e
.obligation
.predicate
.kind().skip_binder() {
1483 ty
::PredicateKind
::Trait(pred
) => Some(pred
),
1487 preds
.sort_by_key(|pred
| (pred
.def_id(), pred
.self_ty()));
1490 .filter_map(|pred
| match pred
.self_ty().kind() {
1491 ty
::Adt(def
, _
) => Some(def
.did()),
1494 .collect
::<FxHashSet
<_
>>();
1495 let mut spans
: MultiSpan
= def_ids
1497 .filter_map(|def_id
| {
1498 let span
= self.tcx
.def_span(*def_id
);
1499 if span
.is_dummy() { None }
else { Some(span) }
1501 .collect
::<Vec
<_
>>()
1504 for pred
in &preds
{
1505 match pred
.self_ty().kind() {
1506 ty
::Adt(def
, _
) if def
.did().is_local() => {
1507 spans
.push_span_label(
1508 self.tcx
.def_span(def
.did()),
1509 format
!("must implement `{}`", pred
.trait_ref
.print_only_trait_path()),
1516 if all_local_types_needing_impls
&& spans
.primary_span().is_some() {
1517 let msg
= if preds
.len() == 1 {
1519 "an implementation of `{}` might be missing for `{}`",
1520 preds
[0].trait_ref
.print_only_trait_path(),
1525 "the following type{} would have to `impl` {} required trait{} for this \
1526 operation to be valid",
1527 pluralize
!(def_ids
.len()),
1528 if def_ids
.len() == 1 { "its" }
else { "their" }
,
1529 pluralize
!(preds
.len()),
1532 err
.span_note(spans
, &msg
);
1535 let preds
: Vec
<_
> = errors
1537 .map(|e
| (e
.obligation
.predicate
, None
, Some(e
.obligation
.cause
.clone())))
1539 self.suggest_derive(err
, &preds
);
1544 err
: &mut Diagnostic
,
1545 unsatisfied_predicates
: &[(
1546 ty
::Predicate
<'tcx
>,
1547 Option
<ty
::Predicate
<'tcx
>>,
1548 Option
<ObligationCause
<'tcx
>>,
1551 let mut derives
= Vec
::<(String
, Span
, Symbol
)>::new();
1552 let mut traits
= Vec
::<Span
>::new();
1553 for (pred
, _
, _
) in unsatisfied_predicates
{
1554 let ty
::PredicateKind
::Trait(trait_pred
) = pred
.kind().skip_binder() else { continue }
;
1555 let adt
= match trait_pred
.self_ty().ty_adt_def() {
1556 Some(adt
) if adt
.did().is_local() => adt
,
1559 if let Some(diagnostic_name
) = self.tcx
.get_diagnostic_name(trait_pred
.def_id()) {
1560 let can_derive
= match diagnostic_name
{
1561 sym
::Default
=> !adt
.is_enum(),
1569 | sym
::Debug
=> true,
1573 let self_name
= trait_pred
.self_ty().to_string();
1574 let self_span
= self.tcx
.def_span(adt
.did());
1575 if let Some(poly_trait_ref
) = pred
.to_opt_poly_trait_pred() {
1576 for super_trait
in supertraits(self.tcx
, poly_trait_ref
.to_poly_trait_ref())
1578 if let Some(parent_diagnostic_name
) =
1579 self.tcx
.get_diagnostic_name(super_trait
.def_id())
1584 parent_diagnostic_name
,
1589 derives
.push((self_name
, self_span
, diagnostic_name
));
1591 traits
.push(self.tcx
.def_span(trait_pred
.def_id()));
1594 traits
.push(self.tcx
.def_span(trait_pred
.def_id()));
1603 let mut derives_grouped
= Vec
::<(String
, Span
, String
)>::new();
1604 for (self_name
, self_span
, trait_name
) in derives
.into_iter() {
1605 if let Some((last_self_name
, _
, ref mut last_trait_names
)) = derives_grouped
.last_mut()
1607 if last_self_name
== &self_name
{
1608 last_trait_names
.push_str(format
!(", {}", trait_name
).as_str());
1612 derives_grouped
.push((self_name
, self_span
, trait_name
.to_string()));
1615 let len
= traits
.len();
1617 let span
: MultiSpan
= traits
.into();
1620 &format
!("the following trait{} must be implemented", pluralize
!(len
),),
1624 for (self_name
, self_span
, traits
) in &derives_grouped
{
1625 err
.span_suggestion_verbose(
1626 self_span
.shrink_to_lo(),
1627 &format
!("consider annotating `{}` with `#[derive({})]`", self_name
, traits
),
1628 format
!("#[derive({})]\n", traits
),
1629 Applicability
::MaybeIncorrect
,
1634 /// Print out the type for use in value namespace.
1635 fn ty_to_value_string(&self, ty
: Ty
<'tcx
>) -> String
{
1637 ty
::Adt(def
, substs
) => format
!("{}", ty
::Instance
::new(def
.did(), substs
)),
1638 _
=> self.ty_to_string(ty
),
1642 fn suggest_await_before_method(
1644 err
: &mut Diagnostic
,
1647 call
: &hir
::Expr
<'_
>,
1650 let output_ty
= match self.get_impl_future_output_ty(ty
) {
1651 Some(output_ty
) => self.resolve_vars_if_possible(output_ty
).skip_binder(),
1654 let method_exists
= self.method_exists(item_name
, output_ty
, call
.hir_id
, true);
1655 debug
!("suggest_await_before_method: is_method_exist={}", method_exists
);
1657 err
.span_suggestion_verbose(
1658 span
.shrink_to_lo(),
1659 "consider `await`ing on the `Future` and calling the method on its `Output`",
1661 Applicability
::MaybeIncorrect
,
1666 fn suggest_use_candidates(&self, err
: &mut Diagnostic
, msg
: String
, candidates
: Vec
<DefId
>) {
1667 let parent_map
= self.tcx
.visible_parent_map(());
1669 // Separate out candidates that must be imported with a glob, because they are named `_`
1670 // and cannot be referred with their identifier.
1671 let (candidates
, globs
): (Vec
<_
>, Vec
<_
>) = candidates
.into_iter().partition(|trait_did
| {
1672 if let Some(parent_did
) = parent_map
.get(trait_did
) {
1673 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1674 if *parent_did
!= self.tcx
.parent(*trait_did
)
1677 .module_children(*parent_did
)
1679 .filter(|child
| child
.res
.opt_def_id() == Some(*trait_did
))
1680 .all(|child
| child
.ident
.name
== kw
::Underscore
)
1689 let module_did
= self.tcx
.parent_module(self.body_id
);
1690 let (module
, _
, _
) = self.tcx
.hir().get_module(module_did
);
1691 let span
= module
.spans
.inject_use_span
;
1693 let path_strings
= candidates
.iter().map(|trait_did
| {
1694 format
!("use {};\n", with_crate_prefix
!(self.tcx
.def_path_str(*trait_did
)),)
1697 let glob_path_strings
= globs
.iter().map(|trait_did
| {
1698 let parent_did
= parent_map
.get(trait_did
).unwrap();
1700 "use {}::*; // trait {}\n",
1701 with_crate_prefix
!(self.tcx
.def_path_str(*parent_did
)),
1702 self.tcx
.item_name(*trait_did
),
1706 err
.span_suggestions(
1709 path_strings
.chain(glob_path_strings
),
1710 Applicability
::MaybeIncorrect
,
1714 fn suggest_valid_traits(
1716 err
: &mut Diagnostic
,
1717 valid_out_of_scope_traits
: Vec
<DefId
>,
1719 if !valid_out_of_scope_traits
.is_empty() {
1720 let mut candidates
= valid_out_of_scope_traits
;
1724 // `TryFrom` and `FromIterator` have no methods
1725 let edition_fix
= candidates
1727 .find(|did
| self.tcx
.is_diagnostic_item(sym
::TryInto
, **did
))
1730 err
.help("items from traits can only be used if the trait is in scope");
1732 "the following {traits_are} implemented but not in scope; \
1733 perhaps add a `use` for {one_of_them}:",
1734 traits_are
= if candidates
.len() == 1 { "trait is" }
else { "traits are" }
,
1735 one_of_them
= if candidates
.len() == 1 { "it" }
else { "one of them" }
,
1738 self.suggest_use_candidates(err
, msg
, candidates
);
1739 if let Some(did
) = edition_fix
{
1741 "'{}' is included in the prelude starting in Edition 2021",
1742 with_crate_prefix
!(self.tcx
.def_path_str(did
))
1752 fn suggest_traits_to_import(
1754 err
: &mut Diagnostic
,
1758 inputs_len
: Option
<usize>,
1759 source
: SelfSource
<'tcx
>,
1760 valid_out_of_scope_traits
: Vec
<DefId
>,
1761 unsatisfied_predicates
: &[(
1762 ty
::Predicate
<'tcx
>,
1763 Option
<ty
::Predicate
<'tcx
>>,
1764 Option
<ObligationCause
<'tcx
>>,
1766 unsatisfied_bounds
: bool
,
1768 let mut alt_rcvr_sugg
= false;
1769 if let (SelfSource
::MethodCall(rcvr
), false) = (source
, unsatisfied_bounds
) {
1770 debug
!(?span
, ?item_name
, ?rcvr_ty
, ?rcvr
);
1772 self.tcx
.lang_items().clone_trait(),
1773 self.tcx
.lang_items().deref_trait(),
1774 self.tcx
.lang_items().deref_mut_trait(),
1775 self.tcx
.lang_items().drop_trait(),
1776 self.tcx
.get_diagnostic_item(sym
::AsRef
),
1778 // Try alternative arbitrary self types that could fulfill this call.
1779 // FIXME: probe for all types that *could* be arbitrary self-types, not
1781 for (rcvr_ty
, post
) in &[
1783 (self.tcx
.mk_mut_ref(self.tcx
.lifetimes
.re_erased
, rcvr_ty
), "&mut "),
1784 (self.tcx
.mk_imm_ref(self.tcx
.lifetimes
.re_erased
, rcvr_ty
), "&"),
1786 match self.lookup_probe(span
, item_name
, *rcvr_ty
, rcvr
, ProbeScope
::AllTraits
) {
1788 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1789 // We point at the method, but we just skip the rest of the check for arbitrary
1790 // self types and rely on the suggestion to `use` the trait from
1791 // `suggest_valid_traits`.
1792 let did
= Some(pick
.item
.container_id(self.tcx
));
1793 let skip
= skippable
.contains(&did
);
1794 if pick
.autoderefs
== 0 && !skip
{
1796 pick
.item
.ident(self.tcx
).span
,
1797 &format
!("the method is available for `{}` here", rcvr_ty
),
1802 Err(MethodError
::Ambiguity(_
)) => {
1803 // If the method is defined (but ambiguous) for the receiver we have, it is also
1804 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1805 // the receiver, then it might disambiguate this method, but I think these
1806 // suggestions are generally misleading (see #94218).
1812 for (rcvr_ty
, pre
) in &[
1813 (self.tcx
.mk_lang_item(*rcvr_ty
, LangItem
::OwnedBox
), "Box::new"),
1814 (self.tcx
.mk_lang_item(*rcvr_ty
, LangItem
::Pin
), "Pin::new"),
1815 (self.tcx
.mk_diagnostic_item(*rcvr_ty
, sym
::Arc
), "Arc::new"),
1816 (self.tcx
.mk_diagnostic_item(*rcvr_ty
, sym
::Rc
), "Rc::new"),
1818 if let Some(new_rcvr_t
) = *rcvr_ty
1819 && let Ok(pick
) = self.lookup_probe(
1824 ProbeScope
::AllTraits
,
1827 debug
!("try_alt_rcvr: pick candidate {:?}", pick
);
1828 let did
= Some(pick
.item
.container_id(self.tcx
));
1829 // We don't want to suggest a container type when the missing
1830 // method is `.clone()` or `.deref()` otherwise we'd suggest
1831 // `Arc::new(foo).clone()`, which is far from what the user wants.
1832 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1833 // implement the `AsRef` trait.
1834 let skip
= skippable
.contains(&did
)
1835 || (("Pin::new" == *pre
) && (sym
::as_ref
== item_name
.name
))
1836 || inputs_len
.map_or(false, |inputs_len
| pick
.item
.kind
== ty
::AssocKind
::Fn
&& self.tcx
.fn_sig(pick
.item
.def_id
).skip_binder().inputs().len() != inputs_len
);
1837 // Make sure the method is defined for the *actual* receiver: we don't
1838 // want to treat `Box<Self>` as a receiver if it only works because of
1839 // an autoderef to `&self`
1840 if pick
.autoderefs
== 0 && !skip
{
1842 pick
.item
.ident(self.tcx
).span
,
1843 &format
!("the method is available for `{}` here", new_rcvr_t
),
1845 err
.multipart_suggestion(
1846 "consider wrapping the receiver expression with the \
1849 (rcvr
.span
.shrink_to_lo(), format
!("{}({}", pre
, post
)),
1850 (rcvr
.span
.shrink_to_hi(), ")".to_string()),
1852 Applicability
::MaybeIncorrect
,
1854 // We don't care about the other suggestions.
1855 alt_rcvr_sugg
= true;
1861 if self.suggest_valid_traits(err
, valid_out_of_scope_traits
) {
1865 let type_is_local
= self.type_derefs_to_local(span
, rcvr_ty
, source
);
1867 let mut arbitrary_rcvr
= vec
![];
1868 // There are no traits implemented, so lets suggest some traits to
1869 // implement, by finding ones that have the item name, and are
1870 // legal to implement.
1871 let mut candidates
= all_traits(self.tcx
)
1873 // Don't issue suggestions for unstable traits since they're
1874 // unlikely to be implementable anyway
1875 .filter(|info
| match self.tcx
.lookup_stability(info
.def_id
) {
1876 Some(attr
) => attr
.level
.is_stable(),
1880 // We approximate the coherence rules to only suggest
1881 // traits that are legal to implement by requiring that
1882 // either the type or trait is local. Multi-dispatch means
1883 // this isn't perfect (that is, there are cases when
1884 // implementing a trait would be legal but is rejected
1886 unsatisfied_predicates
.iter().all(|(p
, _
, _
)| {
1887 match p
.kind().skip_binder() {
1888 // Hide traits if they are present in predicates as they can be fixed without
1889 // having to implement them.
1890 ty
::PredicateKind
::Trait(t
) => t
.def_id() == info
.def_id
,
1891 ty
::PredicateKind
::Projection(p
) => {
1892 p
.projection_ty
.item_def_id
== info
.def_id
1896 }) && (type_is_local
|| info
.def_id
.is_local())
1898 .associated_value(info
.def_id
, item_name
)
1900 if let ty
::AssocKind
::Fn
= item
.kind
{
1904 .map(|def_id
| self.tcx
.hir().local_def_id_to_hir_id(def_id
));
1905 if let Some(hir
::Node
::TraitItem(hir
::TraitItem
{
1906 kind
: hir
::TraitItemKind
::Fn(fn_sig
, method
),
1908 })) = id
.map(|id
| self.tcx
.hir().get(id
))
1910 let self_first_arg
= match method
{
1911 hir
::TraitFn
::Required([ident
, ..]) => {
1912 ident
.name
== kw
::SelfLower
1914 hir
::TraitFn
::Provided(body_id
) => {
1915 self.tcx
.hir().body(*body_id
).params
.first().map_or(
1920 hir
::PatKind
::Binding(_
, _
, ident
, _
)
1921 if ident
.name
== kw
::SelfLower
1929 if !fn_sig
.decl
.implicit_self
.has_implicit_self()
1932 if let Some(ty
) = fn_sig
.decl
.inputs
.get(0) {
1933 arbitrary_rcvr
.push(ty
.span
);
1939 // We only want to suggest public or local traits (#45781).
1940 item
.visibility(self.tcx
).is_public() || info
.def_id
.is_local()
1944 .collect
::<Vec
<_
>>();
1945 for span
in &arbitrary_rcvr
{
1948 "the method might not be found because of this arbitrary self type",
1955 if !candidates
.is_empty() {
1956 // Sort from most relevant to least relevant.
1957 candidates
.sort_by(|a
, b
| a
.cmp(b
).reverse());
1960 let param_type
= match rcvr_ty
.kind() {
1961 ty
::Param(param
) => Some(param
),
1962 ty
::Ref(_
, ty
, _
) => match ty
.kind() {
1963 ty
::Param(param
) => Some(param
),
1968 err
.help(if param_type
.is_some() {
1969 "items from traits can only be used if the type parameter is bounded by the trait"
1971 "items from traits can only be used if the trait is implemented and in scope"
1973 let candidates_len
= candidates
.len();
1974 let message
= |action
| {
1976 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1979 if candidates_len
== 1 { "trait defines" }
else { "traits define" }
,
1981 one_of_them
= if candidates_len
== 1 { "it" }
else { "one of them" }
,
1985 // Obtain the span for `param` and use it for a structured suggestion.
1986 if let Some(param
) = param_type
{
1987 let generics
= self.tcx
.generics_of(self.body_id
.owner
.to_def_id());
1988 let type_param
= generics
.type_param(param
, self.tcx
);
1989 let hir
= self.tcx
.hir();
1990 if let Some(def_id
) = type_param
.def_id
.as_local() {
1991 let id
= hir
.local_def_id_to_hir_id(def_id
);
1992 // Get the `hir::Param` to verify whether it already has any bounds.
1993 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1994 // instead we suggest `T: Foo + Bar` in that case.
1996 Node
::GenericParam(param
) => {
2002 let ast_generics
= hir
.get_generics(id
.owner
).unwrap();
2003 let (sp
, mut introducer
) = if let Some(span
) =
2004 ast_generics
.bounds_span_for_suggestions(def_id
)
2006 (span
, Introducer
::Plus
)
2007 } else if let Some(colon_span
) = param
.colon_span
{
2008 (colon_span
.shrink_to_hi(), Introducer
::Nothing
)
2010 (param
.span
.shrink_to_hi(), Introducer
::Colon
)
2014 hir
::GenericParamKind
::Type { synthetic: true, .. }
,
2016 introducer
= Introducer
::Plus
2018 let trait_def_ids
: FxHashSet
<DefId
> = ast_generics
2019 .bounds_for_param(def_id
)
2020 .flat_map(|bp
| bp
.bounds
.iter())
2021 .filter_map(|bound
| bound
.trait_ref()?
.trait_def_id())
2023 if !candidates
.iter().any(|t
| trait_def_ids
.contains(&t
.def_id
)) {
2024 err
.span_suggestions(
2027 "restrict type parameter `{}` with",
2030 candidates
.iter().map(|t
| {
2034 Introducer
::Plus
=> " +",
2035 Introducer
::Colon
=> ":",
2036 Introducer
::Nothing
=> "",
2038 self.tcx
.def_path_str(t
.def_id
),
2041 Applicability
::MaybeIncorrect
,
2046 Node
::Item(hir
::Item
{
2047 kind
: hir
::ItemKind
::Trait(.., bounds
, _
),
2051 let (sp
, sep
, article
) = if bounds
.is_empty() {
2052 (ident
.span
.shrink_to_hi(), ":", "a")
2054 (bounds
.last().unwrap().span().shrink_to_hi(), " +", "another")
2056 err
.span_suggestions(
2058 &message(format
!("add {} supertrait for", article
)),
2059 candidates
.iter().map(|t
| {
2060 format
!("{} {}", sep
, self.tcx
.def_path_str(t
.def_id
),)
2062 Applicability
::MaybeIncorrect
,
2071 let (potential_candidates
, explicitly_negative
) = if param_type
.is_some() {
2072 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2073 // cases where a positive bound implies a negative impl.
2074 (candidates
, Vec
::new())
2075 } else if let Some(simp_rcvr_ty
) =
2076 simplify_type(self.tcx
, rcvr_ty
, TreatParams
::AsPlaceholder
)
2078 let mut potential_candidates
= Vec
::new();
2079 let mut explicitly_negative
= Vec
::new();
2080 for candidate
in candidates
{
2081 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2084 .all_impls(candidate
.def_id
)
2086 self.tcx
.impl_polarity(*imp_did
) == ty
::ImplPolarity
::Negative
2089 let imp
= self.tcx
.impl_trait_ref(imp_did
).unwrap();
2091 simplify_type(self.tcx
, imp
.self_ty(), TreatParams
::AsPlaceholder
);
2092 imp_simp
.map_or(false, |s
| s
== simp_rcvr_ty
)
2095 explicitly_negative
.push(candidate
);
2097 potential_candidates
.push(candidate
);
2100 (potential_candidates
, explicitly_negative
)
2102 // We don't know enough about `recv_ty` to make proper suggestions.
2103 (candidates
, Vec
::new())
2106 let action
= if let Some(param
) = param_type
{
2107 format
!("restrict type parameter `{}` with", param
)
2109 // FIXME: it might only need to be imported into scope, not implemented.
2110 "implement".to_string()
2112 match &potential_candidates
[..] {
2114 [trait_info
] if trait_info
.def_id
.is_local() => {
2116 self.tcx
.def_span(trait_info
.def_id
),
2118 "`{}` defines an item `{}`, perhaps you need to {} it",
2119 self.tcx
.def_path_str(trait_info
.def_id
),
2126 let mut msg
= message(action
);
2127 for (i
, trait_info
) in trait_infos
.iter().enumerate() {
2128 msg
.push_str(&format
!(
2129 "\ncandidate #{}: `{}`",
2131 self.tcx
.def_path_str(trait_info
.def_id
),
2137 match &explicitly_negative
[..] {
2141 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2142 self.tcx
.def_path_str(trait_info
.def_id
),
2148 let mut msg
= format
!(
2149 "the following traits define an item `{}`, but are explicitly unimplemented:",
2152 for trait_info
in trait_infos
{
2153 msg
.push_str(&format
!("\n{}", self.tcx
.def_path_str(trait_info
.def_id
)));
2161 /// Checks whether there is a local type somewhere in the chain of
2162 /// autoderefs of `rcvr_ty`.
2163 fn type_derefs_to_local(
2167 source
: SelfSource
<'tcx
>,
2169 fn is_local(ty
: Ty
<'_
>) -> bool
{
2171 ty
::Adt(def
, _
) => def
.did().is_local(),
2172 ty
::Foreign(did
) => did
.is_local(),
2173 ty
::Dynamic(tr
, ..) => tr
.principal().map_or(false, |d
| d
.def_id().is_local()),
2174 ty
::Param(_
) => true,
2176 // Everything else (primitive types, etc.) is effectively
2177 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2178 // the noise from these sort of types is usually just really
2179 // annoying, rather than any sort of help).
2184 // This occurs for UFCS desugaring of `T::method`, where there is no
2185 // receiver expression for the method call, and thus no autoderef.
2186 if let SelfSource
::QPath(_
) = source
{
2187 return is_local(self.resolve_vars_with_obligations(rcvr_ty
));
2190 self.autoderef(span
, rcvr_ty
).any(|(ty
, _
)| is_local(ty
))
2194 #[derive(Copy, Clone, Debug)]
2195 pub enum SelfSource
<'a
> {
2196 QPath(&'a hir
::Ty
<'a
>),
2197 MethodCall(&'a hir
::Expr
<'a
> /* rcvr */),
2200 #[derive(Copy, Clone)]
2201 pub struct TraitInfo
{
2205 impl PartialEq
for TraitInfo
{
2206 fn eq(&self, other
: &TraitInfo
) -> bool
{
2207 self.cmp(other
) == Ordering
::Equal
2210 impl Eq
for TraitInfo {}
2211 impl PartialOrd
for TraitInfo
{
2212 fn partial_cmp(&self, other
: &TraitInfo
) -> Option
<Ordering
> {
2213 Some(self.cmp(other
))
2216 impl Ord
for TraitInfo
{
2217 fn cmp(&self, other
: &TraitInfo
) -> Ordering
{
2218 // Local crates are more important than remote ones (local:
2219 // `cnum == 0`), and otherwise we throw in the defid for totality.
2221 let lhs
= (other
.def_id
.krate
, other
.def_id
);
2222 let rhs
= (self.def_id
.krate
, self.def_id
);
2227 /// Retrieves all traits in this crate and any dependent crates,
2228 /// and wraps them into `TraitInfo` for custom sorting.
2229 pub fn all_traits(tcx
: TyCtxt
<'_
>) -> Vec
<TraitInfo
> {
2230 tcx
.all_traits().map(|def_id
| TraitInfo { def_id }
).collect()
2233 fn print_disambiguation_help
<'tcx
>(
2235 args
: Option
<&'tcx
[hir
::Expr
<'tcx
>]>,
2236 err
: &mut Diagnostic
,
2239 kind
: ty
::AssocKind
,
2242 candidate
: Option
<usize>,
2243 source_map
: &source_map
::SourceMap
,
2244 fn_has_self_parameter
: bool
,
2246 let mut applicability
= Applicability
::MachineApplicable
;
2247 let (span
, sugg
) = if let (ty
::AssocKind
::Fn
, Some(args
)) = (kind
, args
) {
2250 if rcvr_ty
.is_region_ptr() {
2251 if rcvr_ty
.is_mutable_ptr() { "&mut " }
else { "&" }
2256 .map(|arg
| source_map
.span_to_snippet(arg
.span
).unwrap_or_else(|_
| {
2257 applicability
= Applicability
::HasPlaceholders
;
2260 .collect
::<Vec
<_
>>()
2263 let trait_name
= if !fn_has_self_parameter
{
2264 format
!("<{} as {}>", rcvr_ty
, trait_name
)
2268 (span
, format
!("{}::{}{}", trait_name
, item_name
, args
))
2270 (span
.with_hi(item_name
.span
.lo()), format
!("<{} as {}>::", rcvr_ty
, trait_name
))
2272 err
.span_suggestion_verbose(
2275 "disambiguate the {} for {}",
2276 kind
.as_def_kind().descr(def_id
),
2277 if let Some(candidate
) = candidate
{
2278 format
!("candidate #{}", candidate
)
2280 "the candidate".to_string()