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, TypeFoldable}
;
21 use rustc_span
::symbol
::{kw, sym, Ident}
;
22 use rustc_span
::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}
;
23 use rustc_trait_selection
::traits
::error_reporting
::on_unimplemented
::InferCtxtExt
as _
;
24 use rustc_trait_selection
::traits
::query
::evaluate_obligation
::InferCtxtExt
as _
;
25 use rustc_trait_selection
::traits
::{
26 FulfillmentError
, Obligation
, ObligationCause
, ObligationCauseCode
, OnUnimplementedNote
,
29 use std
::cmp
::Ordering
;
32 use super::probe
::{Mode, ProbeScope}
;
33 use super::{super::suggest_call_constructor, CandidateSource, MethodError, NoMatchData}
;
35 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
36 fn is_fn_ty(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
39 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
40 // so we look for these beforehand.
41 ty
::Closure(..) | ty
::FnDef(..) | ty
::FnPtr(_
) => true,
42 // If it's not a simple function, look for things which implement `FnOnce`.
44 let Some(fn_once
) = tcx
.lang_items().fn_once_trait() else {
48 // This conditional prevents us from asking to call errors and unresolved types.
49 // It might seem that we can use `predicate_must_hold_modulo_regions`,
50 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
51 // type resolution always gives a "maybe" here.
52 if self.autoderef(span
, ty
).any(|(ty
, _
)| {
53 info
!("check deref {:?} error", ty
);
54 matches
!(ty
.kind(), ty
::Error(_
) | ty
::Infer(_
))
59 self.autoderef(span
, ty
).any(|(ty
, _
)| {
60 info
!("check deref {:?} impl FnOnce", ty
);
62 let fn_once_substs
= tcx
.mk_substs_trait(
65 .next_ty_var(TypeVariableOrigin
{
66 kind
: TypeVariableOriginKind
::MiscVariable
,
71 let trait_ref
= ty
::TraitRef
::new(fn_once
, fn_once_substs
);
72 let poly_trait_ref
= ty
::Binder
::dummy(trait_ref
);
73 let obligation
= Obligation
::misc(
77 poly_trait_ref
.without_const().to_predicate(tcx
),
79 self.predicate_may_hold(&obligation
)
86 fn is_slice_ty(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
87 self.autoderef(span
, ty
).any(|(ty
, _
)| matches
!(ty
.kind(), ty
::Slice(..) | ty
::Array(..)))
90 pub fn report_method_error(
95 source
: SelfSource
<'tcx
>,
96 error
: MethodError
<'tcx
>,
97 args
: Option
<&'tcx
[hir
::Expr
<'tcx
>]>,
98 ) -> Option
<DiagnosticBuilder
<'_
, ErrorGuaranteed
>> {
99 // Avoid suggestions when we don't know what's going on.
100 if rcvr_ty
.references_error() {
104 let report_candidates
= |span
: Span
,
105 err
: &mut Diagnostic
,
106 mut sources
: Vec
<CandidateSource
>,
110 // Dynamic limit to avoid hiding just one candidate, which is silly.
111 let limit
= if sources
.len() == 5 { 5 }
else { 4 }
;
113 for (idx
, source
) in sources
.iter().take(limit
).enumerate() {
115 CandidateSource
::Impl(impl_did
) => {
116 // Provide the best span we can. Use the item, if local to crate, else
117 // the impl, if local to crate (item may be defaulted), else nothing.
118 let Some(item
) = self.associated_value(impl_did
, item_name
).or_else(|| {
119 let impl_trait_ref
= self.tcx
.impl_trait_ref(impl_did
)?
;
120 self.associated_value(impl_trait_ref
.def_id
, item_name
)
127 .span_if_local(item
.def_id
)
128 .or_else(|| self.tcx
.hir().span_if_local(impl_did
));
130 let impl_ty
= self.tcx
.at(span
).type_of(impl_did
);
132 let insertion
= match self.tcx
.impl_trait_ref(impl_did
) {
133 None
=> String
::new(),
134 Some(trait_ref
) => format
!(
135 " of the trait `{}`",
136 self.tcx
.def_path_str(trait_ref
.def_id
)
140 let (note_str
, idx
) = if sources
.len() > 1 {
143 "candidate #{} is defined in an impl{} for the type `{}`",
153 "the candidate is defined in an impl{} for the type `{}`",
159 if let Some(note_span
) = note_span
{
160 // We have a span pointing to the method. Show note with snippet.
162 self.tcx
.sess
.source_map().guess_head_span(note_span
),
168 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_did
) {
169 let path
= self.tcx
.def_path_str(trait_ref
.def_id
);
171 let ty
= match item
.kind
{
172 ty
::AssocKind
::Const
| ty
::AssocKind
::Type
=> rcvr_ty
,
173 ty
::AssocKind
::Fn
=> self
179 .filter(|ty
| ty
.is_region_ptr() && !rcvr_ty
.is_region_ptr())
183 print_disambiguation_help(
193 self.tcx
.sess
.source_map(),
194 item
.fn_has_self_parameter
,
198 CandidateSource
::Trait(trait_did
) => {
199 let Some(item
) = self.associated_value(trait_did
, item_name
) else { continue }
;
204 .guess_head_span(self.tcx
.def_span(item
.def_id
));
205 let idx
= if sources
.len() > 1 {
207 "candidate #{} is defined in the trait `{}`",
209 self.tcx
.def_path_str(trait_did
)
211 err
.span_note(item_span
, msg
);
215 "the candidate is defined in the trait `{}`",
216 self.tcx
.def_path_str(trait_did
)
218 err
.span_note(item_span
, msg
);
221 let path
= self.tcx
.def_path_str(trait_did
);
222 print_disambiguation_help(
232 self.tcx
.sess
.source_map(),
233 item
.fn_has_self_parameter
,
238 if sources
.len() > limit
{
239 err
.note(&format
!("and {} others", sources
.len() - limit
));
243 let sugg_span
= if let SelfSource
::MethodCall(expr
) = source
{
244 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
245 self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
)).span
251 MethodError
::NoMatch(NoMatchData
{
252 static_candidates
: static_sources
,
253 unsatisfied_predicates
,
260 let actual
= self.resolve_vars_if_possible(rcvr_ty
);
261 let ty_str
= self.ty_to_string(actual
);
262 let is_method
= mode
== Mode
::MethodCall
;
263 let item_kind
= if is_method
{
265 } else if actual
.is_enum() {
266 "variant or associated item"
268 match (item_name
.as_str().chars().next(), actual
.is_fresh_ty()) {
269 (Some(name
), false) if name
.is_lowercase() => "function or associated item",
270 (Some(_
), false) => "associated item",
271 (Some(_
), true) | (None
, false) => "variant or associated item",
272 (None
, true) => "variant",
276 if self.suggest_constraining_numerical_ty(
277 tcx
, actual
, source
, span
, item_kind
, item_name
, &ty_str
,
282 span
= item_name
.span
;
284 // Don't show generic arguments when the method can't be found in any implementation (#81576).
285 let mut ty_str_reported
= ty_str
.clone();
286 if let ty
::Adt(_
, generics
) = actual
.kind() {
287 if generics
.len() > 0 {
288 let mut autoderef
= self.autoderef(span
, actual
);
289 let candidate_found
= autoderef
.any(|(ty
, _
)| {
290 if let ty
::Adt(adt_deref
, _
) = ty
.kind() {
292 .inherent_impls(adt_deref
.did())
294 .filter_map(|def_id
| self.associated_value(*def_id
, item_name
))
301 let has_deref
= autoderef
.step_count() > 0;
302 if !candidate_found
&& !has_deref
&& unsatisfied_predicates
.is_empty() {
303 if let Some((path_string
, _
)) = ty_str
.split_once('
<'
) {
304 ty_str_reported
= path_string
.to_string();
310 let mut err
= struct_span_err
!(
314 "no {} named `{}` found for {} `{}` in the current scope",
317 actual
.prefix_string(self.tcx
),
320 if actual
.references_error() {
321 err
.downgrade_to_delayed_bug();
324 if let Mode
::MethodCall
= mode
&& let SelfSource
::MethodCall(cal
) = source
{
325 self.suggest_await_before_method(
326 &mut err
, item_name
, actual
, cal
, span
,
329 if let Some(span
) = tcx
.resolutions(()).confused_type_with_std_module
.get(&span
) {
332 "you are looking for the module in `std`, not the primitive type",
334 Applicability
::MachineApplicable
,
337 if let ty
::RawPtr(_
) = &actual
.kind() {
339 "try using `<*const T>::as_ref()` to get a reference to the \
340 type behind the pointer: https://doc.rust-lang.org/std/\
341 primitive.pointer.html#method.as_ref",
344 "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
345 to invalid or uninitialized memory is undefined behavior",
349 if let Some(def
) = actual
.ty_adt_def() {
350 if let Some(full_sp
) = tcx
.hir().span_if_local(def
.did()) {
351 let def_sp
= tcx
.sess
.source_map().guess_head_span(full_sp
);
355 "{} `{}` not found {}",
358 if def
.is_enum() && !is_method { "here" }
else { "for this" }
364 if self.is_fn_ty(rcvr_ty
, span
) {
365 if let SelfSource
::MethodCall(expr
) = source
{
366 let suggest
= if let ty
::FnDef(def_id
, _
) = rcvr_ty
.kind() {
367 if let Some(local_id
) = def_id
.as_local() {
368 let hir_id
= tcx
.hir().local_def_id_to_hir_id(local_id
);
369 let node
= tcx
.hir().get(hir_id
);
370 let fields
= node
.tuple_fields();
371 if let Some(fields
) = fields
372 && let Some(DefKind
::Ctor(of
, _
)) = self.tcx
.opt_def_kind(local_id
) {
373 Some((fields
.len(), of
))
378 // The logic here isn't smart but `associated_item_def_ids`
379 // doesn't work nicely on local.
380 if let DefKind
::Ctor(of
, _
) = tcx
.def_kind(def_id
) {
381 let parent_def_id
= tcx
.parent(*def_id
);
382 Some((tcx
.associated_item_def_ids(parent_def_id
).len(), of
))
391 // If the function is a tuple constructor, we recommend that they call it
392 if let Some((fields
, kind
)) = suggest
{
393 suggest_call_constructor(expr
.span
, kind
, fields
, &mut err
);
398 "this is a function, perhaps you wish to call it",
404 let mut custom_span_label
= false;
406 if !static_sources
.is_empty() {
408 "found the following associated functions; to be used as methods, \
409 functions must have a `self` parameter",
411 err
.span_label(span
, "this is an associated function, not a method");
412 custom_span_label
= true;
414 if static_sources
.len() == 1 {
416 if let Some(CandidateSource
::Impl(impl_did
)) = static_sources
.get(0) {
417 // When the "method" is resolved through dereferencing, we really want the
418 // original type that has the associated function for accurate suggestions.
420 let ty
= tcx
.at(span
).type_of(*impl_did
);
421 match (&ty
.peel_refs().kind(), &actual
.peel_refs().kind()) {
422 (ty
::Adt(def
, _
), ty
::Adt(def_actual
, _
)) if def
== def_actual
=> {
423 // Use `actual` as it will have more `substs` filled in.
424 self.ty_to_value_string(actual
.peel_refs())
426 _
=> self.ty_to_value_string(ty
.peel_refs()),
429 self.ty_to_value_string(actual
.peel_refs())
431 if let SelfSource
::MethodCall(expr
) = source
{
434 "use associated function syntax instead",
435 format
!("{}::{}", ty_str
, item_name
),
436 Applicability
::MachineApplicable
,
439 err
.help(&format
!("try with `{}::{}`", ty_str
, item_name
,));
442 report_candidates(span
, &mut err
, static_sources
, sugg_span
);
443 } else if static_sources
.len() > 1 {
444 report_candidates(span
, &mut err
, static_sources
, sugg_span
);
447 let mut bound_spans
= vec
![];
448 let mut restrict_type_params
= false;
449 let mut unsatisfied_bounds
= false;
450 if item_name
.name
== sym
::count
&& self.is_slice_ty(actual
, span
) {
451 let msg
= "consider using `len` instead";
452 if let SelfSource
::MethodCall(_expr
) = source
{
453 err
.span_suggestion_short(
457 Applicability
::MachineApplicable
,
460 err
.span_label(span
, msg
);
462 if let Some(iterator_trait
) = self.tcx
.get_diagnostic_item(sym
::Iterator
) {
463 let iterator_trait
= self.tcx
.def_path_str(iterator_trait
);
464 err
.note(&format
!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
466 } else if !unsatisfied_predicates
.is_empty() {
467 let def_span
= |def_id
| {
468 self.tcx
.sess
.source_map().guess_head_span(self.tcx
.def_span(def_id
))
470 let mut type_params
= FxHashMap
::default();
472 // Pick out the list of unimplemented traits on the receiver.
473 // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
474 let mut unimplemented_traits
= FxHashMap
::default();
475 let mut unimplemented_traits_only
= true;
476 for (predicate
, _parent_pred
, cause
) in &unsatisfied_predicates
{
477 if let (ty
::PredicateKind
::Trait(p
), Some(cause
)) =
478 (predicate
.kind().skip_binder(), cause
.as_ref())
480 if p
.trait_ref
.self_ty() != rcvr_ty
{
481 // This is necessary, not just to keep the errors clean, but also
482 // because our derived obligations can wind up with a trait ref that
483 // requires a different param_env to be correctly compared.
486 unimplemented_traits
.entry(p
.trait_ref
.def_id
).or_insert((
487 predicate
.kind().rebind(p
.trait_ref
),
489 cause
: cause
.clone(),
490 param_env
: self.param_env
,
491 predicate
: *predicate
,
498 // Make sure that, if any traits other than the found ones were involved,
499 // we don't don't report an unimplemented trait.
500 // We don't want to say that `iter::Cloned` is not an iterator, just
501 // because of some non-Clone item being iterated over.
502 for (predicate
, _parent_pred
, _cause
) in &unsatisfied_predicates
{
503 match predicate
.kind().skip_binder() {
504 ty
::PredicateKind
::Trait(p
)
505 if unimplemented_traits
.contains_key(&p
.trait_ref
.def_id
) => {}
507 unimplemented_traits_only
= false;
513 let mut collect_type_param_suggestions
=
514 |self_ty
: Ty
<'tcx
>, parent_pred
: ty
::Predicate
<'tcx
>, obligation
: &str| {
515 // We don't care about regions here, so it's fine to skip the binder here.
516 if let (ty
::Param(_
), ty
::PredicateKind
::Trait(p
)) =
517 (self_ty
.kind(), parent_pred
.kind().skip_binder())
519 let node
= match p
.trait_ref
.self_ty().kind() {
521 // Account for `fn` items like in `issue-35677.rs` to
522 // suggest restricting its type params.
523 let did
= self.tcx
.hir().body_owner_def_id(hir
::BodyId
{
524 hir_id
: self.body_id
,
529 .get(self.tcx
.hir().local_def_id_to_hir_id(did
)),
532 ty
::Adt(def
, _
) => def
.did().as_local().map(|def_id
| {
535 .get(self.tcx
.hir().local_def_id_to_hir_id(def_id
))
539 if let Some(hir
::Node
::Item(hir
::Item { kind, .. }
)) = node
{
540 if let Some(g
) = kind
.generics() {
542 g
.tail_span_for_predicate_suggestion(),
543 g
.add_where_or_trailing_comma(),
547 .or_insert_with(FxHashSet
::default)
548 .insert(obligation
.to_owned());
553 let mut bound_span_label
= |self_ty
: Ty
<'_
>, obligation
: &str, quiet
: &str| {
555 "doesn't satisfy `{}`",
556 if obligation
.len() > 50 { quiet }
else { obligation }
558 match &self_ty
.kind() {
559 // Point at the type that couldn't satisfy the bound.
560 ty
::Adt(def
, _
) => bound_spans
.push((def_span(def
.did()), msg
)),
561 // Point at the trait object that couldn't satisfy the bound.
562 ty
::Dynamic(preds
, _
) => {
563 for pred
in preds
.iter() {
564 match pred
.skip_binder() {
565 ty
::ExistentialPredicate
::Trait(tr
) => {
566 bound_spans
.push((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
575 .push((def_span(*def_id
), format
!("doesn't satisfy `{}`", quiet
))),
579 let mut format_pred
= |pred
: ty
::Predicate
<'tcx
>| {
580 let bound_predicate
= pred
.kind();
581 match bound_predicate
.skip_binder() {
582 ty
::PredicateKind
::Projection(pred
) => {
583 let pred
= bound_predicate
.rebind(pred
);
584 // `<Foo as Iterator>::Item = String`.
585 let projection_ty
= pred
.skip_binder().projection_ty
;
587 let substs_with_infer_self
= tcx
.mk_substs(
588 iter
::once(tcx
.mk_ty_var(ty
::TyVid
::from_u32(0)).into())
589 .chain(projection_ty
.substs
.iter().skip(1)),
592 let quiet_projection_ty
= ty
::ProjectionTy
{
593 substs
: substs_with_infer_self
,
594 item_def_id
: projection_ty
.item_def_id
,
597 let term
= pred
.skip_binder().term
;
599 let obligation
= format
!("{} = {}", projection_ty
, term
);
600 let quiet
= format
!("{} = {}", quiet_projection_ty
, term
);
602 bound_span_label(projection_ty
.self_ty(), &obligation
, &quiet
);
603 Some((obligation
, projection_ty
.self_ty()))
605 ty
::PredicateKind
::Trait(poly_trait_ref
) => {
606 let p
= poly_trait_ref
.trait_ref
;
607 let self_ty
= p
.self_ty();
608 let path
= p
.print_only_trait_path();
609 let obligation
= format
!("{}: {}", self_ty
, path
);
610 let quiet
= format
!("_: {}", path
);
611 bound_span_label(self_ty
, &obligation
, &quiet
);
612 Some((obligation
, self_ty
))
618 // Find all the requirements that come from a local `impl` block.
619 let mut skip_list
: FxHashSet
<_
> = Default
::default();
620 let mut spanned_predicates
: FxHashMap
<MultiSpan
, _
> = Default
::default();
621 for (data
, p
, parent_p
, impl_def_id
, cause_span
) in unsatisfied_predicates
623 .filter_map(|(p
, parent
, c
)| c
.as_ref().map(|c
| (p
, parent
, c
)))
624 .filter_map(|(p
, parent
, c
)| match c
.code() {
625 ObligationCauseCode
::ImplDerivedObligation(ref data
) => {
626 Some((&data
.derived
, p
, parent
, data
.impl_def_id
, data
.span
))
631 let parent_trait_ref
= data
.parent_trait_pred
;
632 let path
= parent_trait_ref
.print_modifiers_and_trait_path();
633 let tr_self_ty
= parent_trait_ref
.skip_binder().self_ty();
634 let unsatisfied_msg
= "unsatisfied trait bound introduced here".to_string();
636 "unsatisfied trait bound introduced in this `derive` macro";
637 match self.tcx
.hir().get_if_local(impl_def_id
) {
638 // Unmet obligation comes from a `derive` macro, point at it once to
639 // avoid multiple span labels pointing at the same place.
640 Some(Node
::Item(hir
::Item
{
641 kind
: hir
::ItemKind
::Trait(..),
645 ident
.span
.ctxt().outer_expn_data().kind
,
646 ExpnKind
::Macro(MacroKind
::Derive
, _
)
649 let span
= ident
.span
.ctxt().outer_expn_data().call_site
;
650 let mut spans
: MultiSpan
= span
.into();
651 spans
.push_span_label(span
, derive_msg
.to_string());
652 let entry
= spanned_predicates
.entry(spans
);
653 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
656 Some(Node
::Item(hir
::Item
{
657 kind
: hir
::ItemKind
::Impl(hir
::Impl { of_trait, self_ty, .. }
),
660 self_ty
.span
.ctxt().outer_expn_data().kind
,
661 ExpnKind
::Macro(MacroKind
::Derive
, _
)
663 of_trait
.as_ref().map(|t
| t
669 Some(ExpnKind
::Macro(MacroKind
::Derive
, _
))
672 let span
= self_ty
.span
.ctxt().outer_expn_data().call_site
;
673 let mut spans
: MultiSpan
= span
.into();
674 spans
.push_span_label(span
, derive_msg
.to_string());
675 let entry
= spanned_predicates
.entry(spans
);
676 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
679 // Unmet obligation coming from a `trait`.
680 Some(Node
::Item(hir
::Item
{
681 kind
: hir
::ItemKind
::Trait(..),
686 ident
.span
.ctxt().outer_expn_data().kind
,
687 ExpnKind
::Macro(MacroKind
::Derive
, _
)
690 if let Some(pred
) = parent_p
{
691 // Done to add the "doesn't satisfy" `span_label`.
692 let _
= format_pred(*pred
);
695 let mut spans
= if cause_span
!= *item_span
{
696 let mut spans
: MultiSpan
= cause_span
.into();
697 spans
.push_span_label(cause_span
, unsatisfied_msg
);
702 spans
.push_span_label(ident
.span
, "in this trait".to_string());
703 let entry
= spanned_predicates
.entry(spans
);
704 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
707 // Unmet obligation coming from an `impl`.
708 Some(Node
::Item(hir
::Item
{
709 kind
: hir
::ItemKind
::Impl(hir
::Impl { of_trait, self_ty, .. }
),
713 self_ty
.span
.ctxt().outer_expn_data().kind
,
714 ExpnKind
::Macro(MacroKind
::Derive
, _
)
716 of_trait
.as_ref().map(|t
| t
722 Some(ExpnKind
::Macro(MacroKind
::Derive
, _
))
725 if let Some(pred
) = parent_p
{
726 // Done to add the "doesn't satisfy" `span_label`.
727 let _
= format_pred(*pred
);
730 let mut spans
= if cause_span
!= *item_span
{
731 let mut spans
: MultiSpan
= cause_span
.into();
732 spans
.push_span_label(cause_span
, unsatisfied_msg
);
735 let mut spans
= Vec
::with_capacity(2);
736 if let Some(trait_ref
) = of_trait
{
737 spans
.push(trait_ref
.path
.span
);
739 spans
.push(self_ty
.span
);
742 if let Some(trait_ref
) = of_trait
{
743 spans
.push_span_label(trait_ref
.path
.span
, String
::new());
745 spans
.push_span_label(self_ty
.span
, String
::new());
747 let entry
= spanned_predicates
.entry(spans
);
748 entry
.or_insert_with(|| (path
, tr_self_ty
, Vec
::new())).2.push(p
);
753 let mut spanned_predicates
: Vec
<_
> = spanned_predicates
.into_iter().collect();
754 spanned_predicates
.sort_by_key(|(span
, (_
, _
, _
))| span
.primary_span());
755 for (span
, (_path
, _self_ty
, preds
)) in spanned_predicates
{
756 let mut preds
: Vec
<_
> = preds
758 .filter_map(|pred
| format_pred(*pred
))
759 .map(|(p
, _
)| format
!("`{}`", p
))
763 let msg
= if let [pred
] = &preds
[..] {
764 format
!("trait bound {} was not satisfied", pred
)
767 "the following trait bounds were not satisfied:\n{}",
771 err
.span_note(span
, &msg
);
772 unsatisfied_bounds
= true;
775 // The requirements that didn't have an `impl` span to show.
776 let mut bound_list
= unsatisfied_predicates
778 .filter_map(|(pred
, parent_pred
, _cause
)| {
779 format_pred(*pred
).map(|(p
, self_ty
)| {
780 collect_type_param_suggestions(self_ty
, *pred
, &p
);
783 None
=> format
!("`{}`", &p
),
784 Some(parent_pred
) => match format_pred(*parent_pred
) {
785 None
=> format
!("`{}`", &p
),
786 Some((parent_p
, _
)) => {
787 collect_type_param_suggestions(
793 "`{}`\nwhich is required by `{}`",
803 .filter(|(_
, pred
)| !skip_list
.contains(&pred
))
806 .collect
::<Vec
<(usize, String
)>>();
808 for ((span
, add_where_or_comma
), obligations
) in type_params
.into_iter() {
809 restrict_type_params
= true;
810 // #74886: Sort here so that the output is always the same.
811 let mut obligations
= obligations
.into_iter().collect
::<Vec
<_
>>();
813 err
.span_suggestion_verbose(
816 "consider restricting the type parameter{s} to satisfy the \
818 s
= pluralize
!(obligations
.len())
820 format
!("{} {}", add_where_or_comma
, obligations
.join(", ")),
821 Applicability
::MaybeIncorrect
,
825 bound_list
.sort_by(|(_
, a
), (_
, b
)| a
.cmp(b
)); // Sort alphabetically.
826 bound_list
.dedup_by(|(_
, a
), (_
, b
)| a
== b
); // #35677
827 bound_list
.sort_by_key(|(pos
, _
)| *pos
); // Keep the original predicate order.
829 if !bound_list
.is_empty() || !skip_list
.is_empty() {
830 let bound_list
= bound_list
832 .map(|(_
, path
)| path
)
835 let actual_prefix
= actual
.prefix_string(self.tcx
);
836 info
!("unimplemented_traits.len() == {}", unimplemented_traits
.len());
837 let (primary_message
, label
) = if unimplemented_traits
.len() == 1
838 && unimplemented_traits_only
843 .map(|(_
, (trait_ref
, obligation
))| {
844 if trait_ref
.self_ty().references_error()
845 || actual
.references_error()
850 let OnUnimplementedNote { message, label, .. }
=
851 self.infcx
.on_unimplemented_note(trait_ref
, &obligation
);
854 .unwrap_or((None
, None
))
858 let primary_message
= primary_message
.unwrap_or_else(|| format
!(
859 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
861 err
.set_primary_message(&primary_message
);
862 if let Some(label
) = label
{
863 custom_span_label
= true;
864 err
.span_label(span
, label
);
866 if !bound_list
.is_empty() {
868 "the following trait bounds were not satisfied:\n{bound_list}"
871 self.suggest_derive(&mut err
, &unsatisfied_predicates
);
873 unsatisfied_bounds
= true;
877 let label_span_not_found
= |err
: &mut DiagnosticBuilder
<'_
, _
>| {
878 if unsatisfied_predicates
.is_empty() {
879 err
.span_label(span
, format
!("{item_kind} not found in `{ty_str}`"));
880 let is_string_or_ref_str
= match actual
.kind() {
881 ty
::Ref(_
, ty
, _
) => {
885 ty
::Adt(adt
, _
) if self.tcx
.is_diagnostic_item(sym
::String
, adt
.did())
888 ty
::Adt(adt
, _
) => self.tcx
.is_diagnostic_item(sym
::String
, adt
.did()),
891 if is_string_or_ref_str
&& item_name
.name
== sym
::iter
{
892 err
.span_suggestion_verbose(
894 "because of the in-memory representation of `&str`, to obtain \
895 an `Iterator` over each of its codepoint use method `chars`",
897 Applicability
::MachineApplicable
,
900 if let ty
::Adt(adt
, _
) = rcvr_ty
.kind() {
901 let mut inherent_impls_candidate
= self
903 .inherent_impls(adt
.did())
907 if let Some(assoc
) = self.associated_value(*def_id
, item_name
) {
908 // Check for both mode is the same so we avoid suggesting
909 // incorrect associated item.
910 match (mode
, assoc
.fn_has_self_parameter
, source
) {
911 (Mode
::MethodCall
, true, SelfSource
::MethodCall(_
)) => {
912 // We check that the suggest type is actually
913 // different from the received one
914 // So we avoid suggestion method with Box<Self>
916 self.tcx
.at(span
).type_of(*def_id
) != actual
917 && self.tcx
.at(span
).type_of(*def_id
) != rcvr_ty
919 (Mode
::Path
, false, _
) => true,
926 .collect
::<Vec
<_
>>();
927 if !inherent_impls_candidate
.is_empty() {
928 inherent_impls_candidate
.sort();
929 inherent_impls_candidate
.dedup();
931 // number of type to shows at most.
932 let limit
= if inherent_impls_candidate
.len() == 5 { 5 }
else { 4 }
;
933 let type_candidates
= inherent_impls_candidate
937 format
!("- `{}`", self.tcx
.at(span
).type_of(*impl_item
))
941 let additional_types
= if inherent_impls_candidate
.len() > limit
{
943 "\nand {} more types",
944 inherent_impls_candidate
.len() - limit
950 "the {item_kind} was found for\n{}{}",
951 type_candidates
, additional_types
956 err
.span_label(span
, format
!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
960 // If the method name is the name of a field with a function or closure type,
961 // give a helping note that it has to be called as `(x.f)(...)`.
962 if let SelfSource
::MethodCall(expr
) = source
{
963 if !self.suggest_field_call(span
, rcvr_ty
, expr
, item_name
, &mut err
)
964 && lev_candidate
.is_none()
965 && !custom_span_label
967 label_span_not_found(&mut err
);
969 } else if !custom_span_label
{
970 label_span_not_found(&mut err
);
973 self.check_for_field_method(&mut err
, source
, span
, actual
, item_name
);
975 self.check_for_unwrap_self(&mut err
, source
, span
, actual
, item_name
);
979 for (span
, msg
) in bound_spans
.into_iter() {
980 err
.span_label(span
, &msg
);
983 if actual
.is_numeric() && actual
.is_fresh() || restrict_type_params
{
985 self.suggest_traits_to_import(
992 &unsatisfied_predicates
,
997 // Don't emit a suggestion if we found an actual method
998 // that had unsatisfied trait bounds
999 if unsatisfied_predicates
.is_empty() && actual
.is_enum() {
1000 let adt_def
= actual
.ty_adt_def().expect("enum is not an ADT");
1001 if let Some(suggestion
) = lev_distance
::find_best_match_for_name(
1002 &adt_def
.variants().iter().map(|s
| s
.name
).collect
::<Vec
<_
>>(),
1006 err
.span_suggestion(
1008 "there is a variant with a similar name",
1010 Applicability
::MaybeIncorrect
,
1015 if item_name
.name
== sym
::as_str
&& actual
.peel_refs().is_str() {
1016 let msg
= "remove this method call";
1017 let mut fallback_span
= true;
1018 if let SelfSource
::MethodCall(expr
) = source
{
1020 self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
));
1021 if let Some(span
) = call_expr
.span
.trim_start(expr
.span
) {
1022 err
.span_suggestion(span
, msg
, "", Applicability
::MachineApplicable
);
1023 fallback_span
= false;
1027 err
.span_label(span
, msg
);
1029 } else if let Some(lev_candidate
) = lev_candidate
{
1030 // Don't emit a suggestion if we found an actual method
1031 // that had unsatisfied trait bounds
1032 if unsatisfied_predicates
.is_empty() {
1033 let def_kind
= lev_candidate
.kind
.as_def_kind();
1034 err
.span_suggestion(
1037 "there is {} {} with a similar name",
1039 def_kind
.descr(lev_candidate
.def_id
),
1042 Applicability
::MaybeIncorrect
,
1050 MethodError
::Ambiguity(sources
) => {
1051 let mut err
= struct_span_err
!(
1055 "multiple applicable items in scope"
1057 err
.span_label(item_name
.span
, format
!("multiple `{}` found", item_name
));
1059 report_candidates(span
, &mut err
, sources
, sugg_span
);
1063 MethodError
::PrivateMatch(kind
, def_id
, out_of_scope_traits
) => {
1064 let kind
= kind
.descr(def_id
);
1065 let mut err
= struct_span_err
!(
1069 "{} `{}` is private",
1073 err
.span_label(item_name
.span
, &format
!("private {}", kind
));
1077 .span_if_local(def_id
)
1078 .unwrap_or_else(|| self.tcx
.def_span(def_id
));
1079 err
.span_label(sp
, &format
!("private {} defined here", kind
));
1080 self.suggest_valid_traits(&mut err
, out_of_scope_traits
);
1084 MethodError
::IllegalSizedBound(candidates
, needs_mut
, bound_span
) => {
1085 let msg
= format
!("the `{}` method cannot be invoked on a trait object", item_name
);
1086 let mut err
= self.sess().struct_span_err(span
, &msg
);
1087 err
.span_label(bound_span
, "this has a `Sized` requirement");
1088 if !candidates
.is_empty() {
1090 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
1091 add a `use` for {one_of_them}:",
1092 an
= if candidates
.len() == 1 { "an" }
else { "" }
,
1093 s
= pluralize
!(candidates
.len()),
1094 were
= if candidates
.len() == 1 { "was" }
else { "were" }
,
1095 one_of_them
= if candidates
.len() == 1 { "it" }
else { "one_of_them" }
,
1097 self.suggest_use_candidates(&mut err
, help
, candidates
);
1099 if let ty
::Ref(region
, t_type
, mutability
) = rcvr_ty
.kind() {
1101 let trait_type
= self.tcx
.mk_ref(
1103 ty
::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }
,
1105 err
.note(&format
!("you need `{}` instead of `{}`", trait_type
, rcvr_ty
));
1111 MethodError
::BadReturnType
=> bug
!("no return type expectations but got BadReturnType"),
1116 fn suggest_field_call(
1120 expr
: &hir
::Expr
<'_
>,
1122 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1125 let field_receiver
= self.autoderef(span
, rcvr_ty
).find_map(|(ty
, _
)| match ty
.kind() {
1126 ty
::Adt(def
, substs
) if !def
.is_enum() => {
1127 let variant
= &def
.non_enum_variant();
1128 tcx
.find_field_index(item_name
, variant
).map(|index
| {
1129 let field
= &variant
.fields
[index
];
1130 let field_ty
= field
.ty(tcx
, substs
);
1136 if let Some((field
, field_ty
)) = field_receiver
{
1137 let scope
= tcx
.parent_module(self.body_id
).to_def_id();
1138 let is_accessible
= field
.vis
.is_accessible_from(scope
, tcx
);
1141 if self.is_fn_ty(field_ty
, span
) {
1142 let expr_span
= expr
.span
.to(item_name
.span
);
1143 err
.multipart_suggestion(
1145 "to call the function stored in `{}`, \
1146 surround the field access with parentheses",
1150 (expr_span
.shrink_to_lo(), '
('
.to_string()),
1151 (expr_span
.shrink_to_hi(), '
)'
.to_string()),
1153 Applicability
::MachineApplicable
,
1156 let call_expr
= tcx
.hir().expect_expr(tcx
.hir().get_parent_node(expr
.hir_id
));
1158 if let Some(span
) = call_expr
.span
.trim_start(item_name
.span
) {
1159 err
.span_suggestion(
1161 "remove the arguments",
1163 Applicability
::MaybeIncorrect
,
1169 let field_kind
= if is_accessible { "field" }
else { "private field" }
;
1170 err
.span_label(item_name
.span
, format
!("{}, not a method", field_kind
));
1176 fn suggest_constraining_numerical_ty(
1180 source
: SelfSource
<'_
>,
1186 let found_candidate
= all_traits(self.tcx
)
1188 .any(|info
| self.associated_value(info
.def_id
, item_name
).is_some());
1189 let found_assoc
= |ty
: Ty
<'tcx
>| {
1190 simplify_type(tcx
, ty
, TreatParams
::AsInfer
)
1192 tcx
.incoherent_impls(simp
)
1194 .find_map(|&id
| self.associated_value(id
, item_name
))
1198 let found_candidate
= found_candidate
1199 || found_assoc(tcx
.types
.i8)
1200 || found_assoc(tcx
.types
.i16)
1201 || found_assoc(tcx
.types
.i32)
1202 || found_assoc(tcx
.types
.i64)
1203 || found_assoc(tcx
.types
.i128
)
1204 || found_assoc(tcx
.types
.u8)
1205 || found_assoc(tcx
.types
.u16)
1206 || found_assoc(tcx
.types
.u32)
1207 || found_assoc(tcx
.types
.u64)
1208 || found_assoc(tcx
.types
.u128
)
1209 || found_assoc(tcx
.types
.f32)
1210 || found_assoc(tcx
.types
.f32);
1212 && actual
.is_numeric()
1213 && !actual
.has_concrete_skeleton()
1214 && let SelfSource
::MethodCall(expr
) = source
1216 let mut err
= struct_span_err
!(
1220 "can't call {} `{}` on ambiguous numeric type `{}`",
1225 let concrete_type
= if actual
.is_integral() { "i32" }
else { "f32" }
;
1227 ExprKind
::Lit(ref lit
) => {
1232 .span_to_snippet(lit
.span
)
1233 .unwrap_or_else(|_
| "<numeric literal>".to_owned());
1235 // If this is a floating point literal that ends with '.',
1236 // get rid of it to stop this from becoming a member access.
1237 let snippet
= snippet
.strip_suffix('
.'
).unwrap_or(&snippet
);
1239 err
.span_suggestion(
1242 "you must specify a concrete type for this numeric value, \
1246 format
!("{snippet}_{concrete_type}"),
1247 Applicability
::MaybeIncorrect
,
1250 ExprKind
::Path(QPath
::Resolved(_
, path
)) => {
1252 if let hir
::def
::Res
::Local(hir_id
) = path
.res
{
1253 let span
= tcx
.hir().span(hir_id
);
1254 let snippet
= tcx
.sess
.source_map().span_to_snippet(span
);
1255 let filename
= tcx
.sess
.source_map().span_to_filename(span
);
1258 self.tcx
.hir().get(self.tcx
.hir().get_parent_node(hir_id
));
1260 "you must specify a type for this binding, like `{}`",
1264 match (filename
, parent_node
, snippet
) {
1267 Node
::Local(hir
::Local
{
1268 source
: hir
::LocalSource
::Normal
,
1274 err
.span_suggestion(
1275 // account for `let x: _ = 42;`
1277 span
.to(ty
.as_ref().map(|ty
| ty
.span
).unwrap_or(span
)),
1279 format
!("{}: {}", snippet
, concrete_type
),
1280 Applicability
::MaybeIncorrect
,
1284 err
.span_label(span
, msg
);
1297 fn check_for_field_method(
1299 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1300 source
: SelfSource
<'tcx
>,
1305 if let SelfSource
::MethodCall(expr
) = source
1306 && let Some((fields
, substs
)) = self.get_field_candidates(span
, actual
)
1308 let call_expr
= self.tcx
.hir().expect_expr(self.tcx
.hir().get_parent_node(expr
.hir_id
));
1309 for candidate_field
in fields
.iter() {
1310 if let Some(field_path
) = self.check_for_nested_field_satisfying(
1318 ProbeScope
::AllTraits
,
1325 self.tcx
.parent_module(expr
.hir_id
).to_def_id(),
1327 let field_path_str
= field_path
1329 .map(|id
| id
.name
.to_ident_string())
1330 .collect
::<Vec
<String
>>()
1332 debug
!("field_path_str: {:?}", field_path_str
);
1334 err
.span_suggestion_verbose(
1335 item_name
.span
.shrink_to_lo(),
1336 "one of the expressions' fields has a method of the same name",
1337 format
!("{field_path_str}."),
1338 Applicability
::MaybeIncorrect
,
1345 fn check_for_unwrap_self(
1347 err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1348 source
: SelfSource
<'tcx
>,
1354 let SelfSource
::MethodCall(expr
) = source
else { return; }
;
1355 let call_expr
= tcx
.hir().expect_expr(tcx
.hir().get_parent_node(expr
.hir_id
));
1357 let ty
::Adt(kind
, substs
) = actual
.kind() else { return; }
;
1358 if !kind
.is_enum() {
1362 let matching_variants
: Vec
<_
> = kind
1365 .flat_map(|variant
| {
1366 let [field
] = &variant
.fields
[..] else { return None; }
;
1367 let field_ty
= field
.ty(tcx
, substs
);
1369 // Skip `_`, since that'll just lead to ambiguity.
1370 if self.resolve_vars_if_possible(field_ty
).is_ty_var() {
1374 self.lookup_probe(span
, item_name
, field_ty
, call_expr
, ProbeScope
::AllTraits
)
1376 .map(|pick
| (variant
, field
, pick
))
1380 let ret_ty_matches
= |diagnostic_item
| {
1381 if let Some(ret_ty
) = self
1384 .map(|c
| self.resolve_vars_if_possible(c
.borrow().expected_ty()))
1385 && let ty
::Adt(kind
, _
) = ret_ty
.kind()
1386 && tcx
.get_diagnostic_item(diagnostic_item
) == Some(kind
.did())
1394 match &matching_variants
[..] {
1395 [(_
, field
, pick
)] => {
1396 let self_ty
= field
.ty(tcx
, substs
);
1398 tcx
.def_span(pick
.item
.def_id
),
1399 &format
!("the method `{item_name}` exists on the type `{self_ty}`"),
1401 let (article
, kind
, variant
, question
) =
1402 if Some(kind
.did()) == tcx
.get_diagnostic_item(sym
::Result
) {
1403 ("a", "Result", "Err", ret_ty_matches(sym
::Result
))
1404 } else if Some(kind
.did()) == tcx
.get_diagnostic_item(sym
::Option
) {
1405 ("an", "Option", "None", ret_ty_matches(sym
::Option
))
1410 err
.span_suggestion_verbose(
1411 expr
.span
.shrink_to_hi(),
1413 "use the `?` operator to extract the `{self_ty}` value, propagating \
1414 {article} `{kind}::{variant}` value to the caller"
1417 Applicability
::MachineApplicable
,
1420 err
.span_suggestion_verbose(
1421 expr
.span
.shrink_to_hi(),
1423 "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1424 panicking if the value is {article} `{kind}::{variant}`"
1426 ".expect(\"REASON\")",
1427 Applicability
::HasPlaceholders
,
1431 // FIXME(compiler-errors): Support suggestions for other matching enum variants
1436 pub(crate) fn note_unmet_impls_on_type(
1438 err
: &mut Diagnostic
,
1439 errors
: Vec
<FulfillmentError
<'tcx
>>,
1441 let all_local_types_needing_impls
=
1442 errors
.iter().all(|e
| match e
.obligation
.predicate
.kind().skip_binder() {
1443 ty
::PredicateKind
::Trait(pred
) => match pred
.self_ty().kind() {
1444 ty
::Adt(def
, _
) => def
.did().is_local(),
1449 let mut preds
: Vec
<_
> = errors
1451 .filter_map(|e
| match e
.obligation
.predicate
.kind().skip_binder() {
1452 ty
::PredicateKind
::Trait(pred
) => Some(pred
),
1456 preds
.sort_by_key(|pred
| (pred
.def_id(), pred
.self_ty()));
1459 .filter_map(|pred
| match pred
.self_ty().kind() {
1460 ty
::Adt(def
, _
) => Some(def
.did()),
1463 .collect
::<FxHashSet
<_
>>();
1464 let sm
= self.tcx
.sess
.source_map();
1465 let mut spans
: MultiSpan
= def_ids
1467 .filter_map(|def_id
| {
1468 let span
= self.tcx
.def_span(*def_id
);
1469 if span
.is_dummy() { None }
else { Some(sm.guess_head_span(span)) }
1471 .collect
::<Vec
<_
>>()
1474 for pred
in &preds
{
1475 match pred
.self_ty().kind() {
1476 ty
::Adt(def
, _
) => {
1477 spans
.push_span_label(
1478 sm
.guess_head_span(self.tcx
.def_span(def
.did())),
1479 format
!("must implement `{}`", pred
.trait_ref
.print_only_trait_path()),
1486 if all_local_types_needing_impls
&& spans
.primary_span().is_some() {
1487 let msg
= if preds
.len() == 1 {
1489 "an implementation of `{}` might be missing for `{}`",
1490 preds
[0].trait_ref
.print_only_trait_path(),
1495 "the following type{} would have to `impl` {} required trait{} for this \
1496 operation to be valid",
1497 pluralize
!(def_ids
.len()),
1498 if def_ids
.len() == 1 { "its" }
else { "their" }
,
1499 pluralize
!(preds
.len()),
1502 err
.span_note(spans
, &msg
);
1505 let preds
: Vec
<_
> = errors
1507 .map(|e
| (e
.obligation
.predicate
, None
, Some(e
.obligation
.cause
.clone())))
1509 self.suggest_derive(err
, &preds
);
1514 err
: &mut Diagnostic
,
1515 unsatisfied_predicates
: &[(
1516 ty
::Predicate
<'tcx
>,
1517 Option
<ty
::Predicate
<'tcx
>>,
1518 Option
<ObligationCause
<'tcx
>>,
1521 let mut derives
= Vec
::<(String
, Span
, String
)>::new();
1522 let mut traits
= Vec
::<Span
>::new();
1523 for (pred
, _
, _
) in unsatisfied_predicates
{
1524 let ty
::PredicateKind
::Trait(trait_pred
) = pred
.kind().skip_binder() else { continue }
;
1525 let adt
= match trait_pred
.self_ty().ty_adt_def() {
1526 Some(adt
) if adt
.did().is_local() => adt
,
1529 if let Some(diagnostic_name
) = self.tcx
.get_diagnostic_name(trait_pred
.def_id()) {
1530 let can_derive
= match diagnostic_name
{
1531 sym
::Default
=> !adt
.is_enum(),
1539 | sym
::Debug
=> true,
1543 let self_name
= trait_pred
.self_ty().to_string();
1544 let self_span
= self.tcx
.def_span(adt
.did());
1545 if let Some(poly_trait_ref
) = pred
.to_opt_poly_trait_pred() {
1546 for super_trait
in supertraits(self.tcx
, poly_trait_ref
.to_poly_trait_ref())
1548 if let Some(parent_diagnostic_name
) =
1549 self.tcx
.get_diagnostic_name(super_trait
.def_id())
1554 parent_diagnostic_name
.to_string(),
1559 derives
.push((self_name
, self_span
, diagnostic_name
.to_string()));
1561 traits
.push(self.tcx
.def_span(trait_pred
.def_id()));
1564 traits
.push(self.tcx
.def_span(trait_pred
.def_id()));
1573 let mut derives_grouped
= Vec
::<(String
, Span
, String
)>::new();
1574 for (self_name
, self_span
, trait_name
) in derives
.into_iter() {
1575 if let Some((last_self_name
, _
, ref mut last_trait_names
)) = derives_grouped
.last_mut()
1577 if last_self_name
== &self_name
{
1578 last_trait_names
.push_str(format
!(", {}", trait_name
).as_str());
1582 derives_grouped
.push((self_name
, self_span
, trait_name
));
1585 let len
= traits
.len();
1587 let span
: MultiSpan
= traits
.into();
1590 &format
!("the following trait{} must be implemented", pluralize
!(len
),),
1594 for (self_name
, self_span
, traits
) in &derives_grouped
{
1595 err
.span_suggestion_verbose(
1596 self_span
.shrink_to_lo(),
1597 &format
!("consider annotating `{}` with `#[derive({})]`", self_name
, traits
),
1598 format
!("#[derive({})]\n", traits
),
1599 Applicability
::MaybeIncorrect
,
1604 /// Print out the type for use in value namespace.
1605 fn ty_to_value_string(&self, ty
: Ty
<'tcx
>) -> String
{
1607 ty
::Adt(def
, substs
) => format
!("{}", ty
::Instance
::new(def
.did(), substs
)),
1608 _
=> self.ty_to_string(ty
),
1612 fn suggest_await_before_method(
1614 err
: &mut Diagnostic
,
1617 call
: &hir
::Expr
<'_
>,
1620 let output_ty
= match self.infcx
.get_impl_future_output_ty(ty
) {
1621 Some(output_ty
) => self.resolve_vars_if_possible(output_ty
).skip_binder(),
1624 let method_exists
= self.method_exists(item_name
, output_ty
, call
.hir_id
, true);
1625 debug
!("suggest_await_before_method: is_method_exist={}", method_exists
);
1627 err
.span_suggestion_verbose(
1628 span
.shrink_to_lo(),
1629 "consider `await`ing on the `Future` and calling the method on its `Output`",
1631 Applicability
::MaybeIncorrect
,
1636 fn suggest_use_candidates(&self, err
: &mut Diagnostic
, msg
: String
, candidates
: Vec
<DefId
>) {
1637 let parent_map
= self.tcx
.visible_parent_map(());
1639 // Separate out candidates that must be imported with a glob, because they are named `_`
1640 // and cannot be referred with their identifier.
1641 let (candidates
, globs
): (Vec
<_
>, Vec
<_
>) = candidates
.into_iter().partition(|trait_did
| {
1642 if let Some(parent_did
) = parent_map
.get(trait_did
) {
1643 // If the item is re-exported as `_`, we should suggest a glob-import instead.
1644 if *parent_did
!= self.tcx
.parent(*trait_did
)
1647 .module_children(*parent_did
)
1649 .filter(|child
| child
.res
.opt_def_id() == Some(*trait_did
))
1650 .all(|child
| child
.ident
.name
== kw
::Underscore
)
1659 let module_did
= self.tcx
.parent_module(self.body_id
);
1660 let (module
, _
, _
) = self.tcx
.hir().get_module(module_did
);
1661 let span
= module
.spans
.inject_use_span
;
1663 let path_strings
= candidates
.iter().map(|trait_did
| {
1664 format
!("use {};\n", with_crate_prefix
!(self.tcx
.def_path_str(*trait_did
)),)
1667 let glob_path_strings
= globs
.iter().map(|trait_did
| {
1668 let parent_did
= parent_map
.get(trait_did
).unwrap();
1670 "use {}::*; // trait {}\n",
1671 with_crate_prefix
!(self.tcx
.def_path_str(*parent_did
)),
1672 self.tcx
.item_name(*trait_did
),
1676 err
.span_suggestions(
1679 path_strings
.chain(glob_path_strings
),
1680 Applicability
::MaybeIncorrect
,
1684 fn suggest_valid_traits(
1686 err
: &mut Diagnostic
,
1687 valid_out_of_scope_traits
: Vec
<DefId
>,
1689 if !valid_out_of_scope_traits
.is_empty() {
1690 let mut candidates
= valid_out_of_scope_traits
;
1694 // `TryFrom` and `FromIterator` have no methods
1695 let edition_fix
= candidates
1697 .find(|did
| self.tcx
.is_diagnostic_item(sym
::TryInto
, **did
))
1700 err
.help("items from traits can only be used if the trait is in scope");
1702 "the following {traits_are} implemented but not in scope; \
1703 perhaps add a `use` for {one_of_them}:",
1704 traits_are
= if candidates
.len() == 1 { "trait is" }
else { "traits are" }
,
1705 one_of_them
= if candidates
.len() == 1 { "it" }
else { "one of them" }
,
1708 self.suggest_use_candidates(err
, msg
, candidates
);
1709 if let Some(did
) = edition_fix
{
1711 "'{}' is included in the prelude starting in Edition 2021",
1712 with_crate_prefix
!(self.tcx
.def_path_str(did
))
1722 fn suggest_traits_to_import(
1724 err
: &mut Diagnostic
,
1728 source
: SelfSource
<'tcx
>,
1729 valid_out_of_scope_traits
: Vec
<DefId
>,
1730 unsatisfied_predicates
: &[(
1731 ty
::Predicate
<'tcx
>,
1732 Option
<ty
::Predicate
<'tcx
>>,
1733 Option
<ObligationCause
<'tcx
>>,
1735 unsatisfied_bounds
: bool
,
1737 let mut alt_rcvr_sugg
= false;
1738 if let (SelfSource
::MethodCall(rcvr
), false) = (source
, unsatisfied_bounds
) {
1739 debug
!(?span
, ?item_name
, ?rcvr_ty
, ?rcvr
);
1741 self.tcx
.lang_items().clone_trait(),
1742 self.tcx
.lang_items().deref_trait(),
1743 self.tcx
.lang_items().deref_mut_trait(),
1744 self.tcx
.lang_items().drop_trait(),
1745 self.tcx
.get_diagnostic_item(sym
::AsRef
),
1747 // Try alternative arbitrary self types that could fulfill this call.
1748 // FIXME: probe for all types that *could* be arbitrary self-types, not
1750 for (rcvr_ty
, post
) in &[
1752 (self.tcx
.mk_mut_ref(self.tcx
.lifetimes
.re_erased
, rcvr_ty
), "&mut "),
1753 (self.tcx
.mk_imm_ref(self.tcx
.lifetimes
.re_erased
, rcvr_ty
), "&"),
1755 match self.lookup_probe(span
, item_name
, *rcvr_ty
, rcvr
, ProbeScope
::AllTraits
) {
1757 // If the method is defined for the receiver we have, it likely wasn't `use`d.
1758 // We point at the method, but we just skip the rest of the check for arbitrary
1759 // self types and rely on the suggestion to `use` the trait from
1760 // `suggest_valid_traits`.
1761 let did
= Some(pick
.item
.container
.id());
1762 let skip
= skippable
.contains(&did
);
1763 if pick
.autoderefs
== 0 && !skip
{
1765 pick
.item
.ident(self.tcx
).span
,
1766 &format
!("the method is available for `{}` here", rcvr_ty
),
1771 Err(MethodError
::Ambiguity(_
)) => {
1772 // If the method is defined (but ambiguous) for the receiver we have, it is also
1773 // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1774 // the receiver, then it might disambiguate this method, but I think these
1775 // suggestions are generally misleading (see #94218).
1781 for (rcvr_ty
, pre
) in &[
1782 (self.tcx
.mk_lang_item(*rcvr_ty
, LangItem
::OwnedBox
), "Box::new"),
1783 (self.tcx
.mk_lang_item(*rcvr_ty
, LangItem
::Pin
), "Pin::new"),
1784 (self.tcx
.mk_diagnostic_item(*rcvr_ty
, sym
::Arc
), "Arc::new"),
1785 (self.tcx
.mk_diagnostic_item(*rcvr_ty
, sym
::Rc
), "Rc::new"),
1787 if let Some(new_rcvr_t
) = *rcvr_ty
1788 && let Ok(pick
) = self.lookup_probe(
1793 ProbeScope
::AllTraits
,
1796 debug
!("try_alt_rcvr: pick candidate {:?}", pick
);
1797 let did
= Some(pick
.item
.container
.id());
1798 // We don't want to suggest a container type when the missing
1799 // method is `.clone()` or `.deref()` otherwise we'd suggest
1800 // `Arc::new(foo).clone()`, which is far from what the user wants.
1801 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
1802 // implement the `AsRef` trait.
1803 let skip
= skippable
.contains(&did
)
1804 || (("Pin::new" == *pre
) && (sym
::as_ref
== item_name
.name
));
1805 // Make sure the method is defined for the *actual* receiver: we don't
1806 // want to treat `Box<Self>` as a receiver if it only works because of
1807 // an autoderef to `&self`
1808 if pick
.autoderefs
== 0 && !skip
{
1810 pick
.item
.ident(self.tcx
).span
,
1811 &format
!("the method is available for `{}` here", new_rcvr_t
),
1813 err
.multipart_suggestion(
1814 "consider wrapping the receiver expression with the \
1817 (rcvr
.span
.shrink_to_lo(), format
!("{}({}", pre
, post
)),
1818 (rcvr
.span
.shrink_to_hi(), ")".to_string()),
1820 Applicability
::MaybeIncorrect
,
1822 // We don't care about the other suggestions.
1823 alt_rcvr_sugg
= true;
1829 if self.suggest_valid_traits(err
, valid_out_of_scope_traits
) {
1833 let type_is_local
= self.type_derefs_to_local(span
, rcvr_ty
, source
);
1835 let mut arbitrary_rcvr
= vec
![];
1836 // There are no traits implemented, so lets suggest some traits to
1837 // implement, by finding ones that have the item name, and are
1838 // legal to implement.
1839 let mut candidates
= all_traits(self.tcx
)
1841 // Don't issue suggestions for unstable traits since they're
1842 // unlikely to be implementable anyway
1843 .filter(|info
| match self.tcx
.lookup_stability(info
.def_id
) {
1844 Some(attr
) => attr
.level
.is_stable(),
1848 // We approximate the coherence rules to only suggest
1849 // traits that are legal to implement by requiring that
1850 // either the type or trait is local. Multi-dispatch means
1851 // this isn't perfect (that is, there are cases when
1852 // implementing a trait would be legal but is rejected
1854 unsatisfied_predicates
.iter().all(|(p
, _
, _
)| {
1855 match p
.kind().skip_binder() {
1856 // Hide traits if they are present in predicates as they can be fixed without
1857 // having to implement them.
1858 ty
::PredicateKind
::Trait(t
) => t
.def_id() == info
.def_id
,
1859 ty
::PredicateKind
::Projection(p
) => {
1860 p
.projection_ty
.item_def_id
== info
.def_id
1864 }) && (type_is_local
|| info
.def_id
.is_local())
1866 .associated_value(info
.def_id
, item_name
)
1868 if let ty
::AssocKind
::Fn
= item
.kind
{
1872 .map(|def_id
| self.tcx
.hir().local_def_id_to_hir_id(def_id
));
1873 if let Some(hir
::Node
::TraitItem(hir
::TraitItem
{
1874 kind
: hir
::TraitItemKind
::Fn(fn_sig
, method
),
1876 })) = id
.map(|id
| self.tcx
.hir().get(id
))
1878 let self_first_arg
= match method
{
1879 hir
::TraitFn
::Required([ident
, ..]) => {
1880 ident
.name
== kw
::SelfLower
1882 hir
::TraitFn
::Provided(body_id
) => {
1883 self.tcx
.hir().body(*body_id
).params
.first().map_or(
1888 hir
::PatKind
::Binding(_
, _
, ident
, _
)
1889 if ident
.name
== kw
::SelfLower
1897 if !fn_sig
.decl
.implicit_self
.has_implicit_self()
1900 if let Some(ty
) = fn_sig
.decl
.inputs
.get(0) {
1901 arbitrary_rcvr
.push(ty
.span
);
1907 // We only want to suggest public or local traits (#45781).
1908 item
.vis
.is_public() || info
.def_id
.is_local()
1912 .collect
::<Vec
<_
>>();
1913 for span
in &arbitrary_rcvr
{
1916 "the method might not be found because of this arbitrary self type",
1923 if !candidates
.is_empty() {
1924 // Sort from most relevant to least relevant.
1925 candidates
.sort_by(|a
, b
| a
.cmp(b
).reverse());
1928 let param_type
= match rcvr_ty
.kind() {
1929 ty
::Param(param
) => Some(param
),
1930 ty
::Ref(_
, ty
, _
) => match ty
.kind() {
1931 ty
::Param(param
) => Some(param
),
1936 err
.help(if param_type
.is_some() {
1937 "items from traits can only be used if the type parameter is bounded by the trait"
1939 "items from traits can only be used if the trait is implemented and in scope"
1941 let candidates_len
= candidates
.len();
1942 let message
= |action
| {
1944 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1947 if candidates_len
== 1 { "trait defines" }
else { "traits define" }
,
1949 one_of_them
= if candidates_len
== 1 { "it" }
else { "one of them" }
,
1953 // Obtain the span for `param` and use it for a structured suggestion.
1954 if let (Some(param
), Some(table
)) = (param_type
, self.in_progress_typeck_results
) {
1955 let table_owner
= table
.borrow().hir_owner
;
1956 let generics
= self.tcx
.generics_of(table_owner
.to_def_id());
1957 let type_param
= generics
.type_param(param
, self.tcx
);
1958 let hir
= self.tcx
.hir();
1959 if let Some(def_id
) = type_param
.def_id
.as_local() {
1960 let id
= hir
.local_def_id_to_hir_id(def_id
);
1961 // Get the `hir::Param` to verify whether it already has any bounds.
1962 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1963 // instead we suggest `T: Foo + Bar` in that case.
1965 Node
::GenericParam(param
) => {
1971 let ast_generics
= hir
.get_generics(id
.owner
).unwrap();
1972 let (sp
, mut introducer
) = if let Some(span
) =
1973 ast_generics
.bounds_span_for_suggestions(def_id
)
1975 (span
, Introducer
::Plus
)
1976 } else if let Some(colon_span
) = param
.colon_span
{
1977 (colon_span
.shrink_to_hi(), Introducer
::Nothing
)
1979 (param
.span
.shrink_to_hi(), Introducer
::Colon
)
1983 hir
::GenericParamKind
::Type { synthetic: true, .. }
,
1985 introducer
= Introducer
::Plus
1987 let trait_def_ids
: FxHashSet
<DefId
> = ast_generics
1988 .bounds_for_param(def_id
)
1989 .flat_map(|bp
| bp
.bounds
.iter())
1990 .filter_map(|bound
| bound
.trait_ref()?
.trait_def_id())
1992 if !candidates
.iter().any(|t
| trait_def_ids
.contains(&t
.def_id
)) {
1993 err
.span_suggestions(
1996 "restrict type parameter `{}` with",
1999 candidates
.iter().map(|t
| {
2003 Introducer
::Plus
=> " +",
2004 Introducer
::Colon
=> ":",
2005 Introducer
::Nothing
=> "",
2007 self.tcx
.def_path_str(t
.def_id
),
2010 Applicability
::MaybeIncorrect
,
2015 Node
::Item(hir
::Item
{
2016 kind
: hir
::ItemKind
::Trait(.., bounds
, _
),
2020 let (sp
, sep
, article
) = if bounds
.is_empty() {
2021 (ident
.span
.shrink_to_hi(), ":", "a")
2023 (bounds
.last().unwrap().span().shrink_to_hi(), " +", "another")
2025 err
.span_suggestions(
2027 &message(format
!("add {} supertrait for", article
)),
2028 candidates
.iter().map(|t
| {
2029 format
!("{} {}", sep
, self.tcx
.def_path_str(t
.def_id
),)
2031 Applicability
::MaybeIncorrect
,
2040 let (potential_candidates
, explicitly_negative
) = if param_type
.is_some() {
2041 // FIXME: Even though negative bounds are not implemented, we could maybe handle
2042 // cases where a positive bound implies a negative impl.
2043 (candidates
, Vec
::new())
2044 } else if let Some(simp_rcvr_ty
) =
2045 simplify_type(self.tcx
, rcvr_ty
, TreatParams
::AsPlaceholder
)
2047 let mut potential_candidates
= Vec
::new();
2048 let mut explicitly_negative
= Vec
::new();
2049 for candidate
in candidates
{
2050 // Check if there's a negative impl of `candidate` for `rcvr_ty`
2053 .all_impls(candidate
.def_id
)
2055 self.tcx
.impl_polarity(*imp_did
) == ty
::ImplPolarity
::Negative
2058 let imp
= self.tcx
.impl_trait_ref(imp_did
).unwrap();
2060 simplify_type(self.tcx
, imp
.self_ty(), TreatParams
::AsPlaceholder
);
2061 imp_simp
.map_or(false, |s
| s
== simp_rcvr_ty
)
2064 explicitly_negative
.push(candidate
);
2066 potential_candidates
.push(candidate
);
2069 (potential_candidates
, explicitly_negative
)
2071 // We don't know enough about `recv_ty` to make proper suggestions.
2072 (candidates
, Vec
::new())
2075 let action
= if let Some(param
) = param_type
{
2076 format
!("restrict type parameter `{}` with", param
)
2078 // FIXME: it might only need to be imported into scope, not implemented.
2079 "implement".to_string()
2081 match &potential_candidates
[..] {
2083 [trait_info
] if trait_info
.def_id
.is_local() => {
2084 let span
= self.tcx
.hir().span_if_local(trait_info
.def_id
).unwrap();
2086 self.tcx
.sess
.source_map().guess_head_span(span
),
2088 "`{}` defines an item `{}`, perhaps you need to {} it",
2089 self.tcx
.def_path_str(trait_info
.def_id
),
2096 let mut msg
= message(action
);
2097 for (i
, trait_info
) in trait_infos
.iter().enumerate() {
2098 msg
.push_str(&format
!(
2099 "\ncandidate #{}: `{}`",
2101 self.tcx
.def_path_str(trait_info
.def_id
),
2107 match &explicitly_negative
[..] {
2111 "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
2112 self.tcx
.def_path_str(trait_info
.def_id
),
2118 let mut msg
= format
!(
2119 "the following traits define an item `{}`, but are explicitly unimplemented:",
2122 for trait_info
in trait_infos
{
2123 msg
.push_str(&format
!("\n{}", self.tcx
.def_path_str(trait_info
.def_id
)));
2131 /// Checks whether there is a local type somewhere in the chain of
2132 /// autoderefs of `rcvr_ty`.
2133 fn type_derefs_to_local(
2137 source
: SelfSource
<'tcx
>,
2139 fn is_local(ty
: Ty
<'_
>) -> bool
{
2141 ty
::Adt(def
, _
) => def
.did().is_local(),
2142 ty
::Foreign(did
) => did
.is_local(),
2143 ty
::Dynamic(tr
, ..) => tr
.principal().map_or(false, |d
| d
.def_id().is_local()),
2144 ty
::Param(_
) => true,
2146 // Everything else (primitive types, etc.) is effectively
2147 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
2148 // the noise from these sort of types is usually just really
2149 // annoying, rather than any sort of help).
2154 // This occurs for UFCS desugaring of `T::method`, where there is no
2155 // receiver expression for the method call, and thus no autoderef.
2156 if let SelfSource
::QPath(_
) = source
{
2157 return is_local(self.resolve_vars_with_obligations(rcvr_ty
));
2160 self.autoderef(span
, rcvr_ty
).any(|(ty
, _
)| is_local(ty
))
2164 #[derive(Copy, Clone, Debug)]
2165 pub enum SelfSource
<'a
> {
2166 QPath(&'a hir
::Ty
<'a
>),
2167 MethodCall(&'a hir
::Expr
<'a
> /* rcvr */),
2170 #[derive(Copy, Clone)]
2171 pub struct TraitInfo
{
2175 impl PartialEq
for TraitInfo
{
2176 fn eq(&self, other
: &TraitInfo
) -> bool
{
2177 self.cmp(other
) == Ordering
::Equal
2180 impl Eq
for TraitInfo {}
2181 impl PartialOrd
for TraitInfo
{
2182 fn partial_cmp(&self, other
: &TraitInfo
) -> Option
<Ordering
> {
2183 Some(self.cmp(other
))
2186 impl Ord
for TraitInfo
{
2187 fn cmp(&self, other
: &TraitInfo
) -> Ordering
{
2188 // Local crates are more important than remote ones (local:
2189 // `cnum == 0`), and otherwise we throw in the defid for totality.
2191 let lhs
= (other
.def_id
.krate
, other
.def_id
);
2192 let rhs
= (self.def_id
.krate
, self.def_id
);
2197 /// Retrieves all traits in this crate and any dependent crates,
2198 /// and wraps them into `TraitInfo` for custom sorting.
2199 pub fn all_traits(tcx
: TyCtxt
<'_
>) -> Vec
<TraitInfo
> {
2200 tcx
.all_traits().map(|def_id
| TraitInfo { def_id }
).collect()
2203 fn print_disambiguation_help
<'tcx
>(
2205 args
: Option
<&'tcx
[hir
::Expr
<'tcx
>]>,
2206 err
: &mut Diagnostic
,
2209 kind
: ty
::AssocKind
,
2212 candidate
: Option
<usize>,
2213 source_map
: &source_map
::SourceMap
,
2214 fn_has_self_parameter
: bool
,
2216 let mut applicability
= Applicability
::MachineApplicable
;
2217 let (span
, sugg
) = if let (ty
::AssocKind
::Fn
, Some(args
)) = (kind
, args
) {
2220 if rcvr_ty
.is_region_ptr() {
2221 if rcvr_ty
.is_mutable_ptr() { "&mut " }
else { "&" }
2226 .map(|arg
| source_map
.span_to_snippet(arg
.span
).unwrap_or_else(|_
| {
2227 applicability
= Applicability
::HasPlaceholders
;
2230 .collect
::<Vec
<_
>>()
2233 let trait_name
= if !fn_has_self_parameter
{
2234 format
!("<{} as {}>", rcvr_ty
, trait_name
)
2238 (span
, format
!("{}::{}{}", trait_name
, item_name
, args
))
2240 (span
.with_hi(item_name
.span
.lo()), format
!("<{} as {}>::", rcvr_ty
, trait_name
))
2242 err
.span_suggestion_verbose(
2245 "disambiguate the {} for {}",
2246 kind
.as_def_kind().descr(def_id
),
2247 if let Some(candidate
) = candidate
{
2248 format
!("candidate #{}", candidate
)
2250 "the candidate".to_string()