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