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