]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
dafc424f1b4c45a27da3fb0cd95fd28c202169f7
[rust.git] / compiler / rustc_trait_selection / src / traits / error_reporting / suggestions.rs
1 // ignore-tidy-filelength
2 use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
3
4 use crate::autoderef::Autoderef;
5 use crate::infer::InferCtxt;
6 use crate::traits::{NormalizeExt, ObligationCtxt};
7
8 use hir::def::CtorOf;
9 use hir::HirId;
10 use rustc_data_structures::fx::FxHashSet;
11 use rustc_data_structures::stack::ensure_sufficient_stack;
12 use rustc_errors::{
13     error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
14     ErrorGuaranteed, MultiSpan, Style,
15 };
16 use rustc_hir as hir;
17 use rustc_hir::def::DefKind;
18 use rustc_hir::def_id::DefId;
19 use rustc_hir::intravisit::Visitor;
20 use rustc_hir::lang_items::LangItem;
21 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
22 use rustc_infer::infer::error_reporting::TypeErrCtxt;
23 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
24 use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
25 use rustc_middle::hir::map;
26 use rustc_middle::ty::error::TypeError::{self, Sorts};
27 use rustc_middle::ty::relate::TypeRelation;
28 use rustc_middle::ty::{
29     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
30     GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
31     IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
32     TypeSuperFoldable, TypeVisitable, TypeckResults,
33 };
34 use rustc_span::symbol::{sym, Ident, Symbol};
35 use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
36 use rustc_target::spec::abi;
37 use std::ops::Deref;
38
39 use super::method_chain::CollectAllMismatches;
40 use super::InferCtxtPrivExt;
41 use crate::infer::InferCtxtExt as _;
42 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
43 use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
44
45 #[derive(Debug)]
46 pub enum GeneratorInteriorOrUpvar {
47     // span of interior type
48     Interior(Span, Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>),
49     // span of upvar
50     Upvar(Span),
51 }
52
53 // This type provides a uniform interface to retrieve data on generators, whether it originated from
54 // the local crate being compiled or from a foreign crate.
55 #[derive(Debug)]
56 pub enum GeneratorData<'tcx, 'a> {
57     Local(&'a TypeckResults<'tcx>),
58     Foreign(&'tcx GeneratorDiagnosticData<'tcx>),
59 }
60
61 impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
62     // Try to get information about variables captured by the generator that matches a type we are
63     // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
64     // meet an obligation
65     fn try_get_upvar_span<F>(
66         &self,
67         infer_context: &InferCtxt<'tcx>,
68         generator_did: DefId,
69         ty_matches: F,
70     ) -> Option<GeneratorInteriorOrUpvar>
71     where
72         F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
73     {
74         match self {
75             GeneratorData::Local(typeck_results) => {
76                 infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
77                     upvars.iter().find_map(|(upvar_id, upvar)| {
78                         let upvar_ty = typeck_results.node_type(*upvar_id);
79                         let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
80                         if ty_matches(ty::Binder::dummy(upvar_ty)) {
81                             Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
82                         } else {
83                             None
84                         }
85                     })
86                 })
87             }
88             GeneratorData::Foreign(_) => None,
89         }
90     }
91
92     // Try to get the span of a type being awaited on that matches the type we are looking with the
93     // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
94     // obligation
95     fn get_from_await_ty<F>(
96         &self,
97         visitor: AwaitsVisitor,
98         hir: map::Map<'tcx>,
99         ty_matches: F,
100     ) -> Option<Span>
101     where
102         F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
103     {
104         match self {
105             GeneratorData::Local(typeck_results) => visitor
106                 .awaits
107                 .into_iter()
108                 .map(|id| hir.expect_expr(id))
109                 .find(|await_expr| {
110                     ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
111                 })
112                 .map(|expr| expr.span),
113             GeneratorData::Foreign(generator_diagnostic_data) => visitor
114                 .awaits
115                 .into_iter()
116                 .map(|id| hir.expect_expr(id))
117                 .find(|await_expr| {
118                     ty_matches(ty::Binder::dummy(
119                         generator_diagnostic_data
120                             .adjustments
121                             .get(&await_expr.hir_id.local_id)
122                             .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..])
123                             .last()
124                             .map_or_else::<Ty<'tcx>, _, _>(
125                                 || {
126                                     generator_diagnostic_data
127                                         .nodes_types
128                                         .get(&await_expr.hir_id.local_id)
129                                         .cloned()
130                                         .unwrap_or_else(|| {
131                                             bug!(
132                                                 "node_type: no type for node `{}`",
133                                                 ty::tls::with(|tcx| tcx
134                                                     .hir()
135                                                     .node_to_string(await_expr.hir_id))
136                                             )
137                                         })
138                                 },
139                                 |adj| adj.target,
140                             ),
141                     ))
142                 })
143                 .map(|expr| expr.span),
144         }
145     }
146
147     /// Get the type, expression, span and optional scope span of all types
148     /// that are live across the yield of this generator
149     fn get_generator_interior_types(
150         &self,
151     ) -> ty::Binder<'tcx, &[GeneratorInteriorTypeCause<'tcx>]> {
152         match self {
153             GeneratorData::Local(typeck_result) => {
154                 typeck_result.generator_interior_types.as_deref()
155             }
156             GeneratorData::Foreign(generator_diagnostic_data) => {
157                 generator_diagnostic_data.generator_interior_types.as_deref()
158             }
159         }
160     }
161
162     // Used to get the source of the data, note we don't have as much information for generators
163     // originated from foreign crates
164     fn is_foreign(&self) -> bool {
165         match self {
166             GeneratorData::Local(_) => false,
167             GeneratorData::Foreign(_) => true,
168         }
169     }
170 }
171
172 // This trait is public to expose the diagnostics methods to clippy.
173 pub trait TypeErrCtxtExt<'tcx> {
174     fn suggest_restricting_param_bound(
175         &self,
176         err: &mut Diagnostic,
177         trait_pred: ty::PolyTraitPredicate<'tcx>,
178         associated_item: Option<(&'static str, Ty<'tcx>)>,
179         body_id: hir::HirId,
180     );
181
182     fn suggest_dereferences(
183         &self,
184         obligation: &PredicateObligation<'tcx>,
185         err: &mut Diagnostic,
186         trait_pred: ty::PolyTraitPredicate<'tcx>,
187     ) -> bool;
188
189     fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol>;
190
191     fn suggest_fn_call(
192         &self,
193         obligation: &PredicateObligation<'tcx>,
194         err: &mut Diagnostic,
195         trait_pred: ty::PolyTraitPredicate<'tcx>,
196     ) -> bool;
197
198     fn suggest_add_reference_to_arg(
199         &self,
200         obligation: &PredicateObligation<'tcx>,
201         err: &mut Diagnostic,
202         trait_pred: ty::PolyTraitPredicate<'tcx>,
203         has_custom_message: bool,
204     ) -> bool;
205
206     fn suggest_borrowing_for_object_cast(
207         &self,
208         err: &mut Diagnostic,
209         obligation: &PredicateObligation<'tcx>,
210         self_ty: Ty<'tcx>,
211         object_ty: Ty<'tcx>,
212     );
213
214     fn suggest_remove_reference(
215         &self,
216         obligation: &PredicateObligation<'tcx>,
217         err: &mut Diagnostic,
218         trait_pred: ty::PolyTraitPredicate<'tcx>,
219     ) -> bool;
220
221     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic);
222
223     fn suggest_change_mut(
224         &self,
225         obligation: &PredicateObligation<'tcx>,
226         err: &mut Diagnostic,
227         trait_pred: ty::PolyTraitPredicate<'tcx>,
228     );
229
230     fn suggest_semicolon_removal(
231         &self,
232         obligation: &PredicateObligation<'tcx>,
233         err: &mut Diagnostic,
234         span: Span,
235         trait_pred: ty::PolyTraitPredicate<'tcx>,
236     ) -> bool;
237
238     fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
239
240     fn suggest_impl_trait(
241         &self,
242         err: &mut Diagnostic,
243         span: Span,
244         obligation: &PredicateObligation<'tcx>,
245         trait_pred: ty::PolyTraitPredicate<'tcx>,
246     ) -> bool;
247
248     fn point_at_returns_when_relevant(
249         &self,
250         err: &mut Diagnostic,
251         obligation: &PredicateObligation<'tcx>,
252     );
253
254     fn report_closure_arg_mismatch(
255         &self,
256         span: Span,
257         found_span: Option<Span>,
258         found: ty::PolyTraitRef<'tcx>,
259         expected: ty::PolyTraitRef<'tcx>,
260         cause: &ObligationCauseCode<'tcx>,
261         found_node: Option<Node<'_>>,
262     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
263
264     fn note_conflicting_closure_bounds(
265         &self,
266         cause: &ObligationCauseCode<'tcx>,
267         err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
268     );
269
270     fn suggest_fully_qualified_path(
271         &self,
272         err: &mut Diagnostic,
273         item_def_id: DefId,
274         span: Span,
275         trait_ref: DefId,
276     );
277
278     fn maybe_note_obligation_cause_for_async_await(
279         &self,
280         err: &mut Diagnostic,
281         obligation: &PredicateObligation<'tcx>,
282     ) -> bool;
283
284     fn note_obligation_cause_for_async_await(
285         &self,
286         err: &mut Diagnostic,
287         interior_or_upvar_span: GeneratorInteriorOrUpvar,
288         is_async: bool,
289         outer_generator: Option<DefId>,
290         trait_pred: ty::TraitPredicate<'tcx>,
291         target_ty: Ty<'tcx>,
292         typeck_results: Option<&ty::TypeckResults<'tcx>>,
293         obligation: &PredicateObligation<'tcx>,
294         next_code: Option<&ObligationCauseCode<'tcx>>,
295     );
296
297     fn note_obligation_cause_code<T>(
298         &self,
299         err: &mut Diagnostic,
300         predicate: T,
301         param_env: ty::ParamEnv<'tcx>,
302         cause_code: &ObligationCauseCode<'tcx>,
303         obligated_types: &mut Vec<Ty<'tcx>>,
304         seen_requirements: &mut FxHashSet<DefId>,
305     ) where
306         T: ToPredicate<'tcx>;
307
308     /// Suggest to await before try: future? => future.await?
309     fn suggest_await_before_try(
310         &self,
311         err: &mut Diagnostic,
312         obligation: &PredicateObligation<'tcx>,
313         trait_pred: ty::PolyTraitPredicate<'tcx>,
314         span: Span,
315     );
316
317     fn suggest_floating_point_literal(
318         &self,
319         obligation: &PredicateObligation<'tcx>,
320         err: &mut Diagnostic,
321         trait_ref: &ty::PolyTraitRef<'tcx>,
322     );
323
324     fn suggest_derive(
325         &self,
326         obligation: &PredicateObligation<'tcx>,
327         err: &mut Diagnostic,
328         trait_pred: ty::PolyTraitPredicate<'tcx>,
329     );
330
331     fn suggest_dereferencing_index(
332         &self,
333         obligation: &PredicateObligation<'tcx>,
334         err: &mut Diagnostic,
335         trait_pred: ty::PolyTraitPredicate<'tcx>,
336     );
337     fn function_argument_obligation(
338         &self,
339         arg_hir_id: HirId,
340         err: &mut Diagnostic,
341         parent_code: &ObligationCauseCode<'tcx>,
342         param_env: ty::ParamEnv<'tcx>,
343         predicate: ty::Predicate<'tcx>,
344         call_hir_id: HirId,
345     );
346     fn point_at_chain(
347         &self,
348         expr: &hir::Expr<'_>,
349         typeck_results: &TypeckResults<'tcx>,
350         type_diffs: Vec<TypeError<'tcx>>,
351         param_env: ty::ParamEnv<'tcx>,
352         err: &mut Diagnostic,
353     );
354 }
355
356 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
357     (
358         generics.tail_span_for_predicate_suggestion(),
359         format!("{} {}", generics.add_where_or_trailing_comma(), pred),
360     )
361 }
362
363 /// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but
364 /// it can also be an `impl Trait` param that needs to be decomposed to a type
365 /// param for cleaner code.
366 fn suggest_restriction<'tcx>(
367     tcx: TyCtxt<'tcx>,
368     hir_id: HirId,
369     hir_generics: &hir::Generics<'tcx>,
370     msg: &str,
371     err: &mut Diagnostic,
372     fn_sig: Option<&hir::FnSig<'_>>,
373     projection: Option<&ty::ProjectionTy<'_>>,
374     trait_pred: ty::PolyTraitPredicate<'tcx>,
375     // When we are dealing with a trait, `super_traits` will be `Some`:
376     // Given `trait T: A + B + C {}`
377     //              -  ^^^^^^^^^ GenericBounds
378     //              |
379     //              &Ident
380     super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
381 ) {
382     if hir_generics.where_clause_span.from_expansion()
383         || hir_generics.where_clause_span.desugaring_kind().is_some()
384     {
385         return;
386     }
387     let Some(item_id) = hir_id.as_owner() else { return; };
388     let generics = tcx.generics_of(item_id);
389     // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
390     if let Some((param, bound_str, fn_sig)) =
391         fn_sig.zip(projection).and_then(|(sig, p)| match p.self_ty().kind() {
392             // Shenanigans to get the `Trait` from the `impl Trait`.
393             ty::Param(param) => {
394                 let param_def = generics.type_param(param, tcx);
395                 if param_def.kind.is_synthetic() {
396                     let bound_str =
397                         param_def.name.as_str().strip_prefix("impl ")?.trim_start().to_string();
398                     return Some((param_def, bound_str, sig));
399                 }
400                 None
401             }
402             _ => None,
403         })
404     {
405         let type_param_name = hir_generics.params.next_type_param_name(Some(&bound_str));
406         let trait_pred = trait_pred.fold_with(&mut ReplaceImplTraitFolder {
407             tcx,
408             param,
409             replace_ty: ty::ParamTy::new(generics.count() as u32, Symbol::intern(&type_param_name))
410                 .to_ty(tcx),
411         });
412         if !trait_pred.is_suggestable(tcx, false) {
413             return;
414         }
415         // We know we have an `impl Trait` that doesn't satisfy a required projection.
416
417         // Find all of the occurrences of `impl Trait` for `Trait` in the function arguments'
418         // types. There should be at least one, but there might be *more* than one. In that
419         // case we could just ignore it and try to identify which one needs the restriction,
420         // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
421         // where `T: Trait`.
422         let mut ty_spans = vec![];
423         for input in fn_sig.decl.inputs {
424             ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id }
425                 .visit_ty(input);
426         }
427         // The type param `T: Trait` we will suggest to introduce.
428         let type_param = format!("{}: {}", type_param_name, bound_str);
429
430         let mut sugg = vec![
431             if let Some(span) = hir_generics.span_for_param_suggestion() {
432                 (span, format!(", {}", type_param))
433             } else {
434                 (hir_generics.span, format!("<{}>", type_param))
435             },
436             // `fn foo(t: impl Trait)`
437             //                       ^ suggest `where <T as Trait>::A: Bound`
438             predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
439         ];
440         sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
441
442         // Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
443         // FIXME: once `#![feature(associated_type_bounds)]` is stabilized, we should suggest
444         // `fn foo(t: impl Trait<A: Bound>)` instead.
445         err.multipart_suggestion(
446             "introduce a type parameter with a trait bound instead of using `impl Trait`",
447             sugg,
448             Applicability::MaybeIncorrect,
449         );
450     } else {
451         if !trait_pred.is_suggestable(tcx, false) {
452             return;
453         }
454         // Trivial case: `T` needs an extra bound: `T: Bound`.
455         let (sp, suggestion) = match (
456             hir_generics
457                 .params
458                 .iter()
459                 .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
460             super_traits,
461         ) {
462             (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
463             (None, Some((ident, []))) => (
464                 ident.span.shrink_to_hi(),
465                 format!(": {}", trait_pred.print_modifiers_and_trait_path()),
466             ),
467             (_, Some((_, [.., bounds]))) => (
468                 bounds.span().shrink_to_hi(),
469                 format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
470             ),
471             (Some(_), Some((_, []))) => (
472                 hir_generics.span.shrink_to_hi(),
473                 format!(": {}", trait_pred.print_modifiers_and_trait_path()),
474             ),
475         };
476
477         err.span_suggestion_verbose(
478             sp,
479             &format!("consider further restricting {}", msg),
480             suggestion,
481             Applicability::MachineApplicable,
482         );
483     }
484 }
485
486 impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
487     fn suggest_restricting_param_bound(
488         &self,
489         mut err: &mut Diagnostic,
490         trait_pred: ty::PolyTraitPredicate<'tcx>,
491         associated_ty: Option<(&'static str, Ty<'tcx>)>,
492         body_id: hir::HirId,
493     ) {
494         let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
495
496         let self_ty = trait_pred.skip_binder().self_ty();
497         let (param_ty, projection) = match self_ty.kind() {
498             ty::Param(_) => (true, None),
499             ty::Projection(projection) => (false, Some(projection)),
500             _ => (false, None),
501         };
502
503         // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
504         //        don't suggest `T: Sized + ?Sized`.
505         let mut hir_id = body_id;
506         while let Some(node) = self.tcx.hir().find(hir_id) {
507             match node {
508                 hir::Node::Item(hir::Item {
509                     ident,
510                     kind: hir::ItemKind::Trait(_, _, generics, bounds, _),
511                     ..
512                 }) if self_ty == self.tcx.types.self_param => {
513                     assert!(param_ty);
514                     // Restricting `Self` for a single method.
515                     suggest_restriction(
516                         self.tcx,
517                         hir_id,
518                         &generics,
519                         "`Self`",
520                         err,
521                         None,
522                         projection,
523                         trait_pred,
524                         Some((ident, bounds)),
525                     );
526                     return;
527                 }
528
529                 hir::Node::TraitItem(hir::TraitItem {
530                     generics,
531                     kind: hir::TraitItemKind::Fn(..),
532                     ..
533                 }) if self_ty == self.tcx.types.self_param => {
534                     assert!(param_ty);
535                     // Restricting `Self` for a single method.
536                     suggest_restriction(
537                         self.tcx, hir_id, &generics, "`Self`", err, None, projection, trait_pred,
538                         None,
539                     );
540                     return;
541                 }
542
543                 hir::Node::TraitItem(hir::TraitItem {
544                     generics,
545                     kind: hir::TraitItemKind::Fn(fn_sig, ..),
546                     ..
547                 })
548                 | hir::Node::ImplItem(hir::ImplItem {
549                     generics,
550                     kind: hir::ImplItemKind::Fn(fn_sig, ..),
551                     ..
552                 })
553                 | hir::Node::Item(hir::Item {
554                     kind: hir::ItemKind::Fn(fn_sig, generics, _), ..
555                 }) if projection.is_some() => {
556                     // Missing restriction on associated type of type parameter (unmet projection).
557                     suggest_restriction(
558                         self.tcx,
559                         hir_id,
560                         &generics,
561                         "the associated type",
562                         err,
563                         Some(fn_sig),
564                         projection,
565                         trait_pred,
566                         None,
567                     );
568                     return;
569                 }
570                 hir::Node::Item(hir::Item {
571                     kind:
572                         hir::ItemKind::Trait(_, _, generics, ..)
573                         | hir::ItemKind::Impl(hir::Impl { generics, .. }),
574                     ..
575                 }) if projection.is_some() => {
576                     // Missing restriction on associated type of type parameter (unmet projection).
577                     suggest_restriction(
578                         self.tcx,
579                         hir_id,
580                         &generics,
581                         "the associated type",
582                         err,
583                         None,
584                         projection,
585                         trait_pred,
586                         None,
587                     );
588                     return;
589                 }
590
591                 hir::Node::Item(hir::Item {
592                     kind:
593                         hir::ItemKind::Struct(_, generics)
594                         | hir::ItemKind::Enum(_, generics)
595                         | hir::ItemKind::Union(_, generics)
596                         | hir::ItemKind::Trait(_, _, generics, ..)
597                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
598                         | hir::ItemKind::Fn(_, generics, _)
599                         | hir::ItemKind::TyAlias(_, generics)
600                         | hir::ItemKind::TraitAlias(generics, _)
601                         | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
602                     ..
603                 })
604                 | hir::Node::TraitItem(hir::TraitItem { generics, .. })
605                 | hir::Node::ImplItem(hir::ImplItem { generics, .. })
606                     if param_ty =>
607                 {
608                     // We skip the 0'th subst (self) because we do not want
609                     // to consider the predicate as not suggestible if the
610                     // self type is an arg position `impl Trait` -- instead,
611                     // we handle that by adding ` + Bound` below.
612                     // FIXME(compiler-errors): It would be nice to do the same
613                     // this that we do in `suggest_restriction` and pull the
614                     // `impl Trait` into a new generic if it shows up somewhere
615                     // else in the predicate.
616                     if !trait_pred.skip_binder().trait_ref.substs[1..]
617                         .iter()
618                         .all(|g| g.is_suggestable(self.tcx, false))
619                     {
620                         return;
621                     }
622                     // Missing generic type parameter bound.
623                     let param_name = self_ty.to_string();
624                     let mut constraint = with_no_trimmed_paths!(
625                         trait_pred.print_modifiers_and_trait_path().to_string()
626                     );
627
628                     if let Some((name, term)) = associated_ty {
629                         // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
630                         // That should be extracted into a helper function.
631                         if constraint.ends_with('>') {
632                             constraint = format!(
633                                 "{}, {} = {}>",
634                                 &constraint[..constraint.len() - 1],
635                                 name,
636                                 term
637                             );
638                         } else {
639                             constraint.push_str(&format!("<{} = {}>", name, term));
640                         }
641                     }
642
643                     if suggest_constraining_type_param(
644                         self.tcx,
645                         generics,
646                         &mut err,
647                         &param_name,
648                         &constraint,
649                         Some(trait_pred.def_id()),
650                     ) {
651                         return;
652                     }
653                 }
654
655                 hir::Node::Item(hir::Item {
656                     kind:
657                         hir::ItemKind::Struct(_, generics)
658                         | hir::ItemKind::Enum(_, generics)
659                         | hir::ItemKind::Union(_, generics)
660                         | hir::ItemKind::Trait(_, _, generics, ..)
661                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
662                         | hir::ItemKind::Fn(_, generics, _)
663                         | hir::ItemKind::TyAlias(_, generics)
664                         | hir::ItemKind::TraitAlias(generics, _)
665                         | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
666                     ..
667                 }) if !param_ty => {
668                     // Missing generic type parameter bound.
669                     if suggest_arbitrary_trait_bound(
670                         self.tcx,
671                         generics,
672                         &mut err,
673                         trait_pred,
674                         associated_ty,
675                     ) {
676                         return;
677                     }
678                 }
679                 hir::Node::Crate(..) => return,
680
681                 _ => {}
682             }
683
684             hir_id = self.tcx.hir().get_parent_item(hir_id).into();
685         }
686     }
687
688     /// When after several dereferencing, the reference satisfies the trait
689     /// binding. This function provides dereference suggestion for this
690     /// specific situation.
691     fn suggest_dereferences(
692         &self,
693         obligation: &PredicateObligation<'tcx>,
694         err: &mut Diagnostic,
695         trait_pred: ty::PolyTraitPredicate<'tcx>,
696     ) -> bool {
697         // It only make sense when suggesting dereferences for arguments
698         let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
699             else { return false; };
700         let Some(typeck_results) = &self.typeck_results
701             else { return false; };
702         let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
703             else { return false; };
704         let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
705             else { return false; };
706
707         let span = obligation.cause.span;
708         let mut real_trait_pred = trait_pred;
709         let mut code = obligation.cause.code();
710         while let Some((parent_code, parent_trait_pred)) = code.parent() {
711             code = parent_code;
712             if let Some(parent_trait_pred) = parent_trait_pred {
713                 real_trait_pred = parent_trait_pred;
714             }
715
716             let real_ty = real_trait_pred.self_ty();
717             // We `erase_late_bound_regions` here because `make_subregion` does not handle
718             // `ReLateBound`, and we don't particularly care about the regions.
719             if self
720                 .can_eq(obligation.param_env, self.tcx.erase_late_bound_regions(real_ty), arg_ty)
721                 .is_err()
722             {
723                 continue;
724             }
725
726             if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
727                 let mut autoderef = Autoderef::new(
728                     self,
729                     obligation.param_env,
730                     obligation.cause.body_id,
731                     span,
732                     base_ty,
733                 );
734                 if let Some(steps) = autoderef.find_map(|(ty, steps)| {
735                     // Re-add the `&`
736                     let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
737
738                     // Remapping bound vars here
739                     let real_trait_pred_and_ty =
740                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
741                     let obligation = self.mk_trait_obligation_with_new_self_ty(
742                         obligation.param_env,
743                         real_trait_pred_and_ty,
744                     );
745                     Some(steps).filter(|_| self.predicate_may_hold(&obligation))
746                 }) {
747                     if steps > 0 {
748                         // Don't care about `&mut` because `DerefMut` is used less
749                         // often and user will not expect autoderef happens.
750                         if let Some(hir::Node::Expr(hir::Expr {
751                             kind:
752                                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),
753                             ..
754                         })) = self.tcx.hir().find(*arg_hir_id)
755                         {
756                             let derefs = "*".repeat(steps);
757                             err.span_suggestion_verbose(
758                                 expr.span.shrink_to_lo(),
759                                 "consider dereferencing here",
760                                 derefs,
761                                 Applicability::MachineApplicable,
762                             );
763                             return true;
764                         }
765                     }
766                 } else if real_trait_pred != trait_pred {
767                     // This branch addresses #87437.
768
769                     // Remapping bound vars here
770                     let real_trait_pred_and_base_ty =
771                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, base_ty));
772                     let obligation = self.mk_trait_obligation_with_new_self_ty(
773                         obligation.param_env,
774                         real_trait_pred_and_base_ty,
775                     );
776                     if self.predicate_may_hold(&obligation) {
777                         err.span_suggestion_verbose(
778                             span.shrink_to_lo(),
779                             "consider dereferencing here",
780                             "*",
781                             Applicability::MachineApplicable,
782                         );
783                         return true;
784                     }
785                 }
786             }
787         }
788         false
789     }
790
791     /// Given a closure's `DefId`, return the given name of the closure.
792     ///
793     /// This doesn't account for reassignments, but it's only used for suggestions.
794     fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol> {
795         let get_name = |err: &mut Diagnostic, kind: &hir::PatKind<'_>| -> Option<Symbol> {
796             // Get the local name of this closure. This can be inaccurate because
797             // of the possibility of reassignment, but this should be good enough.
798             match &kind {
799                 hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, ident, None) => {
800                     Some(ident.name)
801                 }
802                 _ => {
803                     err.note(msg);
804                     None
805                 }
806             }
807         };
808
809         let hir = self.tcx.hir();
810         let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?);
811         let parent_node = hir.get_parent_node(hir_id);
812         match hir.find(parent_node) {
813             Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
814                 get_name(err, &local.pat.kind)
815             }
816             // Different to previous arm because one is `&hir::Local` and the other
817             // is `P<hir::Local>`.
818             Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
819             _ => None,
820         }
821     }
822
823     /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
824     /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
825     /// it: `bar(foo)` â†’ `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
826     fn suggest_fn_call(
827         &self,
828         obligation: &PredicateObligation<'tcx>,
829         err: &mut Diagnostic,
830         trait_pred: ty::PolyTraitPredicate<'tcx>,
831     ) -> bool {
832         if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = obligation.predicate.kind().skip_binder()
833             && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait()
834         {
835             // Don't suggest calling to turn an unsized type into a sized type
836             return false;
837         }
838
839         // This is duplicated from `extract_callable_info` in typeck, which
840         // relies on autoderef, so we can't use it here.
841         let found = trait_pred.self_ty().skip_binder().peel_refs();
842         let Some((def_id_or_name, output, inputs)) = (match *found.kind()
843         {
844             ty::FnPtr(fn_sig) => {
845                 Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs()))
846             }
847             ty::FnDef(def_id, _) => {
848                 let fn_sig = found.fn_sig(self.tcx);
849                 Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
850             }
851             ty::Closure(def_id, substs) => {
852                 let fn_sig = substs.as_closure().sig();
853                 Some((
854                     DefIdOrName::DefId(def_id),
855                     fn_sig.output(),
856                     fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
857                 ))
858             }
859             ty::Opaque(def_id, substs) => {
860                 self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
861                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
862                     && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
863                     // args tuple will always be substs[1]
864                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
865                     {
866                         Some((
867                             DefIdOrName::DefId(def_id),
868                             pred.kind().rebind(proj.term.ty().unwrap()),
869                             pred.kind().rebind(args.as_slice()),
870                         ))
871                     } else {
872                         None
873                     }
874                 })
875             }
876             ty::Dynamic(data, _, ty::Dyn) => {
877                 data.iter().find_map(|pred| {
878                     if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
879                     && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
880                     // for existential projection, substs are shifted over by 1
881                     && let ty::Tuple(args) = proj.substs.type_at(0).kind()
882                     {
883                         Some((
884                             DefIdOrName::Name("trait object"),
885                             pred.rebind(proj.term.ty().unwrap()),
886                             pred.rebind(args.as_slice()),
887                         ))
888                     } else {
889                         None
890                     }
891                 })
892             }
893             ty::Param(_) => {
894                 obligation.param_env.caller_bounds().iter().find_map(|pred| {
895                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
896                     && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
897                     && proj.projection_ty.self_ty() == found
898                     // args tuple will always be substs[1]
899                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
900                     {
901                         Some((
902                             DefIdOrName::Name("type parameter"),
903                             pred.kind().rebind(proj.term.ty().unwrap()),
904                             pred.kind().rebind(args.as_slice()),
905                         ))
906                     } else {
907                         None
908                     }
909                 })
910             }
911             _ => None,
912         }) else { return false; };
913         let output = self.replace_bound_vars_with_fresh_vars(
914             obligation.cause.span,
915             LateBoundRegionConversionTime::FnCall,
916             output,
917         );
918         let inputs = inputs.skip_binder().iter().map(|ty| {
919             self.replace_bound_vars_with_fresh_vars(
920                 obligation.cause.span,
921                 LateBoundRegionConversionTime::FnCall,
922                 inputs.rebind(*ty),
923             )
924         });
925
926         // Remapping bound vars here
927         let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
928
929         let new_obligation =
930             self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
931         if !self.predicate_must_hold_modulo_regions(&new_obligation) {
932             return false;
933         }
934
935         // Get the name of the callable and the arguments to be used in the suggestion.
936         let hir = self.tcx.hir();
937
938         let msg = match def_id_or_name {
939             DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
940                 DefKind::Ctor(CtorOf::Struct, _) => {
941                     "use parentheses to construct this tuple struct".to_string()
942                 }
943                 DefKind::Ctor(CtorOf::Variant, _) => {
944                     "use parentheses to construct this tuple variant".to_string()
945                 }
946                 kind => format!("use parentheses to call this {}", kind.descr(def_id)),
947             },
948             DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
949         };
950
951         let args = inputs
952             .map(|ty| {
953                 if ty.is_suggestable(self.tcx, false) {
954                     format!("/* {ty} */")
955                 } else {
956                     "/* value */".to_string()
957                 }
958             })
959             .collect::<Vec<_>>()
960             .join(", ");
961
962         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
963             && obligation.cause.span.can_be_used_for_suggestions()
964         {
965             // When the obligation error has been ensured to have been caused by
966             // an argument, the `obligation.cause.span` points at the expression
967             // of the argument, so we can provide a suggestion. Otherwise, we give
968             // a more general note.
969             err.span_suggestion_verbose(
970                 obligation.cause.span.shrink_to_hi(),
971                 &msg,
972                 format!("({args})"),
973                 Applicability::HasPlaceholders,
974             );
975         } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
976             let name = match hir.get_if_local(def_id) {
977                 Some(hir::Node::Expr(hir::Expr {
978                     kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
979                     ..
980                 })) => {
981                     err.span_label(*fn_decl_span, "consider calling this closure");
982                     let Some(name) = self.get_closure_name(def_id, err, &msg) else {
983                         return false;
984                     };
985                     name.to_string()
986                 }
987                 Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => {
988                     err.span_label(ident.span, "consider calling this function");
989                     ident.to_string()
990                 }
991                 Some(hir::Node::Ctor(..)) => {
992                     let name = self.tcx.def_path_str(def_id);
993                     err.span_label(
994                         self.tcx.def_span(def_id),
995                         format!("consider calling the constructor for `{}`", name),
996                     );
997                     name
998                 }
999                 _ => return false,
1000             };
1001             err.help(&format!("{msg}: `{name}({args})`"));
1002         }
1003         true
1004     }
1005
1006     fn suggest_add_reference_to_arg(
1007         &self,
1008         obligation: &PredicateObligation<'tcx>,
1009         err: &mut Diagnostic,
1010         poly_trait_pred: ty::PolyTraitPredicate<'tcx>,
1011         has_custom_message: bool,
1012     ) -> bool {
1013         let span = obligation.cause.span;
1014
1015         let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
1016             obligation.cause.code()
1017         {
1018             &parent_code
1019         } else if let ObligationCauseCode::ItemObligation(_)
1020         | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
1021         {
1022             obligation.cause.code()
1023         } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
1024             span.ctxt().outer_expn_data().kind
1025         {
1026             obligation.cause.code()
1027         } else {
1028             return false;
1029         };
1030
1031         // List of traits for which it would be nonsensical to suggest borrowing.
1032         // For instance, immutable references are always Copy, so suggesting to
1033         // borrow would always succeed, but it's probably not what the user wanted.
1034         let mut never_suggest_borrow: Vec<_> =
1035             [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
1036                 .iter()
1037                 .filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
1038                 .collect();
1039
1040         if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
1041             never_suggest_borrow.push(def_id);
1042         }
1043
1044         let param_env = obligation.param_env;
1045
1046         // Try to apply the original trait binding obligation by borrowing.
1047         let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
1048                                  blacklist: &[DefId]|
1049          -> bool {
1050             if blacklist.contains(&old_pred.def_id()) {
1051                 return false;
1052             }
1053             // We map bounds to `&T` and `&mut T`
1054             let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
1055                 (
1056                     trait_pred,
1057                     self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1058                 )
1059             });
1060             let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
1061                 (
1062                     trait_pred,
1063                     self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1064                 )
1065             });
1066
1067             let mk_result = |trait_pred_and_new_ty| {
1068                 let obligation =
1069                     self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
1070                 self.predicate_must_hold_modulo_regions(&obligation)
1071             };
1072             let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1073             let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1074
1075             let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
1076                 if let ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
1077                     && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
1078                 {
1079                     (
1080                         mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
1081                         mutability.is_mut(),
1082                     )
1083                 } else {
1084                     (false, false)
1085                 };
1086
1087             if imm_ref_self_ty_satisfies_pred
1088                 || mut_ref_self_ty_satisfies_pred
1089                 || ref_inner_ty_satisfies_pred
1090             {
1091                 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1092                     // We don't want a borrowing suggestion on the fields in structs,
1093                     // ```
1094                     // struct Foo {
1095                     //  the_foos: Vec<Foo>
1096                     // }
1097                     // ```
1098                     if !matches!(
1099                         span.ctxt().outer_expn_data().kind,
1100                         ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
1101                     ) {
1102                         return false;
1103                     }
1104                     if snippet.starts_with('&') {
1105                         // This is already a literal borrow and the obligation is failing
1106                         // somewhere else in the obligation chain. Do not suggest non-sense.
1107                         return false;
1108                     }
1109                     // We have a very specific type of error, where just borrowing this argument
1110                     // might solve the problem. In cases like this, the important part is the
1111                     // original type obligation, not the last one that failed, which is arbitrary.
1112                     // Because of this, we modify the error to refer to the original obligation and
1113                     // return early in the caller.
1114
1115                     let msg = format!("the trait bound `{}` is not satisfied", old_pred);
1116                     if has_custom_message {
1117                         err.note(&msg);
1118                     } else {
1119                         err.message =
1120                             vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
1121                     }
1122                     err.span_label(
1123                         span,
1124                         format!(
1125                             "the trait `{}` is not implemented for `{}`",
1126                             old_pred.print_modifiers_and_trait_path(),
1127                             old_pred.self_ty().skip_binder(),
1128                         ),
1129                     );
1130
1131                     if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
1132                         err.span_suggestions(
1133                             span.shrink_to_lo(),
1134                             "consider borrowing here",
1135                             ["&".to_string(), "&mut ".to_string()],
1136                             Applicability::MaybeIncorrect,
1137                         );
1138                     } else {
1139                         let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
1140                         err.span_suggestion_verbose(
1141                             span.shrink_to_lo(),
1142                             &format!(
1143                                 "consider{} borrowing here",
1144                                 if is_mut { " mutably" } else { "" }
1145                             ),
1146                             format!("&{}", if is_mut { "mut " } else { "" }),
1147                             Applicability::MaybeIncorrect,
1148                         );
1149                     }
1150                     return true;
1151                 }
1152             }
1153             return false;
1154         };
1155
1156         if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
1157             try_borrowing(cause.derived.parent_trait_pred, &[])
1158         } else if let ObligationCauseCode::BindingObligation(_, _)
1159         | ObligationCauseCode::ItemObligation(_)
1160         | ObligationCauseCode::ExprItemObligation(..)
1161         | ObligationCauseCode::ExprBindingObligation(..) = code
1162         {
1163             try_borrowing(poly_trait_pred, &never_suggest_borrow)
1164         } else {
1165             false
1166         }
1167     }
1168
1169     // Suggest borrowing the type
1170     fn suggest_borrowing_for_object_cast(
1171         &self,
1172         err: &mut Diagnostic,
1173         obligation: &PredicateObligation<'tcx>,
1174         self_ty: Ty<'tcx>,
1175         object_ty: Ty<'tcx>,
1176     ) {
1177         let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
1178         let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
1179
1180         for predicate in predicates.iter() {
1181             if !self.predicate_must_hold_modulo_regions(
1182                 &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
1183             ) {
1184                 return;
1185             }
1186         }
1187
1188         err.span_suggestion(
1189             obligation.cause.span.shrink_to_lo(),
1190             &format!(
1191                 "consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
1192             ),
1193             "&",
1194             Applicability::MaybeIncorrect,
1195         );
1196     }
1197
1198     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
1199     /// suggest removing these references until we reach a type that implements the trait.
1200     fn suggest_remove_reference(
1201         &self,
1202         obligation: &PredicateObligation<'tcx>,
1203         err: &mut Diagnostic,
1204         trait_pred: ty::PolyTraitPredicate<'tcx>,
1205     ) -> bool {
1206         let span = obligation.cause.span;
1207
1208         let mut suggested = false;
1209         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1210             let refs_number =
1211                 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
1212             if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
1213                 // Do not suggest removal of borrow from type arguments.
1214                 return false;
1215             }
1216
1217             // Skipping binder here, remapping below
1218             let mut suggested_ty = trait_pred.self_ty().skip_binder();
1219
1220             for refs_remaining in 0..refs_number {
1221                 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
1222                     break;
1223                 };
1224                 suggested_ty = *inner_ty;
1225
1226                 // Remapping bound vars here
1227                 let trait_pred_and_suggested_ty =
1228                     trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
1229
1230                 let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1231                     obligation.param_env,
1232                     trait_pred_and_suggested_ty,
1233                 );
1234
1235                 if self.predicate_may_hold(&new_obligation) {
1236                     let sp = self
1237                         .tcx
1238                         .sess
1239                         .source_map()
1240                         .span_take_while(span, |c| c.is_whitespace() || *c == '&');
1241
1242                     let remove_refs = refs_remaining + 1;
1243
1244                     let msg = if remove_refs == 1 {
1245                         "consider removing the leading `&`-reference".to_string()
1246                     } else {
1247                         format!("consider removing {} leading `&`-references", remove_refs)
1248                     };
1249
1250                     err.span_suggestion_short(sp, &msg, "", Applicability::MachineApplicable);
1251                     suggested = true;
1252                     break;
1253                 }
1254             }
1255         }
1256         suggested
1257     }
1258
1259     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
1260         let span = obligation.cause.span;
1261
1262         if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() {
1263             let hir = self.tcx.hir();
1264             if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
1265                 if let hir::Node::Expr(expr) = node {
1266                     // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
1267                     // and if not maybe suggest doing something else? If we kept the expression around we
1268                     // could also check if it is an fn call (very likely) and suggest changing *that*, if
1269                     // it is from the local crate.
1270                     err.span_suggestion(
1271                         span,
1272                         "remove the `.await`",
1273                         "",
1274                         Applicability::MachineApplicable,
1275                     );
1276                     // FIXME: account for associated `async fn`s.
1277                     if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
1278                         if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
1279                             obligation.predicate.kind().skip_binder()
1280                         {
1281                             err.span_label(
1282                                 *span,
1283                                 &format!("this call returns `{}`", pred.self_ty()),
1284                             );
1285                         }
1286                         if let Some(typeck_results) = &self.typeck_results
1287                             && let ty = typeck_results.expr_ty_adjusted(base)
1288                             && let ty::FnDef(def_id, _substs) = ty.kind()
1289                             && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
1290                                 hir.get_if_local(*def_id)
1291                         {
1292                             let msg = format!(
1293                                 "alternatively, consider making `fn {}` asynchronous",
1294                                 ident
1295                             );
1296                             if vis_span.is_empty() {
1297                                 err.span_suggestion_verbose(
1298                                     span.shrink_to_lo(),
1299                                     &msg,
1300                                     "async ",
1301                                     Applicability::MaybeIncorrect,
1302                                 );
1303                             } else {
1304                                 err.span_suggestion_verbose(
1305                                     vis_span.shrink_to_hi(),
1306                                     &msg,
1307                                     " async",
1308                                     Applicability::MaybeIncorrect,
1309                                 );
1310                             }
1311                         }
1312                     }
1313                 }
1314             }
1315         }
1316     }
1317
1318     /// Check if the trait bound is implemented for a different mutability and note it in the
1319     /// final error.
1320     fn suggest_change_mut(
1321         &self,
1322         obligation: &PredicateObligation<'tcx>,
1323         err: &mut Diagnostic,
1324         trait_pred: ty::PolyTraitPredicate<'tcx>,
1325     ) {
1326         let points_at_arg = matches!(
1327             obligation.cause.code(),
1328             ObligationCauseCode::FunctionArgumentObligation { .. },
1329         );
1330
1331         let span = obligation.cause.span;
1332         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1333             let refs_number =
1334                 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
1335             if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
1336                 // Do not suggest removal of borrow from type arguments.
1337                 return;
1338             }
1339             let trait_pred = self.resolve_vars_if_possible(trait_pred);
1340             if trait_pred.has_non_region_infer() {
1341                 // Do not ICE while trying to find if a reborrow would succeed on a trait with
1342                 // unresolved bindings.
1343                 return;
1344             }
1345
1346             // Skipping binder here, remapping below
1347             if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind()
1348             {
1349                 let suggested_ty = match mutability {
1350                     hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
1351                     hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
1352                 };
1353
1354                 // Remapping bound vars here
1355                 let trait_pred_and_suggested_ty =
1356                     trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
1357
1358                 let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1359                     obligation.param_env,
1360                     trait_pred_and_suggested_ty,
1361                 );
1362                 let suggested_ty_would_satisfy_obligation = self
1363                     .evaluate_obligation_no_overflow(&new_obligation)
1364                     .must_apply_modulo_regions();
1365                 if suggested_ty_would_satisfy_obligation {
1366                     let sp = self
1367                         .tcx
1368                         .sess
1369                         .source_map()
1370                         .span_take_while(span, |c| c.is_whitespace() || *c == '&');
1371                     if points_at_arg && mutability.is_not() && refs_number > 0 {
1372                         err.span_suggestion_verbose(
1373                             sp,
1374                             "consider changing this borrow's mutability",
1375                             "&mut ",
1376                             Applicability::MachineApplicable,
1377                         );
1378                     } else {
1379                         err.note(&format!(
1380                             "`{}` is implemented for `{:?}`, but not for `{:?}`",
1381                             trait_pred.print_modifiers_and_trait_path(),
1382                             suggested_ty,
1383                             trait_pred.skip_binder().self_ty(),
1384                         ));
1385                     }
1386                 }
1387             }
1388         }
1389     }
1390
1391     fn suggest_semicolon_removal(
1392         &self,
1393         obligation: &PredicateObligation<'tcx>,
1394         err: &mut Diagnostic,
1395         span: Span,
1396         trait_pred: ty::PolyTraitPredicate<'tcx>,
1397     ) -> bool {
1398         let hir = self.tcx.hir();
1399         let parent_node = hir.get_parent_node(obligation.cause.body_id);
1400         let node = hir.find(parent_node);
1401         if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
1402             && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
1403             && sig.decl.output.span().overlaps(span)
1404             && blk.expr.is_none()
1405             && trait_pred.self_ty().skip_binder().is_unit()
1406             && let Some(stmt) = blk.stmts.last()
1407             && let hir::StmtKind::Semi(expr) = stmt.kind
1408             // Only suggest this if the expression behind the semicolon implements the predicate
1409             && let Some(typeck_results) = &self.typeck_results
1410             && let Some(ty) = typeck_results.expr_ty_opt(expr)
1411             && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(
1412                 obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty))
1413             ))
1414         {
1415             err.span_label(
1416                 expr.span,
1417                 &format!(
1418                     "this expression has type `{}`, which implements `{}`",
1419                     ty,
1420                     trait_pred.print_modifiers_and_trait_path()
1421                 )
1422             );
1423             err.span_suggestion(
1424                 self.tcx.sess.source_map().end_point(stmt.span),
1425                 "remove this semicolon",
1426                 "",
1427                 Applicability::MachineApplicable
1428             );
1429             return true;
1430         }
1431         false
1432     }
1433
1434     fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
1435         let hir = self.tcx.hir();
1436         let parent_node = hir.get_parent_node(obligation.cause.body_id);
1437         let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find(parent_node) else {
1438             return None;
1439         };
1440
1441         if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
1442     }
1443
1444     /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
1445     /// applicable and signal that the error has been expanded appropriately and needs to be
1446     /// emitted.
1447     fn suggest_impl_trait(
1448         &self,
1449         err: &mut Diagnostic,
1450         span: Span,
1451         obligation: &PredicateObligation<'tcx>,
1452         trait_pred: ty::PolyTraitPredicate<'tcx>,
1453     ) -> bool {
1454         match obligation.cause.code().peel_derives() {
1455             // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
1456             ObligationCauseCode::SizedReturnType => {}
1457             _ => return false,
1458         }
1459
1460         let hir = self.tcx.hir();
1461         let fn_hir_id = hir.get_parent_node(obligation.cause.body_id);
1462         let node = hir.find(fn_hir_id);
1463         let Some(hir::Node::Item(hir::Item {
1464             kind: hir::ItemKind::Fn(sig, _, body_id),
1465             ..
1466         })) = node
1467         else {
1468             return false;
1469         };
1470         let body = hir.body(*body_id);
1471         let trait_pred = self.resolve_vars_if_possible(trait_pred);
1472         let ty = trait_pred.skip_binder().self_ty();
1473         let is_object_safe = match ty.kind() {
1474             ty::Dynamic(predicates, _, ty::Dyn) => {
1475                 // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
1476                 predicates
1477                     .principal_def_id()
1478                     .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
1479             }
1480             // We only want to suggest `impl Trait` to `dyn Trait`s.
1481             // For example, `fn foo() -> str` needs to be filtered out.
1482             _ => return false,
1483         };
1484
1485         let hir::FnRetTy::Return(ret_ty) = sig.decl.output else {
1486             return false;
1487         };
1488
1489         // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
1490         // cases like `fn foo() -> (dyn Trait, i32) {}`.
1491         // Recursively look for `TraitObject` types and if there's only one, use that span to
1492         // suggest `impl Trait`.
1493
1494         // Visit to make sure there's a single `return` type to suggest `impl Trait`,
1495         // otherwise suggest using `Box<dyn Trait>` or an enum.
1496         let mut visitor = ReturnsVisitor::default();
1497         visitor.visit_body(&body);
1498
1499         let typeck_results = self.typeck_results.as_ref().unwrap();
1500         let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id).copied() else { return false; };
1501
1502         let ret_types = visitor
1503             .returns
1504             .iter()
1505             .filter_map(|expr| Some((expr.span, typeck_results.node_type_opt(expr.hir_id)?)))
1506             .map(|(expr_span, ty)| (expr_span, self.resolve_vars_if_possible(ty)));
1507         let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold(
1508             (None, true, true),
1509             |(last_ty, mut same, only_never_return): (std::option::Option<Ty<'_>>, bool, bool),
1510              (_, ty)| {
1511                 let ty = self.resolve_vars_if_possible(ty);
1512                 same &=
1513                     !matches!(ty.kind(), ty::Error(_))
1514                         && last_ty.map_or(true, |last_ty| {
1515                             // FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
1516                             // *after* in the dependency graph.
1517                             match (ty.kind(), last_ty.kind()) {
1518                                 (Infer(InferTy::IntVar(_)), Infer(InferTy::IntVar(_)))
1519                                 | (Infer(InferTy::FloatVar(_)), Infer(InferTy::FloatVar(_)))
1520                                 | (Infer(InferTy::FreshIntTy(_)), Infer(InferTy::FreshIntTy(_)))
1521                                 | (
1522                                     Infer(InferTy::FreshFloatTy(_)),
1523                                     Infer(InferTy::FreshFloatTy(_)),
1524                                 ) => true,
1525                                 _ => ty == last_ty,
1526                             }
1527                         });
1528                 (Some(ty), same, only_never_return && matches!(ty.kind(), ty::Never))
1529             },
1530         );
1531         let mut spans_and_needs_box = vec![];
1532
1533         match liberated_sig.output().kind() {
1534             ty::Dynamic(predicates, _, ty::Dyn) => {
1535                 let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
1536                 let param_env = ty::ParamEnv::empty();
1537
1538                 if !only_never_return {
1539                     for (expr_span, return_ty) in ret_types {
1540                         let self_ty_satisfies_dyn_predicates = |self_ty| {
1541                             predicates.iter().all(|predicate| {
1542                                 let pred = predicate.with_self_ty(self.tcx, self_ty);
1543                                 let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred);
1544                                 self.predicate_may_hold(&obl)
1545                             })
1546                         };
1547
1548                         if let ty::Adt(def, substs) = return_ty.kind()
1549                             && def.is_box()
1550                             && self_ty_satisfies_dyn_predicates(substs.type_at(0))
1551                         {
1552                             spans_and_needs_box.push((expr_span, false));
1553                         } else if self_ty_satisfies_dyn_predicates(return_ty) {
1554                             spans_and_needs_box.push((expr_span, true));
1555                         } else {
1556                             return false;
1557                         }
1558                     }
1559                 }
1560             }
1561             _ => return false,
1562         };
1563
1564         let sm = self.tcx.sess.source_map();
1565         if !ret_ty.span.overlaps(span) {
1566             return false;
1567         }
1568         let snippet = if let hir::TyKind::TraitObject(..) = ret_ty.kind {
1569             if let Ok(snippet) = sm.span_to_snippet(ret_ty.span) {
1570                 snippet
1571             } else {
1572                 return false;
1573             }
1574         } else {
1575             // Substitute the type, so we can print a fixup given `type Alias = dyn Trait`
1576             let name = liberated_sig.output().to_string();
1577             let name =
1578                 name.strip_prefix('(').and_then(|name| name.strip_suffix(')')).unwrap_or(&name);
1579             if !name.starts_with("dyn ") {
1580                 return false;
1581             }
1582             name.to_owned()
1583         };
1584
1585         err.code(error_code!(E0746));
1586         err.set_primary_message("return type cannot have an unboxed trait object");
1587         err.children.clear();
1588         let impl_trait_msg = "for information on `impl Trait`, see \
1589             <https://doc.rust-lang.org/book/ch10-02-traits.html\
1590             #returning-types-that-implement-traits>";
1591         let trait_obj_msg = "for information on trait objects, see \
1592             <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
1593             #using-trait-objects-that-allow-for-values-of-different-types>";
1594
1595         let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
1596         let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
1597         if only_never_return {
1598             // No return paths, probably using `panic!()` or similar.
1599             // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
1600             suggest_trait_object_return_type_alternatives(
1601                 err,
1602                 ret_ty.span,
1603                 trait_obj,
1604                 is_object_safe,
1605             );
1606         } else if let (Some(last_ty), true) = (last_ty, all_returns_have_same_type) {
1607             // Suggest `-> impl Trait`.
1608             err.span_suggestion(
1609                 ret_ty.span,
1610                 &format!(
1611                     "use `impl {1}` as the return type, as all return paths are of type `{}`, \
1612                      which implements `{1}`",
1613                     last_ty, trait_obj,
1614                 ),
1615                 format!("impl {}", trait_obj),
1616                 Applicability::MachineApplicable,
1617             );
1618             err.note(impl_trait_msg);
1619         } else {
1620             if is_object_safe {
1621                 // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
1622                 err.multipart_suggestion(
1623                     "return a boxed trait object instead",
1624                     vec![
1625                         (ret_ty.span.shrink_to_lo(), "Box<".to_string()),
1626                         (span.shrink_to_hi(), ">".to_string()),
1627                     ],
1628                     Applicability::MaybeIncorrect,
1629                 );
1630                 for (span, needs_box) in spans_and_needs_box {
1631                     if needs_box {
1632                         err.multipart_suggestion(
1633                             "... and box this value",
1634                             vec![
1635                                 (span.shrink_to_lo(), "Box::new(".to_string()),
1636                                 (span.shrink_to_hi(), ")".to_string()),
1637                             ],
1638                             Applicability::MaybeIncorrect,
1639                         );
1640                     }
1641                 }
1642             } else {
1643                 // This is currently not possible to trigger because E0038 takes precedence, but
1644                 // leave it in for completeness in case anything changes in an earlier stage.
1645                 err.note(&format!(
1646                     "if trait `{}` were object-safe, you could return a trait object",
1647                     trait_obj,
1648                 ));
1649             }
1650             err.note(trait_obj_msg);
1651             err.note(&format!(
1652                 "if all the returned values were of the same type you could use `impl {}` as the \
1653                  return type",
1654                 trait_obj,
1655             ));
1656             err.note(impl_trait_msg);
1657             err.note("you can create a new `enum` with a variant for each returned type");
1658         }
1659         true
1660     }
1661
1662     fn point_at_returns_when_relevant(
1663         &self,
1664         err: &mut Diagnostic,
1665         obligation: &PredicateObligation<'tcx>,
1666     ) {
1667         match obligation.cause.code().peel_derives() {
1668             ObligationCauseCode::SizedReturnType => {}
1669             _ => return,
1670         }
1671
1672         let hir = self.tcx.hir();
1673         let parent_node = hir.get_parent_node(obligation.cause.body_id);
1674         let node = hir.find(parent_node);
1675         if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
1676             node
1677         {
1678             let body = hir.body(*body_id);
1679             // Point at all the `return`s in the function as they have failed trait bounds.
1680             let mut visitor = ReturnsVisitor::default();
1681             visitor.visit_body(&body);
1682             let typeck_results = self.typeck_results.as_ref().unwrap();
1683             for expr in &visitor.returns {
1684                 if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
1685                     let ty = self.resolve_vars_if_possible(returned_ty);
1686                     err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
1687                 }
1688             }
1689         }
1690     }
1691
1692     fn report_closure_arg_mismatch(
1693         &self,
1694         span: Span,
1695         found_span: Option<Span>,
1696         found: ty::PolyTraitRef<'tcx>,
1697         expected: ty::PolyTraitRef<'tcx>,
1698         cause: &ObligationCauseCode<'tcx>,
1699         found_node: Option<Node<'_>>,
1700     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
1701         pub(crate) fn build_fn_sig_ty<'tcx>(
1702             infcx: &InferCtxt<'tcx>,
1703             trait_ref: ty::PolyTraitRef<'tcx>,
1704         ) -> Ty<'tcx> {
1705             let inputs = trait_ref.skip_binder().substs.type_at(1);
1706             let sig = match inputs.kind() {
1707                 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
1708                     infcx.tcx.mk_fn_sig(
1709                         inputs.iter(),
1710                         infcx.next_ty_var(TypeVariableOrigin {
1711                             span: DUMMY_SP,
1712                             kind: TypeVariableOriginKind::MiscVariable,
1713                         }),
1714                         false,
1715                         hir::Unsafety::Normal,
1716                         abi::Abi::Rust,
1717                     )
1718                 }
1719                 _ => infcx.tcx.mk_fn_sig(
1720                     std::iter::once(inputs),
1721                     infcx.next_ty_var(TypeVariableOrigin {
1722                         span: DUMMY_SP,
1723                         kind: TypeVariableOriginKind::MiscVariable,
1724                     }),
1725                     false,
1726                     hir::Unsafety::Normal,
1727                     abi::Abi::Rust,
1728                 ),
1729             };
1730
1731             infcx.tcx.mk_fn_ptr(trait_ref.rebind(sig))
1732         }
1733
1734         let argument_kind = match expected.skip_binder().self_ty().kind() {
1735             ty::Closure(..) => "closure",
1736             ty::Generator(..) => "generator",
1737             _ => "function",
1738         };
1739         let mut err = struct_span_err!(
1740             self.tcx.sess,
1741             span,
1742             E0631,
1743             "type mismatch in {argument_kind} arguments",
1744         );
1745
1746         err.span_label(span, "expected due to this");
1747
1748         let found_span = found_span.unwrap_or(span);
1749         err.span_label(found_span, "found signature defined here");
1750
1751         let expected = build_fn_sig_ty(self, expected);
1752         let found = build_fn_sig_ty(self, found);
1753
1754         let (expected_str, found_str) = self.cmp(expected, found);
1755
1756         let signature_kind = format!("{argument_kind} signature");
1757         err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
1758
1759         self.note_conflicting_closure_bounds(cause, &mut err);
1760
1761         if let Some(found_node) = found_node {
1762             hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
1763         }
1764
1765         err
1766     }
1767
1768     // Add a note if there are two `Fn`-family bounds that have conflicting argument
1769     // requirements, which will always cause a closure to have a type error.
1770     fn note_conflicting_closure_bounds(
1771         &self,
1772         cause: &ObligationCauseCode<'tcx>,
1773         err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1774     ) {
1775         // First, look for an `ExprBindingObligation`, which means we can get
1776         // the unsubstituted predicate list of the called function. And check
1777         // that the predicate that we failed to satisfy is a `Fn`-like trait.
1778         if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause
1779             && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
1780             && let Some(pred) = predicates.predicates.get(*idx)
1781             && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder()
1782             && self.tcx.is_fn_trait(trait_pred.def_id())
1783         {
1784             let expected_self =
1785                 self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
1786             let expected_substs = self
1787                 .tcx
1788                 .anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));
1789
1790             // Find another predicate whose self-type is equal to the expected self type,
1791             // but whose substs don't match.
1792             let other_pred = std::iter::zip(&predicates.predicates, &predicates.spans)
1793                 .enumerate()
1794                 .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
1795                     ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
1796                         if self.tcx.is_fn_trait(trait_pred.def_id())
1797                             && other_idx != idx
1798                             // Make sure that the self type matches
1799                             // (i.e. constraining this closure)
1800                             && expected_self
1801                                 == self.tcx.anonymize_late_bound_regions(
1802                                     pred.kind().rebind(trait_pred.self_ty()),
1803                                 )
1804                             // But the substs don't match (i.e. incompatible args)
1805                             && expected_substs
1806                                 != self.tcx.anonymize_late_bound_regions(
1807                                     pred.kind().rebind(trait_pred.trait_ref.substs),
1808                                 ) =>
1809                     {
1810                         true
1811                     }
1812                     _ => false,
1813                 });
1814             // If we found one, then it's very likely the cause of the error.
1815             if let Some((_, (_, other_pred_span))) = other_pred {
1816                 err.span_note(
1817                     *other_pred_span,
1818                     "closure inferred to have a different signature due to this bound",
1819                 );
1820             }
1821         }
1822     }
1823
1824     fn suggest_fully_qualified_path(
1825         &self,
1826         err: &mut Diagnostic,
1827         item_def_id: DefId,
1828         span: Span,
1829         trait_ref: DefId,
1830     ) {
1831         if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
1832             if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
1833                 err.note(&format!(
1834                     "{}s cannot be accessed directly on a `trait`, they can only be \
1835                         accessed through a specific `impl`",
1836                     assoc_item.kind.as_def_kind().descr(item_def_id)
1837                 ));
1838                 err.span_suggestion(
1839                     span,
1840                     "use the fully qualified path to an implementation",
1841                     format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.name),
1842                     Applicability::HasPlaceholders,
1843                 );
1844             }
1845         }
1846     }
1847
1848     /// Adds an async-await specific note to the diagnostic when the future does not implement
1849     /// an auto trait because of a captured type.
1850     ///
1851     /// ```text
1852     /// note: future does not implement `Qux` as this value is used across an await
1853     ///   --> $DIR/issue-64130-3-other.rs:17:5
1854     ///    |
1855     /// LL |     let x = Foo;
1856     ///    |         - has type `Foo`
1857     /// LL |     baz().await;
1858     ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1859     /// LL | }
1860     ///    | - `x` is later dropped here
1861     /// ```
1862     ///
1863     /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
1864     /// is "replaced" with a different message and a more specific error.
1865     ///
1866     /// ```text
1867     /// error: future cannot be sent between threads safely
1868     ///   --> $DIR/issue-64130-2-send.rs:21:5
1869     ///    |
1870     /// LL | fn is_send<T: Send>(t: T) { }
1871     ///    |               ---- required by this bound in `is_send`
1872     /// ...
1873     /// LL |     is_send(bar());
1874     ///    |     ^^^^^^^ future returned by `bar` is not send
1875     ///    |
1876     ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
1877     ///            implemented for `Foo`
1878     /// note: future is not send as this value is used across an await
1879     ///   --> $DIR/issue-64130-2-send.rs:15:5
1880     ///    |
1881     /// LL |     let x = Foo;
1882     ///    |         - has type `Foo`
1883     /// LL |     baz().await;
1884     ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1885     /// LL | }
1886     ///    | - `x` is later dropped here
1887     /// ```
1888     ///
1889     /// Returns `true` if an async-await specific note was added to the diagnostic.
1890     #[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
1891     fn maybe_note_obligation_cause_for_async_await(
1892         &self,
1893         err: &mut Diagnostic,
1894         obligation: &PredicateObligation<'tcx>,
1895     ) -> bool {
1896         let hir = self.tcx.hir();
1897
1898         // Attempt to detect an async-await error by looking at the obligation causes, looking
1899         // for a generator to be present.
1900         //
1901         // When a future does not implement a trait because of a captured type in one of the
1902         // generators somewhere in the call stack, then the result is a chain of obligations.
1903         //
1904         // Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
1905         // future is passed as an argument to a function C which requires a `Send` type, then the
1906         // chain looks something like this:
1907         //
1908         // - `BuiltinDerivedObligation` with a generator witness (B)
1909         // - `BuiltinDerivedObligation` with a generator (B)
1910         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1911         // - `BuiltinDerivedObligation` with a generator witness (A)
1912         // - `BuiltinDerivedObligation` with a generator (A)
1913         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1914         // - `BindingObligation` with `impl_send (Send requirement)
1915         //
1916         // The first obligation in the chain is the most useful and has the generator that captured
1917         // the type. The last generator (`outer_generator` below) has information about where the
1918         // bound was introduced. At least one generator should be present for this diagnostic to be
1919         // modified.
1920         let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
1921             ty::PredicateKind::Clause(ty::Clause::Trait(p)) => (Some(p), Some(p.self_ty())),
1922             _ => (None, None),
1923         };
1924         let mut generator = None;
1925         let mut outer_generator = None;
1926         let mut next_code = Some(obligation.cause.code());
1927
1928         let mut seen_upvar_tys_infer_tuple = false;
1929
1930         while let Some(code) = next_code {
1931             debug!(?code);
1932             match code {
1933                 ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
1934                     next_code = Some(parent_code);
1935                 }
1936                 ObligationCauseCode::ImplDerivedObligation(cause) => {
1937                     let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
1938                     debug!(
1939                         parent_trait_ref = ?cause.derived.parent_trait_pred,
1940                         self_ty.kind = ?ty.kind(),
1941                         "ImplDerived",
1942                     );
1943
1944                     match *ty.kind() {
1945                         ty::Generator(did, ..) => {
1946                             generator = generator.or(Some(did));
1947                             outer_generator = Some(did);
1948                         }
1949                         ty::GeneratorWitness(..) => {}
1950                         ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
1951                             // By introducing a tuple of upvar types into the chain of obligations
1952                             // of a generator, the first non-generator item is now the tuple itself,
1953                             // we shall ignore this.
1954
1955                             seen_upvar_tys_infer_tuple = true;
1956                         }
1957                         _ if generator.is_none() => {
1958                             trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
1959                             target_ty = Some(ty);
1960                         }
1961                         _ => {}
1962                     }
1963
1964                     next_code = Some(&cause.derived.parent_code);
1965                 }
1966                 ObligationCauseCode::DerivedObligation(derived_obligation)
1967                 | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
1968                     let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
1969                     debug!(
1970                         parent_trait_ref = ?derived_obligation.parent_trait_pred,
1971                         self_ty.kind = ?ty.kind(),
1972                     );
1973
1974                     match *ty.kind() {
1975                         ty::Generator(did, ..) => {
1976                             generator = generator.or(Some(did));
1977                             outer_generator = Some(did);
1978                         }
1979                         ty::GeneratorWitness(..) => {}
1980                         ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
1981                             // By introducing a tuple of upvar types into the chain of obligations
1982                             // of a generator, the first non-generator item is now the tuple itself,
1983                             // we shall ignore this.
1984
1985                             seen_upvar_tys_infer_tuple = true;
1986                         }
1987                         _ if generator.is_none() => {
1988                             trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
1989                             target_ty = Some(ty);
1990                         }
1991                         _ => {}
1992                     }
1993
1994                     next_code = Some(&derived_obligation.parent_code);
1995                 }
1996                 _ => break,
1997             }
1998         }
1999
2000         // Only continue if a generator was found.
2001         debug!(?generator, ?trait_ref, ?target_ty);
2002         let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
2003             return false;
2004         };
2005
2006         let span = self.tcx.def_span(generator_did);
2007
2008         let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
2009         debug!(
2010             ?generator_did,
2011             ?generator_did_root,
2012             typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
2013             ?span,
2014         );
2015
2016         let generator_body = generator_did
2017             .as_local()
2018             .and_then(|def_id| hir.maybe_body_owned_by(def_id))
2019             .map(|body_id| hir.body(body_id));
2020         let mut visitor = AwaitsVisitor::default();
2021         if let Some(body) = generator_body {
2022             visitor.visit_body(body);
2023         }
2024         debug!(awaits = ?visitor.awaits);
2025
2026         // Look for a type inside the generator interior that matches the target type to get
2027         // a span.
2028         let target_ty_erased = self.tcx.erase_regions(target_ty);
2029         let ty_matches = |ty| -> bool {
2030             // Careful: the regions for types that appear in the
2031             // generator interior are not generally known, so we
2032             // want to erase them when comparing (and anyway,
2033             // `Send` and other bounds are generally unaffected by
2034             // the choice of region).  When erasing regions, we
2035             // also have to erase late-bound regions. This is
2036             // because the types that appear in the generator
2037             // interior generally contain "bound regions" to
2038             // represent regions that are part of the suspended
2039             // generator frame. Bound regions are preserved by
2040             // `erase_regions` and so we must also call
2041             // `erase_late_bound_regions`.
2042             let ty_erased = self.tcx.erase_late_bound_regions(ty);
2043             let ty_erased = self.tcx.erase_regions(ty_erased);
2044             let eq = ty_erased == target_ty_erased;
2045             debug!(?ty_erased, ?target_ty_erased, ?eq);
2046             eq
2047         };
2048
2049         // Get the typeck results from the infcx if the generator is the function we are currently
2050         // type-checking; otherwise, get them by performing a query.  This is needed to avoid
2051         // cycles. If we can't use resolved types because the generator comes from another crate,
2052         // we still provide a targeted error but without all the relevant spans.
2053         let generator_data = match &self.typeck_results {
2054             Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData::Local(&t),
2055             _ if generator_did.is_local() => {
2056                 GeneratorData::Local(self.tcx.typeck(generator_did.expect_local()))
2057             }
2058             _ if let Some(generator_diag_data) = self.tcx.generator_diagnostic_data(generator_did) => {
2059                 GeneratorData::Foreign(generator_diag_data)
2060             }
2061             _ => return false,
2062         };
2063
2064         let mut interior_or_upvar_span = None;
2065
2066         let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
2067         debug!(?from_awaited_ty);
2068
2069         // The generator interior types share the same binders
2070         if let Some(cause) =
2071             generator_data.get_generator_interior_types().skip_binder().iter().find(
2072                 |ty::GeneratorInteriorTypeCause { ty, .. }| {
2073                     ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
2074                 },
2075             )
2076         {
2077             let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
2078
2079             interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
2080                 *span,
2081                 Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
2082             ));
2083         }
2084
2085         if interior_or_upvar_span.is_none() {
2086             interior_or_upvar_span =
2087                 generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
2088         }
2089
2090         if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
2091             interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None));
2092         }
2093
2094         debug!(?interior_or_upvar_span);
2095         if let Some(interior_or_upvar_span) = interior_or_upvar_span {
2096             let is_async = self.tcx.generator_is_async(generator_did);
2097             let typeck_results = match generator_data {
2098                 GeneratorData::Local(typeck_results) => Some(typeck_results),
2099                 GeneratorData::Foreign(_) => None,
2100             };
2101             self.note_obligation_cause_for_async_await(
2102                 err,
2103                 interior_or_upvar_span,
2104                 is_async,
2105                 outer_generator,
2106                 trait_ref,
2107                 target_ty,
2108                 typeck_results,
2109                 obligation,
2110                 next_code,
2111             );
2112             true
2113         } else {
2114             false
2115         }
2116     }
2117
2118     /// Unconditionally adds the diagnostic note described in
2119     /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
2120     #[instrument(level = "debug", skip_all)]
2121     fn note_obligation_cause_for_async_await(
2122         &self,
2123         err: &mut Diagnostic,
2124         interior_or_upvar_span: GeneratorInteriorOrUpvar,
2125         is_async: bool,
2126         outer_generator: Option<DefId>,
2127         trait_pred: ty::TraitPredicate<'tcx>,
2128         target_ty: Ty<'tcx>,
2129         typeck_results: Option<&ty::TypeckResults<'tcx>>,
2130         obligation: &PredicateObligation<'tcx>,
2131         next_code: Option<&ObligationCauseCode<'tcx>>,
2132     ) {
2133         let source_map = self.tcx.sess.source_map();
2134
2135         let (await_or_yield, an_await_or_yield) =
2136             if is_async { ("await", "an await") } else { ("yield", "a yield") };
2137         let future_or_generator = if is_async { "future" } else { "generator" };
2138
2139         // Special case the primary error message when send or sync is the trait that was
2140         // not implemented.
2141         let hir = self.tcx.hir();
2142         let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
2143             self.tcx.get_diagnostic_name(trait_pred.def_id())
2144         {
2145             let (trait_name, trait_verb) =
2146                 if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
2147
2148             err.clear_code();
2149             err.set_primary_message(format!(
2150                 "{} cannot be {} between threads safely",
2151                 future_or_generator, trait_verb
2152             ));
2153
2154             let original_span = err.span.primary_span().unwrap();
2155             let mut span = MultiSpan::from_span(original_span);
2156
2157             let message = outer_generator
2158                 .and_then(|generator_did| {
2159                     Some(match self.tcx.generator_kind(generator_did).unwrap() {
2160                         GeneratorKind::Gen => format!("generator is not {}", trait_name),
2161                         GeneratorKind::Async(AsyncGeneratorKind::Fn) => self
2162                             .tcx
2163                             .parent(generator_did)
2164                             .as_local()
2165                             .map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
2166                             .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
2167                             .map(|name| {
2168                                 format!("future returned by `{}` is not {}", name, trait_name)
2169                             })?,
2170                         GeneratorKind::Async(AsyncGeneratorKind::Block) => {
2171                             format!("future created by async block is not {}", trait_name)
2172                         }
2173                         GeneratorKind::Async(AsyncGeneratorKind::Closure) => {
2174                             format!("future created by async closure is not {}", trait_name)
2175                         }
2176                     })
2177                 })
2178                 .unwrap_or_else(|| format!("{} is not {}", future_or_generator, trait_name));
2179
2180             span.push_span_label(original_span, message);
2181             err.set_span(span);
2182
2183             format!("is not {}", trait_name)
2184         } else {
2185             format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
2186         };
2187
2188         let mut explain_yield = |interior_span: Span,
2189                                  yield_span: Span,
2190                                  scope_span: Option<Span>| {
2191             let mut span = MultiSpan::from_span(yield_span);
2192             if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
2193                 // #70935: If snippet contains newlines, display "the value" instead
2194                 // so that we do not emit complex diagnostics.
2195                 let snippet = &format!("`{}`", snippet);
2196                 let snippet = if snippet.contains('\n') { "the value" } else { snippet };
2197                 // note: future is not `Send` as this value is used across an await
2198                 //   --> $DIR/issue-70935-complex-spans.rs:13:9
2199                 //    |
2200                 // LL |            baz(|| async {
2201                 //    |  ______________-
2202                 //    | |
2203                 //    | |
2204                 // LL | |              foo(tx.clone());
2205                 // LL | |          }).await;
2206                 //    | |          - ^^^^^^ await occurs here, with value maybe used later
2207                 //    | |__________|
2208                 //    |            has type `closure` which is not `Send`
2209                 // note: value is later dropped here
2210                 // LL | |          }).await;
2211                 //    | |                  ^
2212                 //
2213                 span.push_span_label(
2214                     yield_span,
2215                     format!("{} occurs here, with {} maybe used later", await_or_yield, snippet),
2216                 );
2217                 span.push_span_label(
2218                     interior_span,
2219                     format!("has type `{}` which {}", target_ty, trait_explanation),
2220                 );
2221                 // If available, use the scope span to annotate the drop location.
2222                 let mut scope_note = None;
2223                 if let Some(scope_span) = scope_span {
2224                     let scope_span = source_map.end_point(scope_span);
2225
2226                     let msg = format!("{} is later dropped here", snippet);
2227                     if source_map.is_multiline(yield_span.between(scope_span)) {
2228                         span.push_span_label(scope_span, msg);
2229                     } else {
2230                         scope_note = Some((scope_span, msg));
2231                     }
2232                 }
2233                 err.span_note(
2234                     span,
2235                     &format!(
2236                         "{} {} as this value is used across {}",
2237                         future_or_generator, trait_explanation, an_await_or_yield
2238                     ),
2239                 );
2240                 if let Some((span, msg)) = scope_note {
2241                     err.span_note(span, &msg);
2242                 }
2243             }
2244         };
2245         match interior_or_upvar_span {
2246             GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
2247                 if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
2248                     if let Some(await_span) = from_awaited_ty {
2249                         // The type causing this obligation is one being awaited at await_span.
2250                         let mut span = MultiSpan::from_span(await_span);
2251                         span.push_span_label(
2252                             await_span,
2253                             format!(
2254                                 "await occurs here on type `{}`, which {}",
2255                                 target_ty, trait_explanation
2256                             ),
2257                         );
2258                         err.span_note(
2259                             span,
2260                             &format!(
2261                                 "future {not_trait} as it awaits another future which {not_trait}",
2262                                 not_trait = trait_explanation
2263                             ),
2264                         );
2265                     } else {
2266                         // Look at the last interior type to get a span for the `.await`.
2267                         debug!(
2268                             generator_interior_types = ?format_args!(
2269                                 "{:#?}", typeck_results.as_ref().map(|t| &t.generator_interior_types)
2270                             ),
2271                         );
2272                         explain_yield(interior_span, yield_span, scope_span);
2273                     }
2274
2275                     if let Some(expr_id) = expr {
2276                         let expr = hir.expect_expr(expr_id);
2277                         debug!("target_ty evaluated from {:?}", expr);
2278
2279                         let parent = hir.get_parent_node(expr_id);
2280                         if let Some(hir::Node::Expr(e)) = hir.find(parent) {
2281                             let parent_span = hir.span(parent);
2282                             let parent_did = parent.owner.to_def_id();
2283                             // ```rust
2284                             // impl T {
2285                             //     fn foo(&self) -> i32 {}
2286                             // }
2287                             // T.foo();
2288                             // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
2289                             // ```
2290                             //
2291                             let is_region_borrow = if let Some(typeck_results) = typeck_results {
2292                                 typeck_results
2293                                     .expr_adjustments(expr)
2294                                     .iter()
2295                                     .any(|adj| adj.is_region_borrow())
2296                             } else {
2297                                 false
2298                             };
2299
2300                             // ```rust
2301                             // struct Foo(*const u8);
2302                             // bar(Foo(std::ptr::null())).await;
2303                             //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
2304                             // ```
2305                             debug!(parent_def_kind = ?self.tcx.def_kind(parent_did));
2306                             let is_raw_borrow_inside_fn_like_call =
2307                                 match self.tcx.def_kind(parent_did) {
2308                                     DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
2309                                     _ => false,
2310                                 };
2311                             if let Some(typeck_results) = typeck_results {
2312                                 if (typeck_results.is_method_call(e) && is_region_borrow)
2313                                     || is_raw_borrow_inside_fn_like_call
2314                                 {
2315                                     err.span_help(
2316                                         parent_span,
2317                                         "consider moving this into a `let` \
2318                         binding to create a shorter lived borrow",
2319                                     );
2320                                 }
2321                             }
2322                         }
2323                     }
2324                 }
2325             }
2326             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
2327                 // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
2328                 let refers_to_non_sync = match target_ty.kind() {
2329                     ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
2330                         Ok(eval) if !eval.may_apply() => Some(ref_ty),
2331                         _ => None,
2332                     },
2333                     _ => None,
2334                 };
2335
2336                 let (span_label, span_note) = match refers_to_non_sync {
2337                     // if `target_ty` is `&T` and `T` fails to impl `Sync`,
2338                     // include suggestions to make `T: Sync` so that `&T: Send`
2339                     Some(ref_ty) => (
2340                         format!(
2341                             "has type `{}` which {}, because `{}` is not `Sync`",
2342                             target_ty, trait_explanation, ref_ty
2343                         ),
2344                         format!(
2345                             "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
2346                             trait_explanation
2347                         ),
2348                     ),
2349                     None => (
2350                         format!("has type `{}` which {}", target_ty, trait_explanation),
2351                         format!("captured value {}", trait_explanation),
2352                     ),
2353                 };
2354
2355                 let mut span = MultiSpan::from_span(upvar_span);
2356                 span.push_span_label(upvar_span, span_label);
2357                 err.span_note(span, &span_note);
2358             }
2359         }
2360
2361         // Add a note for the item obligation that remains - normally a note pointing to the
2362         // bound that introduced the obligation (e.g. `T: Send`).
2363         debug!(?next_code);
2364         self.note_obligation_cause_code(
2365             err,
2366             obligation.predicate,
2367             obligation.param_env,
2368             next_code.unwrap(),
2369             &mut Vec::new(),
2370             &mut Default::default(),
2371         );
2372     }
2373
2374     fn note_obligation_cause_code<T>(
2375         &self,
2376         err: &mut Diagnostic,
2377         predicate: T,
2378         param_env: ty::ParamEnv<'tcx>,
2379         cause_code: &ObligationCauseCode<'tcx>,
2380         obligated_types: &mut Vec<Ty<'tcx>>,
2381         seen_requirements: &mut FxHashSet<DefId>,
2382     ) where
2383         T: ToPredicate<'tcx>,
2384     {
2385         let tcx = self.tcx;
2386         let predicate = predicate.to_predicate(tcx);
2387         match *cause_code {
2388             ObligationCauseCode::ExprAssignable
2389             | ObligationCauseCode::MatchExpressionArm { .. }
2390             | ObligationCauseCode::Pattern { .. }
2391             | ObligationCauseCode::IfExpression { .. }
2392             | ObligationCauseCode::IfExpressionWithNoElse
2393             | ObligationCauseCode::MainFunctionType
2394             | ObligationCauseCode::StartFunctionType
2395             | ObligationCauseCode::IntrinsicType
2396             | ObligationCauseCode::MethodReceiver
2397             | ObligationCauseCode::ReturnNoExpression
2398             | ObligationCauseCode::UnifyReceiver(..)
2399             | ObligationCauseCode::OpaqueType
2400             | ObligationCauseCode::MiscObligation
2401             | ObligationCauseCode::WellFormed(..)
2402             | ObligationCauseCode::MatchImpl(..)
2403             | ObligationCauseCode::ReturnType
2404             | ObligationCauseCode::ReturnValue(_)
2405             | ObligationCauseCode::BlockTailExpression(_)
2406             | ObligationCauseCode::AwaitableExpr(_)
2407             | ObligationCauseCode::ForLoopIterator
2408             | ObligationCauseCode::QuestionMark
2409             | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
2410             | ObligationCauseCode::LetElse
2411             | ObligationCauseCode::BinOp { .. }
2412             | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
2413             | ObligationCauseCode::RustCall => {}
2414             ObligationCauseCode::SliceOrArrayElem => {
2415                 err.note("slice and array elements must have `Sized` type");
2416             }
2417             ObligationCauseCode::TupleElem => {
2418                 err.note("only the last element of a tuple may have a dynamically sized type");
2419             }
2420             ObligationCauseCode::ProjectionWf(data) => {
2421                 err.note(&format!("required so that the projection `{data}` is well-formed"));
2422             }
2423             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
2424                 err.note(&format!(
2425                     "required so that reference `{ref_ty}` does not outlive its referent"
2426                 ));
2427             }
2428             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
2429                 err.note(&format!(
2430                     "required so that the lifetime bound of `{}` for `{}` is satisfied",
2431                     region, object_ty,
2432                 ));
2433             }
2434             ObligationCauseCode::ItemObligation(_)
2435             | ObligationCauseCode::ExprItemObligation(..) => {
2436                 // We hold the `DefId` of the item introducing the obligation, but displaying it
2437                 // doesn't add user usable information. It always point at an associated item.
2438             }
2439             ObligationCauseCode::BindingObligation(item_def_id, span)
2440             | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
2441                 let item_name = tcx.def_path_str(item_def_id);
2442                 let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
2443                 let mut multispan = MultiSpan::from(span);
2444                 let sm = tcx.sess.source_map();
2445                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
2446                     let same_line =
2447                         match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
2448                             (Ok(l), Ok(r)) => l.line == r.line,
2449                             _ => true,
2450                         };
2451                     if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
2452                         multispan.push_span_label(ident.span, "required by a bound in this");
2453                     }
2454                 }
2455                 let descr = format!("required by a bound in `{item_name}`");
2456                 if span.is_visible(sm) {
2457                     let msg = format!("required by this bound in `{short_item_name}`");
2458                     multispan.push_span_label(span, msg);
2459                     err.span_note(multispan, &descr);
2460                 } else {
2461                     err.span_note(tcx.def_span(item_def_id), &descr);
2462                 }
2463             }
2464             ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
2465                 err.note(&format!(
2466                     "required for the cast from `{}` to the object type `{}`",
2467                     self.ty_to_string(concrete_ty),
2468                     self.ty_to_string(object_ty)
2469                 ));
2470             }
2471             ObligationCauseCode::Coercion { source: _, target } => {
2472                 err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
2473             }
2474             ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
2475                 err.note(
2476                     "the `Copy` trait is required because this value will be copied for each element of the array",
2477                 );
2478
2479                 if is_const_fn {
2480                     err.help(
2481                         "consider creating a new `const` item and initializing it with the result \
2482                         of the function call to be used in the repeat position, like \
2483                         `const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
2484                     );
2485                 }
2486
2487                 if self.tcx.sess.is_nightly_build() && is_const_fn {
2488                     err.help(
2489                         "create an inline `const` block, see RFC #2920 \
2490                          <https://github.com/rust-lang/rfcs/pull/2920> for more information",
2491                     );
2492                 }
2493             }
2494             ObligationCauseCode::VariableType(hir_id) => {
2495                 let parent_node = self.tcx.hir().get_parent_node(hir_id);
2496                 match self.tcx.hir().find(parent_node) {
2497                     Some(Node::Local(hir::Local {
2498                         init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }),
2499                         ..
2500                     })) => {
2501                         // When encountering an assignment of an unsized trait, like
2502                         // `let x = ""[..];`, provide a suggestion to borrow the initializer in
2503                         // order to use have a slice instead.
2504                         err.span_suggestion_verbose(
2505                             span.shrink_to_lo(),
2506                             "consider borrowing here",
2507                             "&",
2508                             Applicability::MachineApplicable,
2509                         );
2510                         err.note("all local variables must have a statically known size");
2511                     }
2512                     Some(Node::Param(param)) => {
2513                         err.span_suggestion_verbose(
2514                             param.ty_span.shrink_to_lo(),
2515                             "function arguments must have a statically known size, borrowed types \
2516                             always have a known size",
2517                             "&",
2518                             Applicability::MachineApplicable,
2519                         );
2520                     }
2521                     _ => {
2522                         err.note("all local variables must have a statically known size");
2523                     }
2524                 }
2525                 if !self.tcx.features().unsized_locals {
2526                     err.help("unsized locals are gated as an unstable feature");
2527                 }
2528             }
2529             ObligationCauseCode::SizedArgumentType(sp) => {
2530                 if let Some(span) = sp {
2531                     err.span_suggestion_verbose(
2532                         span.shrink_to_lo(),
2533                         "function arguments must have a statically known size, borrowed types \
2534                          always have a known size",
2535                         "&",
2536                         Applicability::MachineApplicable,
2537                     );
2538                 } else {
2539                     err.note("all function arguments must have a statically known size");
2540                 }
2541                 if tcx.sess.opts.unstable_features.is_nightly_build()
2542                     && !self.tcx.features().unsized_fn_params
2543                 {
2544                     err.help("unsized fn params are gated as an unstable feature");
2545                 }
2546             }
2547             ObligationCauseCode::SizedReturnType => {
2548                 err.note("the return type of a function must have a statically known size");
2549             }
2550             ObligationCauseCode::SizedYieldType => {
2551                 err.note("the yield type of a generator must have a statically known size");
2552             }
2553             ObligationCauseCode::SizedBoxType => {
2554                 err.note("the type of a box expression must have a statically known size");
2555             }
2556             ObligationCauseCode::AssignmentLhsSized => {
2557                 err.note("the left-hand-side of an assignment must have a statically known size");
2558             }
2559             ObligationCauseCode::TupleInitializerSized => {
2560                 err.note("tuples must have a statically known size to be initialized");
2561             }
2562             ObligationCauseCode::StructInitializerSized => {
2563                 err.note("structs must have a statically known size to be initialized");
2564             }
2565             ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
2566                 match *item {
2567                     AdtKind::Struct => {
2568                         if last {
2569                             err.note(
2570                                 "the last field of a packed struct may only have a \
2571                                 dynamically sized type if it does not need drop to be run",
2572                             );
2573                         } else {
2574                             err.note(
2575                                 "only the last field of a struct may have a dynamically sized type",
2576                             );
2577                         }
2578                     }
2579                     AdtKind::Union => {
2580                         err.note("no field of a union may have a dynamically sized type");
2581                     }
2582                     AdtKind::Enum => {
2583                         err.note("no field of an enum variant may have a dynamically sized type");
2584                     }
2585                 }
2586                 err.help("change the field's type to have a statically known size");
2587                 err.span_suggestion(
2588                     span.shrink_to_lo(),
2589                     "borrowed types always have a statically known size",
2590                     "&",
2591                     Applicability::MachineApplicable,
2592                 );
2593                 err.multipart_suggestion(
2594                     "the `Box` type always has a statically known size and allocates its contents \
2595                      in the heap",
2596                     vec![
2597                         (span.shrink_to_lo(), "Box<".to_string()),
2598                         (span.shrink_to_hi(), ">".to_string()),
2599                     ],
2600                     Applicability::MachineApplicable,
2601                 );
2602             }
2603             ObligationCauseCode::ConstSized => {
2604                 err.note("constant expressions must have a statically known size");
2605             }
2606             ObligationCauseCode::InlineAsmSized => {
2607                 err.note("all inline asm arguments must have a statically known size");
2608             }
2609             ObligationCauseCode::ConstPatternStructural => {
2610                 err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
2611             }
2612             ObligationCauseCode::SharedStatic => {
2613                 err.note("shared static variables must have a type that implements `Sync`");
2614             }
2615             ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
2616                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
2617                 let ty = parent_trait_ref.skip_binder().self_ty();
2618                 if parent_trait_ref.references_error() {
2619                     // NOTE(eddyb) this was `.cancel()`, but `err`
2620                     // is borrowed, so we can't fully defuse it.
2621                     err.downgrade_to_delayed_bug();
2622                     return;
2623                 }
2624
2625                 // If the obligation for a tuple is set directly by a Generator or Closure,
2626                 // then the tuple must be the one containing capture types.
2627                 let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
2628                     false
2629                 } else {
2630                     if let ObligationCauseCode::BuiltinDerivedObligation(data) = &*data.parent_code
2631                     {
2632                         let parent_trait_ref =
2633                             self.resolve_vars_if_possible(data.parent_trait_pred);
2634                         let nested_ty = parent_trait_ref.skip_binder().self_ty();
2635                         matches!(nested_ty.kind(), ty::Generator(..))
2636                             || matches!(nested_ty.kind(), ty::Closure(..))
2637                     } else {
2638                         false
2639                     }
2640                 };
2641
2642                 let identity_future = tcx.require_lang_item(LangItem::IdentityFuture, None);
2643
2644                 // Don't print the tuple of capture types
2645                 'print: {
2646                     if !is_upvar_tys_infer_tuple {
2647                         let msg = format!("required because it appears within the type `{}`", ty);
2648                         match ty.kind() {
2649                             ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
2650                                 Some(ident) => err.span_note(ident.span, &msg),
2651                                 None => err.note(&msg),
2652                             },
2653                             ty::Opaque(def_id, _) => {
2654                                 // Avoid printing the future from `core::future::identity_future`, it's not helpful
2655                                 if tcx.parent(*def_id) == identity_future {
2656                                     break 'print;
2657                                 }
2658
2659                                 // If the previous type is `identity_future`, this is the future generated by the body of an async function.
2660                                 // Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
2661                                 let is_future = tcx.ty_is_opaque_future(ty);
2662                                 debug!(
2663                                     ?obligated_types,
2664                                     ?is_future,
2665                                     "note_obligation_cause_code: check for async fn"
2666                                 );
2667                                 if is_future
2668                                     && obligated_types.last().map_or(false, |ty| match ty.kind() {
2669                                         ty::Generator(last_def_id, ..) => {
2670                                             tcx.generator_is_async(*last_def_id)
2671                                         }
2672                                         _ => false,
2673                                     })
2674                                 {
2675                                     break 'print;
2676                                 }
2677                                 err.span_note(self.tcx.def_span(def_id), &msg)
2678                             }
2679                             ty::GeneratorWitness(bound_tys) => {
2680                                 use std::fmt::Write;
2681
2682                                 // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
2683                                 // Maybe we should just remove this note altogether?
2684                                 // FIXME: only print types which don't meet the trait requirement
2685                                 let mut msg =
2686                                     "required because it captures the following types: ".to_owned();
2687                                 for ty in bound_tys.skip_binder() {
2688                                     write!(msg, "`{}`, ", ty).unwrap();
2689                                 }
2690                                 err.note(msg.trim_end_matches(", "))
2691                             }
2692                             ty::Generator(def_id, _, _) => {
2693                                 let sp = self.tcx.def_span(def_id);
2694
2695                                 // Special-case this to say "async block" instead of `[static generator]`.
2696                                 let kind = tcx.generator_kind(def_id).unwrap().descr();
2697                                 err.span_note(
2698                                     sp,
2699                                     &format!("required because it's used within this {}", kind),
2700                                 )
2701                             }
2702                             ty::Closure(def_id, _) => err.span_note(
2703                                 self.tcx.def_span(def_id),
2704                                 &format!("required because it's used within this closure"),
2705                             ),
2706                             _ => err.note(&msg),
2707                         };
2708                     }
2709                 }
2710
2711                 obligated_types.push(ty);
2712
2713                 let parent_predicate = parent_trait_ref;
2714                 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
2715                     // #74711: avoid a stack overflow
2716                     ensure_sufficient_stack(|| {
2717                         self.note_obligation_cause_code(
2718                             err,
2719                             parent_predicate,
2720                             param_env,
2721                             &data.parent_code,
2722                             obligated_types,
2723                             seen_requirements,
2724                         )
2725                     });
2726                 } else {
2727                     ensure_sufficient_stack(|| {
2728                         self.note_obligation_cause_code(
2729                             err,
2730                             parent_predicate,
2731                             param_env,
2732                             cause_code.peel_derives(),
2733                             obligated_types,
2734                             seen_requirements,
2735                         )
2736                     });
2737                 }
2738             }
2739             ObligationCauseCode::ImplDerivedObligation(ref data) => {
2740                 let mut parent_trait_pred =
2741                     self.resolve_vars_if_possible(data.derived.parent_trait_pred);
2742                 parent_trait_pred.remap_constness_diag(param_env);
2743                 let parent_def_id = parent_trait_pred.def_id();
2744                 let (self_ty, file) =
2745                     self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
2746                 let msg = format!(
2747                     "required for `{self_ty}` to implement `{}`",
2748                     parent_trait_pred.print_modifiers_and_trait_path()
2749                 );
2750                 let mut is_auto_trait = false;
2751                 match self.tcx.hir().get_if_local(data.impl_def_id) {
2752                     Some(Node::Item(hir::Item {
2753                         kind: hir::ItemKind::Trait(is_auto, ..),
2754                         ident,
2755                         ..
2756                     })) => {
2757                         // FIXME: we should do something else so that it works even on crate foreign
2758                         // auto traits.
2759                         is_auto_trait = matches!(is_auto, hir::IsAuto::Yes);
2760                         err.span_note(ident.span, &msg)
2761                     }
2762                     Some(Node::Item(hir::Item {
2763                         kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
2764                         ..
2765                     })) => {
2766                         let mut spans = Vec::with_capacity(2);
2767                         if let Some(trait_ref) = of_trait {
2768                             spans.push(trait_ref.path.span);
2769                         }
2770                         spans.push(self_ty.span);
2771                         err.span_note(spans, &msg)
2772                     }
2773                     _ => err.note(&msg),
2774                 };
2775
2776                 if let Some(file) = file {
2777                     err.note(&format!(
2778                         "the full type name has been written to '{}'",
2779                         file.display(),
2780                     ));
2781                 }
2782                 let mut parent_predicate = parent_trait_pred;
2783                 let mut data = &data.derived;
2784                 let mut count = 0;
2785                 seen_requirements.insert(parent_def_id);
2786                 if is_auto_trait {
2787                     // We don't want to point at the ADT saying "required because it appears within
2788                     // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
2789                     while let ObligationCauseCode::BuiltinDerivedObligation(derived) =
2790                         &*data.parent_code
2791                     {
2792                         let child_trait_ref =
2793                             self.resolve_vars_if_possible(derived.parent_trait_pred);
2794                         let child_def_id = child_trait_ref.def_id();
2795                         if seen_requirements.insert(child_def_id) {
2796                             break;
2797                         }
2798                         data = derived;
2799                         parent_predicate = child_trait_ref.to_predicate(tcx);
2800                         parent_trait_pred = child_trait_ref;
2801                     }
2802                 }
2803                 while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
2804                     // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
2805                     let child_trait_pred =
2806                         self.resolve_vars_if_possible(child.derived.parent_trait_pred);
2807                     let child_def_id = child_trait_pred.def_id();
2808                     if seen_requirements.insert(child_def_id) {
2809                         break;
2810                     }
2811                     count += 1;
2812                     data = &child.derived;
2813                     parent_predicate = child_trait_pred.to_predicate(tcx);
2814                     parent_trait_pred = child_trait_pred;
2815                 }
2816                 if count > 0 {
2817                     err.note(&format!(
2818                         "{} redundant requirement{} hidden",
2819                         count,
2820                         pluralize!(count)
2821                     ));
2822                     let (self_ty, file) =
2823                         self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
2824                     err.note(&format!(
2825                         "required for `{self_ty}` to implement `{}`",
2826                         parent_trait_pred.print_modifiers_and_trait_path()
2827                     ));
2828                     if let Some(file) = file {
2829                         err.note(&format!(
2830                             "the full type name has been written to '{}'",
2831                             file.display(),
2832                         ));
2833                     }
2834                 }
2835                 // #74711: avoid a stack overflow
2836                 ensure_sufficient_stack(|| {
2837                     self.note_obligation_cause_code(
2838                         err,
2839                         parent_predicate,
2840                         param_env,
2841                         &data.parent_code,
2842                         obligated_types,
2843                         seen_requirements,
2844                     )
2845                 });
2846             }
2847             ObligationCauseCode::DerivedObligation(ref data) => {
2848                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
2849                 let parent_predicate = parent_trait_ref;
2850                 // #74711: avoid a stack overflow
2851                 ensure_sufficient_stack(|| {
2852                     self.note_obligation_cause_code(
2853                         err,
2854                         parent_predicate,
2855                         param_env,
2856                         &data.parent_code,
2857                         obligated_types,
2858                         seen_requirements,
2859                     )
2860                 });
2861             }
2862             ObligationCauseCode::FunctionArgumentObligation {
2863                 arg_hir_id,
2864                 call_hir_id,
2865                 ref parent_code,
2866             } => {
2867                 self.function_argument_obligation(
2868                     arg_hir_id,
2869                     err,
2870                     parent_code,
2871                     param_env,
2872                     predicate,
2873                     call_hir_id,
2874                 );
2875                 ensure_sufficient_stack(|| {
2876                     self.note_obligation_cause_code(
2877                         err,
2878                         predicate,
2879                         param_env,
2880                         &parent_code,
2881                         obligated_types,
2882                         seen_requirements,
2883                     )
2884                 });
2885             }
2886             ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
2887                 let item_name = self.tcx.item_name(trait_item_def_id);
2888                 let msg = format!(
2889                     "the requirement `{predicate}` appears on the `impl`'s {kind} \
2890                      `{item_name}` but not on the corresponding trait's {kind}",
2891                 );
2892                 let sp = self
2893                     .tcx
2894                     .opt_item_ident(trait_item_def_id)
2895                     .map(|i| i.span)
2896                     .unwrap_or_else(|| self.tcx.def_span(trait_item_def_id));
2897                 let mut assoc_span: MultiSpan = sp.into();
2898                 assoc_span.push_span_label(
2899                     sp,
2900                     format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
2901                 );
2902                 if let Some(ident) = self
2903                     .tcx
2904                     .opt_associated_item(trait_item_def_id)
2905                     .and_then(|i| self.tcx.opt_item_ident(i.container_id(self.tcx)))
2906                 {
2907                     assoc_span.push_span_label(ident.span, "in this trait");
2908                 }
2909                 err.span_note(assoc_span, &msg);
2910             }
2911             ObligationCauseCode::TrivialBound => {
2912                 err.help("see issue #48214");
2913                 if tcx.sess.opts.unstable_features.is_nightly_build() {
2914                     err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
2915                 }
2916             }
2917             ObligationCauseCode::OpaqueReturnType(expr_info) => {
2918                 if let Some((expr_ty, expr_span)) = expr_info {
2919                     let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
2920                     err.span_label(
2921                         expr_span,
2922                         format!("return type was inferred to be `{expr_ty}` here"),
2923                     );
2924                 }
2925             }
2926         }
2927     }
2928
2929     #[instrument(
2930         level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
2931     )]
2932     fn suggest_await_before_try(
2933         &self,
2934         err: &mut Diagnostic,
2935         obligation: &PredicateObligation<'tcx>,
2936         trait_pred: ty::PolyTraitPredicate<'tcx>,
2937         span: Span,
2938     ) {
2939         let body_hir_id = obligation.cause.body_id;
2940         let item_id = self.tcx.hir().get_parent_node(body_hir_id);
2941
2942         if let Some(body_id) =
2943             self.tcx.hir().maybe_body_owned_by(self.tcx.hir().local_def_id(item_id))
2944         {
2945             let body = self.tcx.hir().body(body_id);
2946             if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
2947                 let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
2948
2949                 let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
2950                 let impls_future = self.type_implements_trait(
2951                     future_trait,
2952                     [self.tcx.erase_late_bound_regions(self_ty)],
2953                     obligation.param_env,
2954                 );
2955                 if !impls_future.must_apply_modulo_regions() {
2956                     return;
2957                 }
2958
2959                 let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
2960                 // `<T as Future>::Output`
2961                 let projection_ty = trait_pred.map_bound(|trait_pred| {
2962                     self.tcx.mk_projection(
2963                         item_def_id,
2964                         // Future::Output has no substs
2965                         self.tcx.mk_substs_trait(trait_pred.self_ty(), []),
2966                     )
2967                 });
2968                 let InferOk { value: projection_ty, .. } =
2969                     self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
2970
2971                 debug!(
2972                     normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
2973                 );
2974                 let try_obligation = self.mk_trait_obligation_with_new_self_ty(
2975                     obligation.param_env,
2976                     trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
2977                 );
2978                 debug!(try_trait_obligation = ?try_obligation);
2979                 if self.predicate_may_hold(&try_obligation)
2980                     && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2981                     && snippet.ends_with('?')
2982                 {
2983                     err.span_suggestion_verbose(
2984                         span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
2985                         "consider `await`ing on the `Future`",
2986                         ".await",
2987                         Applicability::MaybeIncorrect,
2988                     );
2989                 }
2990             }
2991         }
2992     }
2993
2994     fn suggest_floating_point_literal(
2995         &self,
2996         obligation: &PredicateObligation<'tcx>,
2997         err: &mut Diagnostic,
2998         trait_ref: &ty::PolyTraitRef<'tcx>,
2999     ) {
3000         let rhs_span = match obligation.cause.code() {
3001             ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span,
3002             _ => return,
3003         };
3004         if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
3005             && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
3006         {
3007             err.span_suggestion_verbose(
3008                 rhs_span.shrink_to_hi(),
3009                 "consider using a floating-point literal by writing it with `.0`",
3010                 ".0",
3011                 Applicability::MaybeIncorrect,
3012             );
3013         }
3014     }
3015
3016     fn suggest_derive(
3017         &self,
3018         obligation: &PredicateObligation<'tcx>,
3019         err: &mut Diagnostic,
3020         trait_pred: ty::PolyTraitPredicate<'tcx>,
3021     ) {
3022         let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
3023             return;
3024         };
3025         let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() {
3026             ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs),
3027             _ => return,
3028         };
3029         let can_derive = {
3030             let is_derivable_trait = match diagnostic_name {
3031                 sym::Default => !adt.is_enum(),
3032                 sym::PartialEq | sym::PartialOrd => {
3033                     let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
3034                     trait_pred.skip_binder().self_ty() == rhs_ty
3035                 }
3036                 sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
3037                 _ => false,
3038             };
3039             is_derivable_trait &&
3040                 // Ensure all fields impl the trait.
3041                 adt.all_fields().all(|field| {
3042                     let field_ty = field.ty(self.tcx, substs);
3043                     let trait_substs = match diagnostic_name {
3044                         sym::PartialEq | sym::PartialOrd => {
3045                             Some(field_ty)
3046                         }
3047                         _ => None,
3048                     };
3049                     let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
3050                         trait_ref: self.tcx.mk_trait_ref(
3051                             trait_pred.def_id(),
3052                             [field_ty].into_iter().chain(trait_substs),
3053                         ),
3054                         ..*tr
3055                     });
3056                     let field_obl = Obligation::new(
3057                         self.tcx,
3058                         obligation.cause.clone(),
3059                         obligation.param_env,
3060                         trait_pred,
3061                     );
3062                     self.predicate_must_hold_modulo_regions(&field_obl)
3063                 })
3064         };
3065         if can_derive {
3066             err.span_suggestion_verbose(
3067                 self.tcx.def_span(adt.did()).shrink_to_lo(),
3068                 &format!(
3069                     "consider annotating `{}` with `#[derive({})]`",
3070                     trait_pred.skip_binder().self_ty(),
3071                     diagnostic_name,
3072                 ),
3073                 format!("#[derive({})]\n", diagnostic_name),
3074                 Applicability::MaybeIncorrect,
3075             );
3076         }
3077     }
3078
3079     fn suggest_dereferencing_index(
3080         &self,
3081         obligation: &PredicateObligation<'tcx>,
3082         err: &mut Diagnostic,
3083         trait_pred: ty::PolyTraitPredicate<'tcx>,
3084     ) {
3085         if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code()
3086             && self.tcx.is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
3087             && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.substs.type_at(1).kind()
3088             && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
3089             && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
3090         {
3091             err.span_suggestion_verbose(
3092                 obligation.cause.span.shrink_to_lo(),
3093             "dereference this index",
3094             '*',
3095                 Applicability::MachineApplicable,
3096             );
3097         }
3098     }
3099     fn function_argument_obligation(
3100         &self,
3101         arg_hir_id: HirId,
3102         err: &mut Diagnostic,
3103         parent_code: &ObligationCauseCode<'tcx>,
3104         param_env: ty::ParamEnv<'tcx>,
3105         predicate: ty::Predicate<'tcx>,
3106         call_hir_id: HirId,
3107     ) {
3108         let tcx = self.tcx;
3109         let hir = tcx.hir();
3110         if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
3111             let parent_id = hir.get_parent_item(arg_hir_id);
3112             let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
3113                 Some(t) if t.hir_owner == parent_id => t,
3114                 _ => self.tcx.typeck(parent_id.def_id),
3115             };
3116             if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
3117                 let expr = expr.peel_blocks();
3118                 let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
3119                 let span = expr.span;
3120                 if Some(span) != err.span.primary_span() {
3121                     err.span_label(
3122                         span,
3123                         if ty.references_error() {
3124                             String::new()
3125                         } else {
3126                             let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
3127                             format!("this tail expression is of type `{ty}`")
3128                         },
3129                     );
3130                 }
3131             }
3132
3133             // FIXME: visit the ty to see if there's any closure involved, and if there is,
3134             // check whether its evaluated return type is the same as the one corresponding
3135             // to an associated type (as seen from `trait_pred`) in the predicate. Like in
3136             // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
3137             let mut type_diffs = vec![];
3138
3139             if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
3140                 && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
3141                 && let Some(pred) = predicates.predicates.get(*idx)
3142                 && let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
3143                     ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
3144                     _ => Err(()),
3145                 })
3146             {
3147                 let mut c = CollectAllMismatches {
3148                     infcx: self.infcx,
3149                     param_env,
3150                     errors: vec![],
3151                 };
3152                 if let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
3153                     ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
3154                     _ => Err(()),
3155                 }) {
3156                     if let Ok(_) = c.relate(trait_pred, trait_predicate) {
3157                         type_diffs = c.errors;
3158                     }
3159                 }
3160             }
3161             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
3162                 && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
3163                 && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
3164                 && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
3165                 && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
3166                 && let Some(binding_expr) = local.init
3167             {
3168                 // If the expression we're calling on is a binding, we want to point at the
3169                 // `let` when talking about the type. Otherwise we'll point at every part
3170                 // of the method chain with the type.
3171                 self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
3172             } else {
3173                 self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
3174             }
3175         }
3176         let call_node = hir.find(call_hir_id);
3177         if let Some(Node::Expr(hir::Expr {
3178             kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
3179         })) = call_node
3180         {
3181             if Some(rcvr.span) == err.span.primary_span() {
3182                 err.replace_span_with(path.ident.span);
3183             }
3184         }
3185         if let Some(Node::Expr(hir::Expr {
3186             kind:
3187                 hir::ExprKind::Call(hir::Expr { span, .. }, _)
3188                 | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
3189             ..
3190         })) = hir.find(call_hir_id)
3191         {
3192             if Some(*span) != err.span.primary_span() {
3193                 err.span_label(*span, "required by a bound introduced by this call");
3194             }
3195         }
3196     }
3197
3198     fn point_at_chain(
3199         &self,
3200         expr: &hir::Expr<'_>,
3201         typeck_results: &TypeckResults<'tcx>,
3202         type_diffs: Vec<TypeError<'tcx>>,
3203         param_env: ty::ParamEnv<'tcx>,
3204         err: &mut Diagnostic,
3205     ) {
3206         let mut primary_spans = vec![];
3207         let mut span_labels = vec![];
3208
3209         let tcx = self.tcx;
3210
3211         let mut assocs = vec![];
3212         // We still want to point at the different methods even if there hasn't
3213         // been a change of assoc type.
3214         let mut call_spans = vec![];
3215         let mut expr = expr;
3216         let mut prev_ty = self.resolve_vars_if_possible(
3217             typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
3218         );
3219         while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
3220             // Point at every method call in the chain with the resulting type.
3221             // vec![1, 2, 3].iter().map(mapper).sum<i32>()
3222             //               ^^^^^^ ^^^^^^^^^^^
3223             expr = rcvr_expr;
3224             let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
3225             call_spans.push(span);
3226
3227             let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
3228             for diff in &type_diffs {
3229                 let Sorts(expected_found) = diff else { continue; };
3230                 let ty::Projection(proj) = expected_found.expected.kind() else { continue; };
3231
3232                 let origin =
3233                     TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
3234                 let trait_def_id = proj.trait_def_id(self.tcx);
3235                 // Make `Self` be equivalent to the type of the call chain
3236                 // expression we're looking at now, so that we can tell what
3237                 // for example `Iterator::Item` is at this point in the chain.
3238                 let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
3239                     match param.kind {
3240                         ty::GenericParamDefKind::Type { .. } => {
3241                             if param.index == 0 {
3242                                 return prev_ty.into();
3243                             }
3244                         }
3245                         ty::GenericParamDefKind::Lifetime
3246                         | ty::GenericParamDefKind::Const { .. } => {}
3247                     }
3248                     self.var_for_def(span, param)
3249                 });
3250                 // This will hold the resolved type of the associated type, if the
3251                 // current expression implements the trait that associated type is
3252                 // in. For example, this would be what `Iterator::Item` is here.
3253                 let ty_var = self.infcx.next_ty_var(origin);
3254                 // This corresponds to `<ExprTy as Iterator>::Item = _`.
3255                 let trait_ref = ty::Binder::dummy(ty::PredicateKind::Clause(
3256                     ty::Clause::Projection(ty::ProjectionPredicate {
3257                         projection_ty: ty::ProjectionTy { substs, item_def_id: proj.item_def_id },
3258                         term: ty_var.into(),
3259                     }),
3260                 ));
3261                 // Add `<ExprTy as Iterator>::Item = _` obligation.
3262                 ocx.register_obligation(Obligation::misc(
3263                     self.tcx,
3264                     span,
3265                     expr.hir_id,
3266                     param_env,
3267                     trait_ref,
3268                 ));
3269                 if ocx.select_where_possible().is_empty() {
3270                     // `ty_var` now holds the type that `Item` is for `ExprTy`.
3271                     let ty_var = self.resolve_vars_if_possible(ty_var);
3272                     assocs_in_this_method.push(Some((span, (proj.item_def_id, ty_var))));
3273                 } else {
3274                     // `<ExprTy as Iterator>` didn't select, so likely we've
3275                     // reached the end of the iterator chain, like the originating
3276                     // `Vec<_>`.
3277                     // Keep the space consistent for later zipping.
3278                     assocs_in_this_method.push(None);
3279                 }
3280             }
3281             assocs.push(assocs_in_this_method);
3282             prev_ty = self.resolve_vars_if_possible(
3283                 typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
3284             );
3285
3286             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
3287                 && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
3288                 && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
3289                 && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
3290                 && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
3291                 && let Some(binding_expr) = local.init
3292             {
3293                 // We've reached the root of the method call chain and it is a
3294                 // binding. Get the binding creation and try to continue the chain.
3295                 expr = binding_expr;
3296             }
3297         }
3298         // We want the type before deref coercions, otherwise we talk about `&[_]`
3299         // instead of `Vec<_>`.
3300         if let Some(ty) = typeck_results.expr_ty_opt(expr) {
3301             let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
3302             // Point at the root expression
3303             // vec![1, 2, 3].iter().map(mapper).sum<i32>()
3304             // ^^^^^^^^^^^^^
3305             span_labels.push((expr.span, format!("this expression has type `{ty}`")));
3306         };
3307         // Only show this if it is not a "trivial" expression (not a method
3308         // chain) and there are associated types to talk about.
3309         let mut assocs = assocs.into_iter().peekable();
3310         while let Some(assocs_in_method) = assocs.next() {
3311             let Some(prev_assoc_in_method) = assocs.peek() else {
3312                 for entry in assocs_in_method {
3313                     let Some((span, (assoc, ty))) = entry else { continue; };
3314                     if type_diffs.iter().any(|diff| {
3315                         let Sorts(expected_found) = diff else { return false; };
3316                         self.can_eq(param_env, expected_found.found, ty).is_ok()
3317                     }) {
3318                         // FIXME: this doesn't quite work for `Iterator::collect`
3319                         // because we have `Vec<i32>` and `()`, but we'd want `i32`
3320                         // to point at the `.into_iter()` call, but as long as we
3321                         // still point at the other method calls that might have
3322                         // introduced the issue, this is fine for now.
3323                         primary_spans.push(span);
3324                     }
3325                     span_labels.push((
3326                         span,
3327                         with_forced_trimmed_paths!(format!(
3328                             "`{}` is `{ty}` here",
3329                             self.tcx.def_path_str(assoc),
3330                         )),
3331                     ));
3332                 }
3333                 break;
3334             };
3335             for (entry, prev_entry) in
3336                 assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
3337             {
3338                 match (entry, prev_entry) {
3339                     (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
3340                         let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
3341
3342                         let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
3343                         if ty != *prev_ty {
3344                             if type_diffs.iter().any(|diff| {
3345                                 let Sorts(expected_found) = diff else { return false; };
3346                                 self.can_eq(param_env, expected_found.found, ty).is_ok()
3347                             }) {
3348                                 primary_spans.push(span);
3349                             }
3350                             span_labels
3351                                 .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
3352                         } else {
3353                             span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
3354                         }
3355                     }
3356                     (Some((span, (assoc, ty))), None) => {
3357                         span_labels.push((
3358                             span,
3359                             with_forced_trimmed_paths!(format!(
3360                                 "`{}` is `{}` here",
3361                                 self.tcx.def_path_str(assoc),
3362                                 self.ty_to_string(ty),
3363                             )),
3364                         ));
3365                     }
3366                     (None, Some(_)) | (None, None) => {}
3367                 }
3368             }
3369         }
3370         for span in call_spans {
3371             if span_labels.iter().find(|(s, _)| *s == span).is_none() {
3372                 // Ensure we are showing the entire chain, even if the assoc types
3373                 // haven't changed.
3374                 span_labels.push((span, String::new()));
3375             }
3376         }
3377         if !primary_spans.is_empty() {
3378             let mut multi_span: MultiSpan = primary_spans.into();
3379             for (span, label) in span_labels {
3380                 multi_span.push_span_label(span, label);
3381             }
3382             err.span_note(
3383                 multi_span,
3384                 format!(
3385                     "the method call chain might not have had the expected \
3386                                      associated types",
3387                 ),
3388             );
3389         }
3390     }
3391 }
3392
3393 /// Add a hint to add a missing borrow or remove an unnecessary one.
3394 fn hint_missing_borrow<'tcx>(
3395     span: Span,
3396     found_span: Span,
3397     found: Ty<'tcx>,
3398     expected: Ty<'tcx>,
3399     found_node: Node<'_>,
3400     err: &mut Diagnostic,
3401 ) {
3402     let found_args = match found.kind() {
3403         ty::FnPtr(f) => f.inputs().skip_binder().iter(),
3404         kind => {
3405             span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
3406         }
3407     };
3408     let expected_args = match expected.kind() {
3409         ty::FnPtr(f) => f.inputs().skip_binder().iter(),
3410         kind => {
3411             span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
3412         }
3413     };
3414
3415     let fn_decl = found_node
3416         .fn_decl()
3417         .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
3418
3419     let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
3420
3421     fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
3422         let mut refs = 0;
3423
3424         while let ty::Ref(_, new_ty, _) = ty.kind() {
3425             ty = *new_ty;
3426             refs += 1;
3427         }
3428
3429         (ty, refs)
3430     }
3431
3432     let mut to_borrow = Vec::new();
3433     let mut remove_borrow = Vec::new();
3434
3435     for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
3436         let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
3437         let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
3438
3439         if found_ty == expected_ty {
3440             if found_refs < expected_refs {
3441                 to_borrow.push((arg_span, expected_arg.to_string()));
3442             } else if found_refs > expected_refs {
3443                 remove_borrow.push((arg_span, expected_arg.to_string()));
3444             }
3445         }
3446     }
3447
3448     if !to_borrow.is_empty() {
3449         err.multipart_suggestion(
3450             "consider borrowing the argument",
3451             to_borrow,
3452             Applicability::MaybeIncorrect,
3453         );
3454     }
3455
3456     if !remove_borrow.is_empty() {
3457         err.multipart_suggestion(
3458             "do not borrow the argument",
3459             remove_borrow,
3460             Applicability::MaybeIncorrect,
3461         );
3462     }
3463 }
3464
3465 /// Collect all the returned expressions within the input expression.
3466 /// Used to point at the return spans when we want to suggest some change to them.
3467 #[derive(Default)]
3468 pub struct ReturnsVisitor<'v> {
3469     pub returns: Vec<&'v hir::Expr<'v>>,
3470     in_block_tail: bool,
3471 }
3472
3473 impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
3474     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
3475         // Visit every expression to detect `return` paths, either through the function's tail
3476         // expression or `return` statements. We walk all nodes to find `return` statements, but
3477         // we only care about tail expressions when `in_block_tail` is `true`, which means that
3478         // they're in the return path of the function body.
3479         match ex.kind {
3480             hir::ExprKind::Ret(Some(ex)) => {
3481                 self.returns.push(ex);
3482             }
3483             hir::ExprKind::Block(block, _) if self.in_block_tail => {
3484                 self.in_block_tail = false;
3485                 for stmt in block.stmts {
3486                     hir::intravisit::walk_stmt(self, stmt);
3487                 }
3488                 self.in_block_tail = true;
3489                 if let Some(expr) = block.expr {
3490                     self.visit_expr(expr);
3491                 }
3492             }
3493             hir::ExprKind::If(_, then, else_opt) if self.in_block_tail => {
3494                 self.visit_expr(then);
3495                 if let Some(el) = else_opt {
3496                     self.visit_expr(el);
3497                 }
3498             }
3499             hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
3500                 for arm in arms {
3501                     self.visit_expr(arm.body);
3502                 }
3503             }
3504             // We need to walk to find `return`s in the entire body.
3505             _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
3506             _ => self.returns.push(ex),
3507         }
3508     }
3509
3510     fn visit_body(&mut self, body: &'v hir::Body<'v>) {
3511         assert!(!self.in_block_tail);
3512         if body.generator_kind().is_none() {
3513             if let hir::ExprKind::Block(block, None) = body.value.kind {
3514                 if block.expr.is_some() {
3515                     self.in_block_tail = true;
3516                 }
3517             }
3518         }
3519         hir::intravisit::walk_body(self, body);
3520     }
3521 }
3522
3523 /// Collect all the awaited expressions within the input expression.
3524 #[derive(Default)]
3525 struct AwaitsVisitor {
3526     awaits: Vec<hir::HirId>,
3527 }
3528
3529 impl<'v> Visitor<'v> for AwaitsVisitor {
3530     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
3531         if let hir::ExprKind::Yield(_, hir::YieldSource::Await { expr: Some(id) }) = ex.kind {
3532             self.awaits.push(id)
3533         }
3534         hir::intravisit::walk_expr(self, ex)
3535     }
3536 }
3537
3538 pub trait NextTypeParamName {
3539     fn next_type_param_name(&self, name: Option<&str>) -> String;
3540 }
3541
3542 impl NextTypeParamName for &[hir::GenericParam<'_>] {
3543     fn next_type_param_name(&self, name: Option<&str>) -> String {
3544         // This is the list of possible parameter names that we might suggest.
3545         let name = name.and_then(|n| n.chars().next()).map(|c| c.to_string().to_uppercase());
3546         let name = name.as_deref();
3547         let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
3548         let used_names = self
3549             .iter()
3550             .filter_map(|p| match p.name {
3551                 hir::ParamName::Plain(ident) => Some(ident.name),
3552                 _ => None,
3553             })
3554             .collect::<Vec<_>>();
3555
3556         possible_names
3557             .iter()
3558             .find(|n| !used_names.contains(&Symbol::intern(n)))
3559             .unwrap_or(&"ParamName")
3560             .to_string()
3561     }
3562 }
3563
3564 fn suggest_trait_object_return_type_alternatives(
3565     err: &mut Diagnostic,
3566     ret_ty: Span,
3567     trait_obj: &str,
3568     is_object_safe: bool,
3569 ) {
3570     err.span_suggestion(
3571         ret_ty,
3572         "use some type `T` that is `T: Sized` as the return type if all return paths have the \
3573             same type",
3574         "T",
3575         Applicability::MaybeIncorrect,
3576     );
3577     err.span_suggestion(
3578         ret_ty,
3579         &format!(
3580             "use `impl {}` as the return type if all return paths have the same type but you \
3581                 want to expose only the trait in the signature",
3582             trait_obj,
3583         ),
3584         format!("impl {}", trait_obj),
3585         Applicability::MaybeIncorrect,
3586     );
3587     if is_object_safe {
3588         err.multipart_suggestion(
3589             &format!(
3590                 "use a boxed trait object if all return paths implement trait `{}`",
3591                 trait_obj,
3592             ),
3593             vec![
3594                 (ret_ty.shrink_to_lo(), "Box<".to_string()),
3595                 (ret_ty.shrink_to_hi(), ">".to_string()),
3596             ],
3597             Applicability::MaybeIncorrect,
3598         );
3599     }
3600 }
3601
3602 /// Collect the spans that we see the generic param `param_did`
3603 struct ReplaceImplTraitVisitor<'a> {
3604     ty_spans: &'a mut Vec<Span>,
3605     param_did: DefId,
3606 }
3607
3608 impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
3609     fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) {
3610         if let hir::TyKind::Path(hir::QPath::Resolved(
3611             None,
3612             hir::Path { res: hir::def::Res::Def(_, segment_did), .. },
3613         )) = t.kind
3614         {
3615             if self.param_did == *segment_did {
3616                 // `fn foo(t: impl Trait)`
3617                 //            ^^^^^^^^^^ get this to suggest `T` instead
3618
3619                 // There might be more than one `impl Trait`.
3620                 self.ty_spans.push(t.span);
3621                 return;
3622             }
3623         }
3624
3625         hir::intravisit::walk_ty(self, t);
3626     }
3627 }
3628
3629 // Replace `param` with `replace_ty`
3630 struct ReplaceImplTraitFolder<'tcx> {
3631     tcx: TyCtxt<'tcx>,
3632     param: &'tcx ty::GenericParamDef,
3633     replace_ty: Ty<'tcx>,
3634 }
3635
3636 impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> {
3637     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
3638         if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
3639             if self.param.index == *index {
3640                 return self.replace_ty;
3641             }
3642         }
3643         t.super_fold_with(self)
3644     }
3645
3646     fn tcx(&self) -> TyCtxt<'tcx> {
3647         self.tcx
3648     }
3649 }