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