Skip to main content

rustc_trait_selection/error_reporting/traits/
suggestions.rs

1// ignore-tidy-filelength
2
3use std::borrow::Cow;
4use std::path::PathBuf;
5use std::{debug_assert_matches, iter};
6
7use itertools::{EitherOrBoth, Itertools};
8use rustc_abi::ExternAbi;
9use rustc_data_structures::fx::FxHashSet;
10use rustc_data_structures::stack::ensure_sufficient_stack;
11use rustc_errors::codes::*;
12use rustc_errors::{
13    Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize,
14    struct_span_code_err,
15};
16use rustc_hir::def::{CtorOf, DefKind, Res};
17use rustc_hir::def_id::DefId;
18use rustc_hir::intravisit::{Visitor, VisitorExt};
19use rustc_hir::lang_items::LangItem;
20use rustc_hir::{
21    self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
22    expr_needs_parens,
23};
24use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
25use rustc_infer::traits::ImplSource;
26use rustc_middle::middle::privacy::Level;
27use rustc_middle::traits::IsConstable;
28use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
29use rustc_middle::ty::error::TypeError;
30use rustc_middle::ty::print::{
31    PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
32    with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion,
33};
34use rustc_middle::ty::{
35    self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
36    TypeSuperFoldable, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, TypeckResults, Upcast,
37    suggest_arbitrary_trait_bound, suggest_constraining_type_param,
38};
39use rustc_middle::{bug, span_bug};
40use rustc_span::def_id::LocalDefId;
41use rustc_span::{
42    BytePos, DUMMY_SP, DesugaringKind, ExpnKind, Ident, MacroKind, Span, Symbol, kw, sym,
43};
44use tracing::{debug, instrument};
45
46use super::{
47    DefIdOrName, FindExprBySpan, ImplCandidate, Obligation, ObligationCause, ObligationCauseCode,
48    PredicateObligation,
49};
50use crate::error_reporting::TypeErrCtxt;
51use crate::errors;
52use crate::infer::InferCtxtExt as _;
53use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
54use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt, SelectionContext};
55
56#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CoroutineInteriorOrUpvar {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CoroutineInteriorOrUpvar::Interior(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "Interior", __self_0, &__self_1),
            CoroutineInteriorOrUpvar::Upvar(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Upvar",
                    &__self_0),
        }
    }
}Debug)]
57pub enum CoroutineInteriorOrUpvar {
58    // span of interior type
59    Interior(Span, Option<(Span, Option<Span>)>),
60    // span of upvar
61    Upvar(Span),
62}
63
64// This type provides a uniform interface to retrieve data on coroutines, whether it originated from
65// the local crate being compiled or from a foreign crate.
66#[derive(#[automatically_derived]
impl<'a, 'tcx> ::core::fmt::Debug for CoroutineData<'a, 'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "CoroutineData",
            &&self.0)
    }
}Debug)]
67struct CoroutineData<'a, 'tcx>(&'a TypeckResults<'tcx>);
68
69impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
70    /// Try to get information about variables captured by the coroutine that matches a type we are
71    /// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
72    /// meet an obligation
73    fn try_get_upvar_span<F>(
74        &self,
75        infer_context: &InferCtxt<'tcx>,
76        coroutine_did: DefId,
77        ty_matches: F,
78    ) -> Option<CoroutineInteriorOrUpvar>
79    where
80        F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
81    {
82        infer_context.tcx.upvars_mentioned(coroutine_did).and_then(|upvars| {
83            upvars.iter().find_map(|(upvar_id, upvar)| {
84                let upvar_ty = self.0.node_type(*upvar_id);
85                let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
86                ty_matches(ty::Binder::dummy(upvar_ty))
87                    .then(|| CoroutineInteriorOrUpvar::Upvar(upvar.span))
88            })
89        })
90    }
91
92    /// Try to get the span of a type being awaited on that matches the type we are looking with the
93    /// `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
94    /// obligation
95    fn get_from_await_ty<F>(
96        &self,
97        visitor: AwaitsVisitor,
98        tcx: TyCtxt<'tcx>,
99        ty_matches: F,
100    ) -> Option<Span>
101    where
102        F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
103    {
104        visitor
105            .awaits
106            .into_iter()
107            .map(|id| tcx.hir_expect_expr(id))
108            .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(await_expr))))
109            .map(|expr| expr.span)
110    }
111}
112
113fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
114    (
115        generics.tail_span_for_predicate_suggestion(),
116        {
    let _guard =
        ::rustc_middle::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion);
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("{0} {1}",
                    generics.add_where_or_trailing_comma(), pred))
        })
}with_types_for_suggestion!(format!("{} {}", generics.add_where_or_trailing_comma(), pred)),
117    )
118}
119
120/// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but
121/// it can also be an `impl Trait` param that needs to be decomposed to a type
122/// param for cleaner code.
123pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
124    tcx: TyCtxt<'tcx>,
125    item_id: LocalDefId,
126    hir_generics: &hir::Generics<'tcx>,
127    msg: &str,
128    err: &mut Diag<'_, G>,
129    fn_sig: Option<&hir::FnSig<'_>>,
130    projection: Option<ty::AliasTy<'_>>,
131    trait_pred: ty::PolyTraitPredicate<'tcx>,
132    // When we are dealing with a trait, `super_traits` will be `Some`:
133    // Given `trait T: A + B + C {}`
134    //              -  ^^^^^^^^^ GenericBounds
135    //              |
136    //              &Ident
137    super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
138) {
139    if hir_generics.where_clause_span.from_expansion()
140        || hir_generics.where_clause_span.desugaring_kind().is_some()
141        || projection.is_some_and(|projection| {
142            (tcx.is_impl_trait_in_trait(projection.kind.def_id())
143                && !tcx.features().return_type_notation())
144                || tcx
145                    .lookup_stability(projection.kind.def_id())
146                    .is_some_and(|stab| stab.is_unstable())
147        })
148    {
149        return;
150    }
151    let generics = tcx.generics_of(item_id);
152    // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
153    if let Some((param, bound_str, fn_sig)) =
154        fn_sig.zip(projection).and_then(|(sig, p)| match *p.self_ty().kind() {
155            // Shenanigans to get the `Trait` from the `impl Trait`.
156            ty::Param(param) => {
157                let param_def = generics.type_param(param, tcx);
158                if param_def.kind.is_synthetic() {
159                    let bound_str =
160                        param_def.name.as_str().strip_prefix("impl ")?.trim_start().to_string();
161                    return Some((param_def, bound_str, sig));
162                }
163                None
164            }
165            _ => None,
166        })
167    {
168        let type_param_name = hir_generics.params.next_type_param_name(Some(&bound_str));
169        let trait_pred = trait_pred.fold_with(&mut ReplaceImplTraitFolder {
170            tcx,
171            param,
172            replace_ty: ty::ParamTy::new(generics.count() as u32, Symbol::intern(&type_param_name))
173                .to_ty(tcx),
174        });
175        if !trait_pred.is_suggestable(tcx, false) {
176            return;
177        }
178        // We know we have an `impl Trait` that doesn't satisfy a required projection.
179
180        // Find all of the occurrences of `impl Trait` for `Trait` in the function arguments'
181        // types. There should be at least one, but there might be *more* than one. In that
182        // case we could just ignore it and try to identify which one needs the restriction,
183        // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
184        // where `T: Trait`.
185        let mut ty_spans = ::alloc::vec::Vec::new()vec![];
186        for input in fn_sig.decl.inputs {
187            ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id }
188                .visit_ty_unambig(input);
189        }
190        // The type param `T: Trait` we will suggest to introduce.
191        let type_param = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", type_param_name,
                bound_str))
    })format!("{type_param_name}: {bound_str}");
192
193        let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [if let Some(span) = hir_generics.span_for_param_suggestion() {
                    (span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!(", {0}", type_param))
                            }))
                } else {
                    (hir_generics.span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("<{0}>", type_param))
                            }))
                },
                predicate_constraint(hir_generics, trait_pred.upcast(tcx))]))vec![
194            if let Some(span) = hir_generics.span_for_param_suggestion() {
195                (span, format!(", {type_param}"))
196            } else {
197                (hir_generics.span, format!("<{type_param}>"))
198            },
199            // `fn foo(t: impl Trait)`
200            //                       ^ suggest `where <T as Trait>::A: Bound`
201            predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
202        ];
203        sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
204
205        // Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
206        // FIXME: we should suggest `fn foo(t: impl Trait<A: Bound>)` instead.
207        err.multipart_suggestion(
208            "introduce a type parameter with a trait bound instead of using `impl Trait`",
209            sugg,
210            Applicability::MaybeIncorrect,
211        );
212    } else {
213        if !trait_pred.is_suggestable(tcx, false) {
214            return;
215        }
216        // Trivial case: `T` needs an extra bound: `T: Bound`.
217        let (sp, suggestion) = match (
218            hir_generics
219                .params
220                .iter()
221                .find(|p| !#[allow(non_exhaustive_omitted_patterns)] match p.kind {
    hir::GenericParamKind::Type { synthetic: true, .. } => true,
    _ => false,
}matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
222            super_traits,
223        ) {
224            (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
225            (None, Some((ident, []))) => (
226                ident.span.shrink_to_hi(),
227                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(": {0}",
                trait_pred.print_modifiers_and_trait_path()))
    })format!(": {}", trait_pred.print_modifiers_and_trait_path()),
228            ),
229            (_, Some((_, [.., bounds]))) => (
230                bounds.span().shrink_to_hi(),
231                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}",
                trait_pred.print_modifiers_and_trait_path()))
    })format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
232            ),
233            (Some(_), Some((_, []))) => (
234                hir_generics.span.shrink_to_hi(),
235                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(": {0}",
                trait_pred.print_modifiers_and_trait_path()))
    })format!(": {}", trait_pred.print_modifiers_and_trait_path()),
236            ),
237        };
238
239        err.span_suggestion_verbose(
240            sp,
241            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider further restricting {0}",
                msg))
    })format!("consider further restricting {msg}"),
242            suggestion,
243            Applicability::MachineApplicable,
244        );
245    }
246}
247
248impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
249    pub fn note_field_shadowed_by_private_candidate_in_cause(
250        &self,
251        err: &mut Diag<'_>,
252        cause: &ObligationCause<'tcx>,
253        param_env: ty::ParamEnv<'tcx>,
254    ) {
255        let mut hir_ids = FxHashSet::default();
256        // Walk the parent chain so we can recover
257        // the source expression from whichever layer carries them.
258        let mut next_code = Some(cause.code());
259        while let Some(cause_code) = next_code {
260            match cause_code {
261                ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
262                    hir_ids.insert(*lhs_hir_id);
263                    hir_ids.insert(*rhs_hir_id);
264                }
265                ObligationCauseCode::FunctionArg { arg_hir_id, .. }
266                | ObligationCauseCode::ReturnValue(arg_hir_id)
267                | ObligationCauseCode::AwaitableExpr(arg_hir_id)
268                | ObligationCauseCode::BlockTailExpression(arg_hir_id, _)
269                | ObligationCauseCode::UnOp { hir_id: arg_hir_id } => {
270                    hir_ids.insert(*arg_hir_id);
271                }
272                ObligationCauseCode::OpaqueReturnType(Some((_, hir_id))) => {
273                    hir_ids.insert(*hir_id);
274                }
275                _ => {}
276            }
277            next_code = cause_code.parent();
278        }
279
280        if !cause.span.is_dummy()
281            && let Some(body) = self.tcx.hir_maybe_body_owned_by(cause.body_id)
282        {
283            let mut expr_finder = FindExprBySpan::new(cause.span, self.tcx);
284            expr_finder.visit_body(body);
285            if let Some(expr) = expr_finder.result {
286                hir_ids.insert(expr.hir_id);
287            }
288        }
289
290        // we will sort immediately by source order before emitting any diagnostics
291        #[allow(rustc::potential_query_instability)]
292        let mut hir_ids: Vec<_> = hir_ids.into_iter().collect();
293        let source_map = self.tcx.sess.source_map();
294        hir_ids.sort_by_cached_key(|hir_id| {
295            let span = self.tcx.hir_span(*hir_id);
296            let lo = source_map.lookup_byte_offset(span.lo());
297            let hi = source_map.lookup_byte_offset(span.hi());
298            (lo.sf.name.prefer_remapped_unconditionally().to_string(), lo.pos.0, hi.pos.0)
299        });
300
301        for hir_id in hir_ids {
302            self.note_field_shadowed_by_private_candidate(err, hir_id, param_env);
303        }
304    }
305
306    pub fn note_field_shadowed_by_private_candidate(
307        &self,
308        err: &mut Diag<'_>,
309        hir_id: hir::HirId,
310        param_env: ty::ParamEnv<'tcx>,
311    ) {
312        let Some(typeck_results) = &self.typeck_results else {
313            return;
314        };
315        let Node::Expr(expr) = self.tcx.hir_node(hir_id) else {
316            return;
317        };
318        let hir::ExprKind::Field(base_expr, field_ident) = expr.kind else {
319            return;
320        };
321
322        let Some(base_ty) = typeck_results.expr_ty_opt(base_expr) else {
323            return;
324        };
325        let base_ty = self.resolve_vars_if_possible(base_ty);
326        if base_ty.references_error() {
327            return;
328        }
329
330        let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(typeck_results.hir_owner.def_id);
331        let mut private_candidate: Option<(Ty<'tcx>, Ty<'tcx>, Span)> = None;
332
333        for (deref_base_ty, _) in (self.autoderef_steps)(base_ty) {
334            let ty::Adt(base_def, args) = deref_base_ty.kind() else {
335                continue;
336            };
337
338            if base_def.is_enum() {
339                continue;
340            }
341
342            let (adjusted_ident, def_scope) =
343                self.tcx.adjust_ident_and_get_scope(field_ident, base_def.did(), fn_body_hir_id);
344
345            let Some((_, field_def)) =
346                base_def.non_enum_variant().fields.iter_enumerated().find(|(_, field)| {
347                    field.ident(self.tcx).normalize_to_macros_2_0() == adjusted_ident
348                })
349            else {
350                continue;
351            };
352            let field_span = self
353                .tcx
354                .def_ident_span(field_def.did)
355                .unwrap_or_else(|| self.tcx.def_span(field_def.did));
356
357            if field_def.vis.is_accessible_from(def_scope, self.tcx) {
358                let accessible_field_ty = field_def.ty(self.tcx, args);
359                if let Some((private_base_ty, private_field_ty, private_field_span)) =
360                    private_candidate
361                    && !self.can_eq(param_env, private_field_ty, accessible_field_ty)
362                {
363                    let private_struct_span = match private_base_ty.kind() {
364                        ty::Adt(private_base_def, _) => self
365                            .tcx
366                            .def_ident_span(private_base_def.did())
367                            .unwrap_or_else(|| self.tcx.def_span(private_base_def.did())),
368                        _ => DUMMY_SP,
369                    };
370                    let accessible_struct_span = self
371                        .tcx
372                        .def_ident_span(base_def.did())
373                        .unwrap_or_else(|| self.tcx.def_span(base_def.did()));
374                    let deref_impl_span = (typeck_results
375                        .expr_adjustments(base_expr)
376                        .iter()
377                        .filter(|adj| {
378                            #[allow(non_exhaustive_omitted_patterns)] match adj.kind {
    Adjust::Deref(DerefAdjustKind::Overloaded(_)) => true,
    _ => false,
}matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))
379                        })
380                        .count()
381                        == 1)
382                        .then(|| {
383                            self.probe(|_| {
384                                let deref_trait_did =
385                                    self.tcx.require_lang_item(LangItem::Deref, DUMMY_SP);
386                                let trait_ref =
387                                    ty::TraitRef::new(self.tcx, deref_trait_did, [private_base_ty]);
388                                let obligation: Obligation<'tcx, ty::Predicate<'tcx>> =
389                                    Obligation::new(
390                                        self.tcx,
391                                        ObligationCause::dummy(),
392                                        param_env,
393                                        trait_ref,
394                                    );
395                                let Ok(Some(ImplSource::UserDefined(impl_data))) =
396                                    SelectionContext::new(self)
397                                        .select(&obligation.with(self.tcx, trait_ref))
398                                else {
399                                    return None;
400                                };
401                                Some(self.tcx.def_span(impl_data.impl_def_id))
402                            })
403                        })
404                        .flatten();
405
406                    let mut note_spans: MultiSpan = private_struct_span.into();
407                    if private_struct_span != DUMMY_SP {
408                        note_spans.push_span_label(private_struct_span, "in this struct");
409                    }
410                    if private_field_span != DUMMY_SP {
411                        note_spans.push_span_label(
412                            private_field_span,
413                            "if this field wasn't private, it would be accessible",
414                        );
415                    }
416                    if accessible_struct_span != DUMMY_SP {
417                        note_spans.push_span_label(
418                            accessible_struct_span,
419                            "this struct is accessible through auto-deref",
420                        );
421                    }
422                    if field_span != DUMMY_SP {
423                        note_spans
424                            .push_span_label(field_span, "this is the field that was accessed");
425                    }
426                    if let Some(deref_impl_span) = deref_impl_span
427                        && deref_impl_span != DUMMY_SP
428                    {
429                        note_spans.push_span_label(
430                            deref_impl_span,
431                            "the field was accessed through this `Deref`",
432                        );
433                    }
434
435                    err.span_note(
436                        note_spans,
437                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("there is a field `{0}` on `{1}` with type `{2}` but it is private; `{0}` from `{3}` was accessed through auto-deref instead",
                field_ident, private_base_ty, private_field_ty,
                deref_base_ty))
    })format!(
438                            "there is a field `{field_ident}` on `{private_base_ty}` with type `{private_field_ty}` but it is private; `{field_ident}` from `{deref_base_ty}` was accessed through auto-deref instead"
439                        ),
440                    );
441                }
442
443                // we finally get to the accessible field,
444                // so we can return early without checking the rest of the autoderef candidates
445                return;
446            }
447
448            private_candidate.get_or_insert((
449                deref_base_ty,
450                field_def.ty(self.tcx, args),
451                field_span,
452            ));
453        }
454    }
455
456    pub fn suggest_restricting_param_bound(
457        &self,
458        err: &mut Diag<'_>,
459        trait_pred: ty::PolyTraitPredicate<'tcx>,
460        associated_ty: Option<(&'static str, Ty<'tcx>)>,
461        mut body_id: LocalDefId,
462    ) {
463        if trait_pred.skip_binder().polarity != ty::PredicatePolarity::Positive {
464            return;
465        }
466
467        let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
468
469        let self_ty = trait_pred.skip_binder().self_ty();
470        let (param_ty, projection) = match *self_ty.kind() {
471            ty::Param(_) => (true, None),
472            ty::Alias(projection @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
473                (false, Some(projection))
474            }
475            _ => (false, None),
476        };
477
478        let mut finder = ParamFinder { .. };
479        finder.visit_binder(&trait_pred);
480
481        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
482        //        don't suggest `T: Sized + ?Sized`.
483        loop {
484            let node = self.tcx.hir_node_by_def_id(body_id);
485            match node {
486                hir::Node::Item(hir::Item {
487                    kind: hir::ItemKind::Trait(_, _, _, ident, generics, bounds, _),
488                    ..
489                }) if self_ty == self.tcx.types.self_param => {
490                    if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
491                    // Restricting `Self` for a single method.
492                    suggest_restriction(
493                        self.tcx,
494                        body_id,
495                        generics,
496                        "`Self`",
497                        err,
498                        None,
499                        projection,
500                        trait_pred,
501                        Some((&ident, bounds)),
502                    );
503                    return;
504                }
505
506                hir::Node::TraitItem(hir::TraitItem {
507                    generics,
508                    kind: hir::TraitItemKind::Fn(..),
509                    ..
510                }) if self_ty == self.tcx.types.self_param => {
511                    if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
512                    // Restricting `Self` for a single method.
513                    suggest_restriction(
514                        self.tcx, body_id, generics, "`Self`", err, None, projection, trait_pred,
515                        None,
516                    );
517                    return;
518                }
519
520                hir::Node::TraitItem(hir::TraitItem {
521                    generics,
522                    kind: hir::TraitItemKind::Fn(fn_sig, ..),
523                    ..
524                })
525                | hir::Node::ImplItem(hir::ImplItem {
526                    generics,
527                    kind: hir::ImplItemKind::Fn(fn_sig, ..),
528                    ..
529                })
530                | hir::Node::Item(hir::Item {
531                    kind: hir::ItemKind::Fn { sig: fn_sig, generics, .. },
532                    ..
533                }) if projection.is_some() => {
534                    // Missing restriction on associated type of type parameter (unmet projection).
535                    suggest_restriction(
536                        self.tcx,
537                        body_id,
538                        generics,
539                        "the associated type",
540                        err,
541                        Some(fn_sig),
542                        projection,
543                        trait_pred,
544                        None,
545                    );
546                    return;
547                }
548                hir::Node::Item(hir::Item {
549                    kind:
550                        hir::ItemKind::Trait(_, _, _, _, generics, ..)
551                        | hir::ItemKind::Impl(hir::Impl { generics, .. }),
552                    ..
553                }) if projection.is_some() => {
554                    // Missing restriction on associated type of type parameter (unmet projection).
555                    suggest_restriction(
556                        self.tcx,
557                        body_id,
558                        generics,
559                        "the associated type",
560                        err,
561                        None,
562                        projection,
563                        trait_pred,
564                        None,
565                    );
566                    return;
567                }
568
569                hir::Node::Item(hir::Item {
570                    kind:
571                        hir::ItemKind::Struct(_, generics, _)
572                        | hir::ItemKind::Enum(_, generics, _)
573                        | hir::ItemKind::Union(_, generics, _)
574                        | hir::ItemKind::Trait(_, _, _, _, generics, ..)
575                        | hir::ItemKind::Impl(hir::Impl { generics, .. })
576                        | hir::ItemKind::Fn { generics, .. }
577                        | hir::ItemKind::TyAlias(_, generics, _)
578                        | hir::ItemKind::Const(_, generics, _, _)
579                        | hir::ItemKind::TraitAlias(_, _, generics, _),
580                    ..
581                })
582                | hir::Node::TraitItem(hir::TraitItem { generics, .. })
583                | hir::Node::ImplItem(hir::ImplItem { generics, .. })
584                    if param_ty =>
585                {
586                    // We skip the 0'th arg (self) because we do not want
587                    // to consider the predicate as not suggestible if the
588                    // self type is an arg position `impl Trait` -- instead,
589                    // we handle that by adding ` + Bound` below.
590                    // FIXME(compiler-errors): It would be nice to do the same
591                    // this that we do in `suggest_restriction` and pull the
592                    // `impl Trait` into a new generic if it shows up somewhere
593                    // else in the predicate.
594                    if !trait_pred.skip_binder().trait_ref.args[1..]
595                        .iter()
596                        .all(|g| g.is_suggestable(self.tcx, false))
597                    {
598                        return;
599                    }
600                    // Missing generic type parameter bound.
601                    let param_name = self_ty.to_string();
602                    let mut constraint = {
    let _guard = NoTrimmedGuard::new();
    trait_pred.print_modifiers_and_trait_path().to_string()
}with_no_trimmed_paths!(
603                        trait_pred.print_modifiers_and_trait_path().to_string()
604                    );
605
606                    if let Some((name, term)) = associated_ty {
607                        // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
608                        // That should be extracted into a helper function.
609                        if let Some(stripped) = constraint.strip_suffix('>') {
610                            constraint = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, {1} = {2}>", stripped, name,
                term))
    })format!("{stripped}, {name} = {term}>");
611                        } else {
612                            constraint.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} = {1}>", name, term))
    })format!("<{name} = {term}>"));
613                        }
614                    }
615
616                    if suggest_constraining_type_param(
617                        self.tcx,
618                        generics,
619                        err,
620                        &param_name,
621                        &constraint,
622                        Some(trait_pred.def_id()),
623                        None,
624                    ) {
625                        return;
626                    }
627                }
628
629                hir::Node::TraitItem(hir::TraitItem {
630                    generics,
631                    kind: hir::TraitItemKind::Fn(..),
632                    ..
633                })
634                | hir::Node::ImplItem(hir::ImplItem {
635                    generics,
636                    impl_kind: hir::ImplItemImplKind::Inherent { .. },
637                    kind: hir::ImplItemKind::Fn(..),
638                    ..
639                }) if finder.can_suggest_bound(generics) => {
640                    // Missing generic type parameter bound.
641                    suggest_arbitrary_trait_bound(
642                        self.tcx,
643                        generics,
644                        err,
645                        trait_pred,
646                        associated_ty,
647                    );
648                }
649                hir::Node::Item(hir::Item {
650                    kind:
651                        hir::ItemKind::Struct(_, generics, _)
652                        | hir::ItemKind::Enum(_, generics, _)
653                        | hir::ItemKind::Union(_, generics, _)
654                        | hir::ItemKind::Trait(_, _, _, _, generics, ..)
655                        | hir::ItemKind::Impl(hir::Impl { generics, .. })
656                        | hir::ItemKind::Fn { generics, .. }
657                        | hir::ItemKind::TyAlias(_, generics, _)
658                        | hir::ItemKind::Const(_, generics, _, _)
659                        | hir::ItemKind::TraitAlias(_, _, generics, _),
660                    ..
661                }) if finder.can_suggest_bound(generics) => {
662                    // Missing generic type parameter bound.
663                    if suggest_arbitrary_trait_bound(
664                        self.tcx,
665                        generics,
666                        err,
667                        trait_pred,
668                        associated_ty,
669                    ) {
670                        return;
671                    }
672                }
673                hir::Node::Crate(..) => return,
674
675                _ => {}
676            }
677            body_id = self.tcx.local_parent(body_id);
678        }
679    }
680
681    /// Provide a suggestion to dereference arguments to functions and binary operators, if that
682    /// would satisfy trait bounds.
683    pub(super) fn suggest_dereferences(
684        &self,
685        obligation: &PredicateObligation<'tcx>,
686        err: &mut Diag<'_>,
687        trait_pred: ty::PolyTraitPredicate<'tcx>,
688    ) -> bool {
689        let mut code = obligation.cause.code();
690        if let ObligationCauseCode::FunctionArg { arg_hir_id, call_hir_id, .. } = code
691            && let Some(typeck_results) = &self.typeck_results
692            && let hir::Node::Expr(expr) = self.tcx.hir_node(*arg_hir_id)
693            && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
694        {
695            // Suggest dereferencing the argument to a function/method call if possible
696
697            // Get the root obligation, since the leaf obligation we have may be unhelpful (#87437)
698            let mut real_trait_pred = trait_pred;
699            while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
700                code = parent_code;
701                if let Some(parent_trait_pred) = parent_trait_pred {
702                    real_trait_pred = parent_trait_pred;
703                }
704            }
705
706            // We `instantiate_bound_regions_with_erased` here because `make_subregion` does not handle
707            // `ReBound`, and we don't particularly care about the regions.
708            let real_ty = self.tcx.instantiate_bound_regions_with_erased(real_trait_pred.self_ty());
709            if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
710                return false;
711            }
712
713            // Potentially, we'll want to place our dereferences under a `&`. We don't try this for
714            // `&mut`, since we can't be sure users will get the side-effects they want from it.
715            // If this doesn't work, we'll try removing the `&` in `suggest_remove_reference`.
716            // FIXME(dianne): this misses the case where users need both to deref and remove `&`s.
717            // This method could be combined with `TypeErrCtxt::suggest_remove_reference` to handle
718            // that, similar to what `FnCtxt::suggest_deref_or_ref` does.
719            let (is_under_ref, base_ty, span) = match expr.kind {
720                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, subexpr)
721                    if let &ty::Ref(region, base_ty, hir::Mutability::Not) = real_ty.kind() =>
722                {
723                    (Some(region), base_ty, subexpr.span)
724                }
725                // Don't suggest `*&mut`, etc.
726                hir::ExprKind::AddrOf(..) => return false,
727                _ => (None, real_ty, obligation.cause.span),
728            };
729
730            let autoderef = (self.autoderef_steps)(base_ty);
731            let mut is_boxed = base_ty.is_box();
732            if let Some(steps) = autoderef.into_iter().position(|(mut ty, obligations)| {
733                // Ensure one of the following for dereferencing to be valid: we're passing by
734                // reference, `ty` is `Copy`, or we're moving out of a (potentially nested) `Box`.
735                let can_deref = is_under_ref.is_some()
736                    || self.type_is_copy_modulo_regions(obligation.param_env, ty)
737                    || ty.is_numeric() // for inference vars (presumably but not provably `Copy`)
738                    || is_boxed && self.type_is_sized_modulo_regions(obligation.param_env, ty);
739                is_boxed &= ty.is_box();
740
741                // Re-add the `&` if necessary
742                if let Some(region) = is_under_ref {
743                    ty = Ty::new_ref(self.tcx, region, ty, hir::Mutability::Not);
744                }
745
746                // Remapping bound vars here
747                let real_trait_pred_and_ty =
748                    real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
749                let obligation = self.mk_trait_obligation_with_new_self_ty(
750                    obligation.param_env,
751                    real_trait_pred_and_ty,
752                );
753
754                can_deref
755                    && obligations
756                        .iter()
757                        .chain([&obligation])
758                        .all(|obligation| self.predicate_may_hold(obligation))
759            }) && steps > 0
760            {
761                if span.in_external_macro(self.tcx.sess.source_map()) {
762                    return false;
763                }
764                let derefs = "*".repeat(steps);
765                let msg = "consider dereferencing here";
766
767                let call_node = self.tcx.hir_node(*call_hir_id);
768                let is_receiver = #[allow(non_exhaustive_omitted_patterns)] match call_node {
    Node::Expr(hir::Expr {
        kind: hir::ExprKind::MethodCall(_, receiver_expr, ..), .. }) if
        receiver_expr.hir_id == *arg_hir_id => true,
    _ => false,
}matches!(
769                    call_node,
770                    Node::Expr(hir::Expr {
771                        kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
772                        ..
773                    })
774                    if receiver_expr.hir_id == *arg_hir_id
775                );
776                if is_receiver {
777                    err.multipart_suggestion(
778                        msg,
779                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("({0}", derefs))
                        })), (span.shrink_to_hi(), ")".to_string())]))vec![
780                            (span.shrink_to_lo(), format!("({derefs}")),
781                            (span.shrink_to_hi(), ")".to_string()),
782                        ],
783                        Applicability::MachineApplicable,
784                    )
785                } else {
786                    err.span_suggestion_verbose(
787                        span.shrink_to_lo(),
788                        msg,
789                        derefs,
790                        Applicability::MachineApplicable,
791                    )
792                };
793                return true;
794            }
795        } else if let (
796            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. },
797            predicate,
798        ) = code.peel_derives_with_predicate()
799            && let Some(typeck_results) = &self.typeck_results
800            && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id)
801            && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id)
802            && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs)
803            && let trait_pred = predicate.unwrap_or(trait_pred)
804            // Only run this code on binary operators
805            && hir::lang_items::BINARY_OPERATORS
806                .iter()
807                .filter_map(|&op| self.tcx.lang_items().get(op))
808                .any(|op| {
809                    op == trait_pred.skip_binder().trait_ref.def_id
810                })
811        {
812            // Suggest dereferencing the LHS, RHS, or both terms of a binop if possible
813            let trait_pred = predicate.unwrap_or(trait_pred);
814            let lhs_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
815            let lhs_autoderef = (self.autoderef_steps)(lhs_ty);
816            let rhs_autoderef = (self.autoderef_steps)(rhs_ty);
817            let first_lhs = lhs_autoderef.first().unwrap().clone();
818            let first_rhs = rhs_autoderef.first().unwrap().clone();
819            let mut autoderefs = lhs_autoderef
820                .into_iter()
821                .enumerate()
822                .rev()
823                .zip_longest(rhs_autoderef.into_iter().enumerate().rev())
824                .map(|t| match t {
825                    EitherOrBoth::Both(a, b) => (a, b),
826                    EitherOrBoth::Left(a) => (a, (0, first_rhs.clone())),
827                    EitherOrBoth::Right(b) => ((0, first_lhs.clone()), b),
828                })
829                .rev();
830            if let Some((lsteps, rsteps)) =
831                autoderefs.find_map(|((lsteps, (l_ty, _)), (rsteps, (r_ty, _)))| {
832                    // Create a new predicate with the dereferenced LHS and RHS
833                    // We simultaneously dereference both sides rather than doing them
834                    // one at a time to account for cases such as &Box<T> == &&T
835                    let trait_pred_and_ty = trait_pred.map_bound(|inner| {
836                        (
837                            ty::TraitPredicate {
838                                trait_ref: ty::TraitRef::new_from_args(
839                                    self.tcx,
840                                    inner.trait_ref.def_id,
841                                    self.tcx.mk_args(
842                                        &[&[l_ty.into(), r_ty.into()], &inner.trait_ref.args[2..]]
843                                            .concat(),
844                                    ),
845                                ),
846                                ..inner
847                            },
848                            l_ty,
849                        )
850                    });
851                    let obligation = self.mk_trait_obligation_with_new_self_ty(
852                        obligation.param_env,
853                        trait_pred_and_ty,
854                    );
855                    self.predicate_may_hold(&obligation).then_some(match (lsteps, rsteps) {
856                        (_, 0) => (Some(lsteps), None),
857                        (0, _) => (None, Some(rsteps)),
858                        _ => (Some(lsteps), Some(rsteps)),
859                    })
860                })
861            {
862                let make_sugg = |mut expr: &Expr<'_>, mut steps| {
863                    if expr.span.in_external_macro(self.tcx.sess.source_map()) {
864                        return None;
865                    }
866                    let mut prefix_span = expr.span.shrink_to_lo();
867                    let mut msg = "consider dereferencing here";
868                    if let hir::ExprKind::AddrOf(_, _, inner) = expr.kind {
869                        msg = "consider removing the borrow and dereferencing instead";
870                        if let hir::ExprKind::AddrOf(..) = inner.kind {
871                            msg = "consider removing the borrows and dereferencing instead";
872                        }
873                    }
874                    while let hir::ExprKind::AddrOf(_, _, inner) = expr.kind
875                        && steps > 0
876                    {
877                        prefix_span = prefix_span.with_hi(inner.span.lo());
878                        expr = inner;
879                        steps -= 1;
880                    }
881                    // Empty suggestions with empty spans ICE with debug assertions
882                    if steps == 0 {
883                        return Some((
884                            msg.trim_end_matches(" and dereferencing instead"),
885                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(prefix_span, String::new())]))vec![(prefix_span, String::new())],
886                        ));
887                    }
888                    let derefs = "*".repeat(steps);
889                    let needs_parens = steps > 0 && expr_needs_parens(expr);
890                    let mut suggestion = if needs_parens {
891                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}(", derefs))
                        })), (expr.span.shrink_to_hi(), ")".to_string())]))vec![
892                            (
893                                expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
894                                format!("{derefs}("),
895                            ),
896                            (expr.span.shrink_to_hi(), ")".to_string()),
897                        ]
898                    } else {
899                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}", derefs))
                        }))]))vec![(
900                            expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
901                            format!("{derefs}"),
902                        )]
903                    };
904                    // Empty suggestions with empty spans ICE with debug assertions
905                    if !prefix_span.is_empty() {
906                        suggestion.push((prefix_span, String::new()));
907                    }
908                    Some((msg, suggestion))
909                };
910
911                if let Some(lsteps) = lsteps
912                    && let Some(rsteps) = rsteps
913                    && lsteps > 0
914                    && rsteps > 0
915                {
916                    let Some((_, mut suggestion)) = make_sugg(lhs, lsteps) else {
917                        return false;
918                    };
919                    let Some((_, mut rhs_suggestion)) = make_sugg(rhs, rsteps) else {
920                        return false;
921                    };
922                    suggestion.append(&mut rhs_suggestion);
923                    err.multipart_suggestion(
924                        "consider dereferencing both sides of the expression",
925                        suggestion,
926                        Applicability::MachineApplicable,
927                    );
928                    return true;
929                } else if let Some(lsteps) = lsteps
930                    && lsteps > 0
931                {
932                    let Some((msg, suggestion)) = make_sugg(lhs, lsteps) else {
933                        return false;
934                    };
935                    err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
936                    return true;
937                } else if let Some(rsteps) = rsteps
938                    && rsteps > 0
939                {
940                    let Some((msg, suggestion)) = make_sugg(rhs, rsteps) else {
941                        return false;
942                    };
943                    err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
944                    return true;
945                }
946            }
947        }
948        false
949    }
950
951    /// Given a closure's `DefId`, return the given name of the closure.
952    ///
953    /// This doesn't account for reassignments, but it's only used for suggestions.
954    fn get_closure_name(
955        &self,
956        def_id: DefId,
957        err: &mut Diag<'_>,
958        msg: Cow<'static, str>,
959    ) -> Option<Symbol> {
960        let get_name = |err: &mut Diag<'_>, kind: &hir::PatKind<'_>| -> Option<Symbol> {
961            // Get the local name of this closure. This can be inaccurate because
962            // of the possibility of reassignment, but this should be good enough.
963            match &kind {
964                hir::PatKind::Binding(hir::BindingMode::NONE, _, ident, None) => Some(ident.name),
965                _ => {
966                    err.note(msg);
967                    None
968                }
969            }
970        };
971
972        let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?);
973        match self.tcx.parent_hir_node(hir_id) {
974            hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => {
975                get_name(err, &local.pat.kind)
976            }
977            // Different to previous arm because one is `&hir::Local` and the other
978            // is `Box<hir::Local>`.
979            hir::Node::LetStmt(local) => get_name(err, &local.pat.kind),
980            _ => None,
981        }
982    }
983
984    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
985    /// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling
986    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
987    pub(super) fn suggest_fn_call(
988        &self,
989        obligation: &PredicateObligation<'tcx>,
990        err: &mut Diag<'_>,
991        trait_pred: ty::PolyTraitPredicate<'tcx>,
992    ) -> bool {
993        // It doesn't make sense to make this suggestion outside of typeck...
994        // (also autoderef will ICE...)
995        if self.typeck_results.is_none() {
996            return false;
997        }
998
999        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
1000            obligation.predicate.kind().skip_binder()
1001            && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
1002        {
1003            // Don't suggest calling to turn an unsized type into a sized type
1004            return false;
1005        }
1006
1007        let self_ty = self.instantiate_binder_with_fresh_vars(
1008            DUMMY_SP,
1009            BoundRegionConversionTime::FnCall,
1010            trait_pred.self_ty(),
1011        );
1012
1013        let Some((def_id_or_name, output, inputs)) =
1014            self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty)
1015        else {
1016            return false;
1017        };
1018
1019        // Remapping bound vars here
1020        let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
1021
1022        let new_obligation =
1023            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
1024        if !self.predicate_must_hold_modulo_regions(&new_obligation) {
1025            return false;
1026        }
1027
1028        // If this is a zero-argument async closure directly passed as an argument
1029        // and the expected type is `Future`, suggest using `async {}` block instead
1030        // of `async || {}`
1031        if let ty::CoroutineClosure(def_id, args) = *self_ty.kind()
1032            && let sig = args.as_coroutine_closure().coroutine_closure_sig().skip_binder()
1033            && let ty::Tuple(inputs) = *sig.tupled_inputs_ty.kind()
1034            && inputs.is_empty()
1035            && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Future)
1036            && let Some(hir::Node::Expr(hir::Expr {
1037                kind:
1038                    hir::ExprKind::Closure(hir::Closure {
1039                        kind: hir::ClosureKind::CoroutineClosure(CoroutineDesugaring::Async),
1040                        fn_arg_span: Some(arg_span),
1041                        ..
1042                    }),
1043                ..
1044            })) = self.tcx.hir_get_if_local(def_id)
1045            && obligation.cause.span.contains(*arg_span)
1046        {
1047            let sm = self.tcx.sess.source_map();
1048            let removal_span = if let Ok(snippet) =
1049                sm.span_to_snippet(arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1)))
1050                && snippet.ends_with(' ')
1051            {
1052                // There's a space after `||`, include it in the removal
1053                arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1))
1054            } else {
1055                *arg_span
1056            };
1057            err.span_suggestion_verbose(
1058                removal_span,
1059                "use `async {}` instead of `async || {}` to introduce an async block",
1060                "",
1061                Applicability::MachineApplicable,
1062            );
1063            return true;
1064        }
1065
1066        // Get the name of the callable and the arguments to be used in the suggestion.
1067        let msg = match def_id_or_name {
1068            DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
1069                DefKind::Ctor(CtorOf::Struct, _) => {
1070                    Cow::from("use parentheses to construct this tuple struct")
1071                }
1072                DefKind::Ctor(CtorOf::Variant, _) => {
1073                    Cow::from("use parentheses to construct this tuple variant")
1074                }
1075                kind => Cow::from(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use parentheses to call this {0}",
                self.tcx.def_kind_descr(kind, def_id)))
    })format!(
1076                    "use parentheses to call this {}",
1077                    self.tcx.def_kind_descr(kind, def_id)
1078                )),
1079            },
1080            DefIdOrName::Name(name) => Cow::from(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use parentheses to call this {0}",
                name))
    })format!("use parentheses to call this {name}")),
1081        };
1082
1083        let args = inputs
1084            .into_iter()
1085            .map(|ty| {
1086                if ty.is_suggestable(self.tcx, false) {
1087                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", ty))
    })format!("/* {ty} */")
1088                } else {
1089                    "/* value */".to_string()
1090                }
1091            })
1092            .collect::<Vec<_>>()
1093            .join(", ");
1094
1095        if #[allow(non_exhaustive_omitted_patterns)] match obligation.cause.code() {
    ObligationCauseCode::FunctionArg { .. } => true,
    _ => false,
}matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. })
1096            && obligation.cause.span.can_be_used_for_suggestions()
1097        {
1098            let (span, sugg) = if let Some(snippet) =
1099                self.tcx.sess.source_map().span_to_snippet(obligation.cause.span).ok()
1100                && snippet.starts_with("|")
1101            {
1102                (obligation.cause.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0})({1})", snippet, args))
    })format!("({snippet})({args})"))
1103            } else {
1104                (obligation.cause.span.shrink_to_hi(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0})", args))
    })format!("({args})"))
1105            };
1106
1107            // When the obligation error has been ensured to have been caused by
1108            // an argument, the `obligation.cause.span` points at the expression
1109            // of the argument, so we can provide a suggestion. Otherwise, we give
1110            // a more general note.
1111            err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
1112        } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
1113            let name = match self.tcx.hir_get_if_local(def_id) {
1114                Some(hir::Node::Expr(hir::Expr {
1115                    kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
1116                    ..
1117                })) => {
1118                    err.span_label(*fn_decl_span, "consider calling this closure");
1119                    let Some(name) = self.get_closure_name(def_id, err, msg.clone()) else {
1120                        return false;
1121                    };
1122                    name.to_string()
1123                }
1124                Some(hir::Node::Item(hir::Item {
1125                    kind: hir::ItemKind::Fn { ident, .. }, ..
1126                })) => {
1127                    err.span_label(ident.span, "consider calling this function");
1128                    ident.to_string()
1129                }
1130                Some(hir::Node::Ctor(..)) => {
1131                    let name = self.tcx.def_path_str(def_id);
1132                    err.span_label(
1133                        self.tcx.def_span(def_id),
1134                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider calling the constructor for `{0}`",
                name))
    })format!("consider calling the constructor for `{name}`"),
1135                    );
1136                    name
1137                }
1138                _ => return false,
1139            };
1140            err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: `{1}({2})`", msg, name, args))
    })format!("{msg}: `{name}({args})`"));
1141        }
1142        true
1143    }
1144
1145    pub(super) fn check_for_binding_assigned_block_without_tail_expression(
1146        &self,
1147        obligation: &PredicateObligation<'tcx>,
1148        err: &mut Diag<'_>,
1149        trait_pred: ty::PolyTraitPredicate<'tcx>,
1150    ) {
1151        let mut span = obligation.cause.span;
1152        while span.from_expansion() {
1153            // Remove all the desugaring and macro contexts.
1154            span.remove_mark();
1155        }
1156        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
1157        let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
1158            return;
1159        };
1160        expr_finder.visit_expr(body.value);
1161        let Some(expr) = expr_finder.result else {
1162            return;
1163        };
1164        let Some(typeck) = &self.typeck_results else {
1165            return;
1166        };
1167        let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
1168            return;
1169        };
1170        if !ty.is_unit() {
1171            return;
1172        };
1173        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
1174            return;
1175        };
1176        let Res::Local(hir_id) = path.res else {
1177            return;
1178        };
1179        let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else {
1180            return;
1181        };
1182        let hir::Node::LetStmt(hir::LetStmt { ty: None, init: Some(init), .. }) =
1183            self.tcx.parent_hir_node(pat.hir_id)
1184        else {
1185            return;
1186        };
1187        let hir::ExprKind::Block(block, None) = init.kind else {
1188            return;
1189        };
1190        if block.expr.is_some() {
1191            return;
1192        }
1193        let [.., stmt] = block.stmts else {
1194            err.span_label(block.span, "this empty block is missing a tail expression");
1195            return;
1196        };
1197        // FIXME expr and stmt have the same span if expr comes from expansion
1198        // cc: https://github.com/rust-lang/rust/pull/147416#discussion_r2499407523
1199        if stmt.span.from_expansion() {
1200            return;
1201        }
1202        let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
1203            return;
1204        };
1205        let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
1206            err.span_label(block.span, "this block is missing a tail expression");
1207            return;
1208        };
1209        let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty));
1210        let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty));
1211
1212        let new_obligation =
1213            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
1214        if !#[allow(non_exhaustive_omitted_patterns)] match tail_expr.kind {
    hir::ExprKind::Err(_) => true,
    _ => false,
}matches!(tail_expr.kind, hir::ExprKind::Err(_))
1215            && self.predicate_must_hold_modulo_regions(&new_obligation)
1216        {
1217            err.span_suggestion_short(
1218                stmt.span.with_lo(tail_expr.span.hi()),
1219                "remove this semicolon",
1220                "",
1221                Applicability::MachineApplicable,
1222            );
1223        } else {
1224            err.span_label(block.span, "this block is missing a tail expression");
1225        }
1226    }
1227
1228    pub(super) fn suggest_add_clone_to_arg(
1229        &self,
1230        obligation: &PredicateObligation<'tcx>,
1231        err: &mut Diag<'_>,
1232        trait_pred: ty::PolyTraitPredicate<'tcx>,
1233    ) -> bool {
1234        let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
1235        self.enter_forall(self_ty, |ty: Ty<'_>| {
1236            let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else {
1237                return false;
1238            };
1239            let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
1240            let ty::Param(param) = inner_ty.kind() else { return false };
1241            let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
1242            else {
1243                return false;
1244            };
1245
1246            let clone_trait = self.tcx.require_lang_item(LangItem::Clone, obligation.cause.span);
1247            let has_clone = |ty| {
1248                self.type_implements_trait(clone_trait, [ty], obligation.param_env)
1249                    .must_apply_modulo_regions()
1250            };
1251
1252            let existing_clone_call = match self.tcx.hir_node(*arg_hir_id) {
1253                // It's just a variable. Propose cloning it.
1254                Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) => None,
1255                // It's already a call to `clone()`. We might be able to suggest
1256                // adding a `+ Clone` bound, though.
1257                Node::Expr(Expr {
1258                    kind:
1259                        hir::ExprKind::MethodCall(
1260                            hir::PathSegment { ident, .. },
1261                            _receiver,
1262                            [],
1263                            call_span,
1264                        ),
1265                    hir_id,
1266                    ..
1267                }) if ident.name == sym::clone
1268                    && !call_span.from_expansion()
1269                    && !has_clone(*inner_ty) =>
1270                {
1271                    // We only care about method calls corresponding to the real `Clone` trait.
1272                    let Some(typeck_results) = self.typeck_results.as_ref() else { return false };
1273                    let Some((DefKind::AssocFn, did)) = typeck_results.type_dependent_def(*hir_id)
1274                    else {
1275                        return false;
1276                    };
1277                    if self.tcx.trait_of_assoc(did) != Some(clone_trait) {
1278                        return false;
1279                    }
1280                    Some(ident.span)
1281                }
1282                _ => return false,
1283            };
1284
1285            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1286                obligation.param_env,
1287                trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
1288            );
1289
1290            if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
1291                if !has_clone(param.to_ty(self.tcx)) {
1292                    suggest_constraining_type_param(
1293                        self.tcx,
1294                        generics,
1295                        err,
1296                        param.name.as_str(),
1297                        "Clone",
1298                        Some(clone_trait),
1299                        None,
1300                    );
1301                }
1302                if let Some(existing_clone_call) = existing_clone_call {
1303                    err.span_note(
1304                        existing_clone_call,
1305                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this `clone()` copies the reference, which does not do anything, because `{0}` does not implement `Clone`",
                inner_ty))
    })format!(
1306                            "this `clone()` copies the reference, \
1307                            which does not do anything, \
1308                            because `{inner_ty}` does not implement `Clone`"
1309                        ),
1310                    );
1311                } else {
1312                    err.span_suggestion_verbose(
1313                        obligation.cause.span.shrink_to_hi(),
1314                        "consider using clone here",
1315                        ".clone()".to_string(),
1316                        Applicability::MaybeIncorrect,
1317                    );
1318                }
1319                return true;
1320            }
1321            false
1322        })
1323    }
1324
1325    /// Extracts information about a callable type for diagnostics. This is a
1326    /// heuristic -- it doesn't necessarily mean that a type is always callable,
1327    /// because the callable type must also be well-formed to be called.
1328    pub fn extract_callable_info(
1329        &self,
1330        body_id: LocalDefId,
1331        param_env: ty::ParamEnv<'tcx>,
1332        found: Ty<'tcx>,
1333    ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
1334        // Autoderef is useful here because sometimes we box callables, etc.
1335        let Some((def_id_or_name, output, inputs)) =
1336            (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| match *found.kind() {
1337                ty::FnPtr(sig_tys, _) => Some((
1338                    DefIdOrName::Name("function pointer"),
1339                    sig_tys.output(),
1340                    sig_tys.inputs(),
1341                )),
1342                ty::FnDef(def_id, _) => {
1343                    let fn_sig = found.fn_sig(self.tcx);
1344                    Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
1345                }
1346                ty::Closure(def_id, args) => {
1347                    let fn_sig = args.as_closure().sig();
1348                    Some((
1349                        DefIdOrName::DefId(def_id),
1350                        fn_sig.output(),
1351                        fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()),
1352                    ))
1353                }
1354                ty::CoroutineClosure(def_id, args) => {
1355                    let sig_parts = args.as_coroutine_closure().coroutine_closure_sig();
1356                    Some((
1357                        DefIdOrName::DefId(def_id),
1358                        sig_parts.map_bound(|sig| {
1359                            sig.to_coroutine(
1360                                self.tcx,
1361                                args.as_coroutine_closure().parent_args(),
1362                                // Just use infer vars here, since we  don't really care
1363                                // what these types are, just that we're returning a coroutine.
1364                                self.next_ty_var(DUMMY_SP),
1365                                self.tcx.coroutine_for_closure(def_id),
1366                                self.next_ty_var(DUMMY_SP),
1367                            )
1368                        }),
1369                        sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()),
1370                    ))
1371                }
1372                ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
1373                    self.tcx.item_self_bounds(def_id).instantiate(self.tcx, args).iter().find_map(
1374                        |pred| {
1375                            if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
1376                            && self
1377                                .tcx
1378                                .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput)
1379                            // args tuple will always be args[1]
1380                            && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1381                            {
1382                                Some((
1383                                    DefIdOrName::DefId(def_id),
1384                                    pred.kind().rebind(proj.term.expect_type()),
1385                                    pred.kind().rebind(args.as_slice()),
1386                                ))
1387                            } else {
1388                                None
1389                            }
1390                        },
1391                    )
1392                }
1393                ty::Dynamic(data, _) => data.iter().find_map(|pred| {
1394                    if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
1395                        && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput)
1396                        // for existential projection, args are shifted over by 1
1397                        && let ty::Tuple(args) = proj.args.type_at(0).kind()
1398                    {
1399                        Some((
1400                            DefIdOrName::Name("trait object"),
1401                            pred.rebind(proj.term.expect_type()),
1402                            pred.rebind(args.as_slice()),
1403                        ))
1404                    } else {
1405                        None
1406                    }
1407                }),
1408                ty::Param(param) => {
1409                    let generics = self.tcx.generics_of(body_id);
1410                    let name = if generics.count() > param.index as usize
1411                        && let def = generics.param_at(param.index as usize, self.tcx)
1412                        && #[allow(non_exhaustive_omitted_patterns)] match def.kind {
    ty::GenericParamDefKind::Type { .. } => true,
    _ => false,
}matches!(def.kind, ty::GenericParamDefKind::Type { .. })
1413                        && def.name == param.name
1414                    {
1415                        DefIdOrName::DefId(def.def_id)
1416                    } else {
1417                        DefIdOrName::Name("type parameter")
1418                    };
1419                    param_env.caller_bounds().iter().find_map(|pred| {
1420                        if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
1421                            && self
1422                                .tcx
1423                                .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput)
1424                            && proj.projection_term.self_ty() == found
1425                            // args tuple will always be args[1]
1426                            && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1427                        {
1428                            Some((
1429                                name,
1430                                pred.kind().rebind(proj.term.expect_type()),
1431                                pred.kind().rebind(args.as_slice()),
1432                            ))
1433                        } else {
1434                            None
1435                        }
1436                    })
1437                }
1438                _ => None,
1439            })
1440        else {
1441            return None;
1442        };
1443
1444        let output = self.instantiate_binder_with_fresh_vars(
1445            DUMMY_SP,
1446            BoundRegionConversionTime::FnCall,
1447            output,
1448        );
1449        let inputs = inputs
1450            .skip_binder()
1451            .iter()
1452            .map(|ty| {
1453                self.instantiate_binder_with_fresh_vars(
1454                    DUMMY_SP,
1455                    BoundRegionConversionTime::FnCall,
1456                    inputs.rebind(*ty),
1457                )
1458            })
1459            .collect();
1460
1461        // We don't want to register any extra obligations, which should be
1462        // implied by wf, but also because that would possibly result in
1463        // erroneous errors later on.
1464        let InferOk { value: output, obligations: _ } =
1465            self.at(&ObligationCause::dummy(), param_env).normalize(output);
1466
1467        if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
1468    }
1469
1470    pub(super) fn suggest_add_reference_to_arg(
1471        &self,
1472        obligation: &PredicateObligation<'tcx>,
1473        err: &mut Diag<'_>,
1474        poly_trait_pred: ty::PolyTraitPredicate<'tcx>,
1475        has_custom_message: bool,
1476    ) -> bool {
1477        let span = obligation.cause.span;
1478        let param_env = obligation.param_env;
1479
1480        let mk_result = |trait_pred_and_new_ty| {
1481            let obligation =
1482                self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
1483            self.predicate_must_hold_modulo_regions(&obligation)
1484        };
1485
1486        let code = match obligation.cause.code() {
1487            ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code,
1488            // FIXME(compiler-errors): This is kind of a mess, but required for obligations
1489            // that come from a path expr to affect the *call* expr.
1490            c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _)
1491                if self.tcx.hir_span(*hir_id).lo() == span.lo() =>
1492            {
1493                // `hir_id` corresponds to the HIR node that introduced a `where`-clause obligation.
1494                // If that obligation comes from a type in an associated method call, we need
1495                // special handling here.
1496                if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id)
1497                    && let hir::ExprKind::Call(base, _) = expr.kind
1498                    && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) = base.kind
1499                    && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id)
1500                    && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind
1501                    && ty.span == span
1502                {
1503                    // We've encountered something like `&str::from("")`, where the intended code
1504                    // was likely `<&str>::from("")`. The former is interpreted as "call method
1505                    // `from` on `str` and borrow the result", while the latter means "call method
1506                    // `from` on `&str`".
1507
1508                    let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| {
1509                        (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1510                    });
1511                    let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| {
1512                        (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1513                    });
1514
1515                    let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1516                    let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1517                    let sugg_msg = |pre: &str| {
1518                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you likely meant to call the associated function `{0}` for type `&{2}{1}`, but the code as written calls associated function `{0}` on type `{1}`",
                segment.ident, poly_trait_pred.self_ty(), pre))
    })format!(
1519                            "you likely meant to call the associated function `{FN}` for type \
1520                             `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \
1521                             type `{TY}`",
1522                            FN = segment.ident,
1523                            TY = poly_trait_pred.self_ty(),
1524                        )
1525                    };
1526                    match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) {
1527                        (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => {
1528                            err.multipart_suggestion(
1529                                sugg_msg(mtbl.prefix_str()),
1530                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(outer.span.shrink_to_lo(), "<".to_string()),
                (span.shrink_to_hi(), ">".to_string())]))vec![
1531                                    (outer.span.shrink_to_lo(), "<".to_string()),
1532                                    (span.shrink_to_hi(), ">".to_string()),
1533                                ],
1534                                Applicability::MachineApplicable,
1535                            );
1536                        }
1537                        (true, _, hir::Mutability::Mut) => {
1538                            // There's an associated function found on the immutable borrow of the
1539                            err.multipart_suggestion(
1540                                sugg_msg("mut "),
1541                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(outer.span.shrink_to_lo().until(span), "<&".to_string()),
                (span.shrink_to_hi(), ">".to_string())]))vec![
1542                                    (outer.span.shrink_to_lo().until(span), "<&".to_string()),
1543                                    (span.shrink_to_hi(), ">".to_string()),
1544                                ],
1545                                Applicability::MachineApplicable,
1546                            );
1547                        }
1548                        (_, true, hir::Mutability::Not) => {
1549                            err.multipart_suggestion(
1550                                sugg_msg(""),
1551                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(outer.span.shrink_to_lo().until(span), "<&mut ".to_string()),
                (span.shrink_to_hi(), ">".to_string())]))vec![
1552                                    (outer.span.shrink_to_lo().until(span), "<&mut ".to_string()),
1553                                    (span.shrink_to_hi(), ">".to_string()),
1554                                ],
1555                                Applicability::MachineApplicable,
1556                            );
1557                        }
1558                        _ => {}
1559                    }
1560                    // If we didn't return early here, we would instead suggest `&&str::from("")`.
1561                    return false;
1562                }
1563                c
1564            }
1565            c if #[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
    _ => false,
}matches!(
1566                span.ctxt().outer_expn_data().kind,
1567                ExpnKind::Desugaring(DesugaringKind::ForLoop)
1568            ) =>
1569            {
1570                c
1571            }
1572            _ => return false,
1573        };
1574
1575        // List of traits for which it would be nonsensical to suggest borrowing.
1576        // For instance, immutable references are always Copy, so suggesting to
1577        // borrow would always succeed, but it's probably not what the user wanted.
1578        let mut never_suggest_borrow: Vec<_> =
1579            [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
1580                .iter()
1581                .filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
1582                .collect();
1583
1584        if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
1585            never_suggest_borrow.push(def_id);
1586        }
1587
1588        // Try to apply the original trait bound by borrowing.
1589        let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
1590                                 blacklist: &[DefId]|
1591         -> bool {
1592            if blacklist.contains(&old_pred.def_id()) {
1593                return false;
1594            }
1595            // We map bounds to `&T` and `&mut T`
1596            let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
1597                (
1598                    trait_pred,
1599                    Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1600                )
1601            });
1602            let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
1603                (
1604                    trait_pred,
1605                    Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1606                )
1607            });
1608
1609            let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1610            let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1611
1612            let (ref_inner_ty_satisfies_pred, ref_inner_ty_is_mut) =
1613                if let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
1614                    && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
1615                {
1616                    (
1617                        mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
1618                        mutability.is_mut(),
1619                    )
1620                } else {
1621                    (false, false)
1622                };
1623
1624            let is_immut = imm_ref_self_ty_satisfies_pred
1625                || (ref_inner_ty_satisfies_pred && !ref_inner_ty_is_mut);
1626            let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_is_mut;
1627            if !is_immut && !is_mut {
1628                return false;
1629            }
1630            let Ok(_snippet) = self.tcx.sess.source_map().span_to_snippet(span) else {
1631                return false;
1632            };
1633            // We don't want a borrowing suggestion on the fields in structs
1634            // ```
1635            // #[derive(Clone)]
1636            // struct Foo {
1637            //     the_foos: Vec<Foo>
1638            // }
1639            // ```
1640            if !#[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
    _ => false,
}matches!(
1641                span.ctxt().outer_expn_data().kind,
1642                ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
1643            ) {
1644                return false;
1645            }
1646            // We have a very specific type of error, where just borrowing this argument
1647            // might solve the problem. In cases like this, the important part is the
1648            // original type obligation, not the last one that failed, which is arbitrary.
1649            // Because of this, we modify the error to refer to the original obligation and
1650            // return early in the caller.
1651
1652            let mut label = || {
1653                // Special case `Sized` as `old_pred` will be the trait itself instead of
1654                // `Sized` when the trait bound is the source of the error.
1655                let is_sized = match obligation.predicate.kind().skip_binder() {
1656                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
1657                        self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
1658                    }
1659                    _ => false,
1660                };
1661
1662                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the trait bound `{0}` is not satisfied",
                self.tcx.short_string(old_pred, err.long_ty_path())))
    })format!(
1663                    "the trait bound `{}` is not satisfied",
1664                    self.tcx.short_string(old_pred, err.long_ty_path()),
1665                );
1666                let self_ty_str = self.tcx.short_string(old_pred.self_ty(), err.long_ty_path());
1667                let trait_path = self
1668                    .tcx
1669                    .short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
1670
1671                if has_custom_message {
1672                    let msg = if is_sized {
1673                        "the trait bound `Sized` is not satisfied".into()
1674                    } else {
1675                        msg
1676                    };
1677                    err.note(msg);
1678                } else {
1679                    err.messages = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(rustc_errors::DiagMessage::from(msg), Style::NoStyle)]))vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
1680                }
1681                if is_sized {
1682                    err.span_label(
1683                        span,
1684                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the trait `Sized` is not implemented for `{0}`",
                self_ty_str))
    })format!("the trait `Sized` is not implemented for `{self_ty_str}`"),
1685                    );
1686                } else {
1687                    err.span_label(
1688                        span,
1689                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the trait `{0}` is not implemented for `{1}`",
                trait_path, self_ty_str))
    })format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
1690                    );
1691                }
1692            };
1693
1694            let mut sugg_prefixes = ::alloc::vec::Vec::new()vec![];
1695            if is_immut {
1696                sugg_prefixes.push("&");
1697            }
1698            if is_mut {
1699                sugg_prefixes.push("&mut ");
1700            }
1701            let sugg_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider{0} borrowing here",
                if is_mut && !is_immut { " mutably" } else { "" }))
    })format!(
1702                "consider{} borrowing here",
1703                if is_mut && !is_immut { " mutably" } else { "" },
1704            );
1705
1706            // Issue #104961, we need to add parentheses properly for compound expressions
1707            // for example, `x.starts_with("hi".to_string() + "you")`
1708            // should be `x.starts_with(&("hi".to_string() + "you"))`
1709            let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
1710                return false;
1711            };
1712            let mut expr_finder = FindExprBySpan::new(span, self.tcx);
1713            expr_finder.visit_expr(body.value);
1714
1715            if let Some(ty) = expr_finder.ty_result {
1716                if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(ty.hir_id)
1717                    && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, _)) = expr.kind
1718                    && ty.span == span
1719                {
1720                    // We've encountered something like `str::from("")`, where the intended code
1721                    // was likely `<&str>::from("")`. #143393.
1722                    label();
1723                    err.multipart_suggestions(
1724                        sugg_msg,
1725                        sugg_prefixes.into_iter().map(|sugg_prefix| {
1726                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("<{0}", sugg_prefix))
                        })), (span.shrink_to_hi(), ">".to_string())]))vec![
1727                                (span.shrink_to_lo(), format!("<{sugg_prefix}")),
1728                                (span.shrink_to_hi(), ">".to_string()),
1729                            ]
1730                        }),
1731                        Applicability::MaybeIncorrect,
1732                    );
1733                    return true;
1734                }
1735                return false;
1736            }
1737            let Some(expr) = expr_finder.result else {
1738                return false;
1739            };
1740            if let hir::ExprKind::AddrOf(_, _, _) = expr.kind {
1741                return false;
1742            }
1743            let needs_parens_post = expr_needs_parens(expr);
1744            let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) {
1745                Node::Expr(e)
1746                    if let hir::ExprKind::MethodCall(_, base, _, _) = e.kind
1747                        && base.hir_id == expr.hir_id =>
1748                {
1749                    true
1750                }
1751                _ => false,
1752            };
1753
1754            label();
1755            let suggestions = sugg_prefixes.into_iter().map(|sugg_prefix| {
1756                match (needs_parens_pre, needs_parens_post) {
1757                    (false, false) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), sugg_prefix.to_string())]))vec![(span.shrink_to_lo(), sugg_prefix.to_string())],
1758                    // We have something like `foo.bar()`, where we want to bororw foo, so we need
1759                    // to suggest `(&mut foo).bar()`.
1760                    (false, true) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}(", sugg_prefix))
                        })), (span.shrink_to_hi(), ")".to_string())]))vec![
1761                        (span.shrink_to_lo(), format!("{sugg_prefix}(")),
1762                        (span.shrink_to_hi(), ")".to_string()),
1763                    ],
1764                    // Issue #109436, we need to add parentheses properly for method calls
1765                    // for example, `foo.into()` should be `(&foo).into()`
1766                    (true, false) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("({0}", sugg_prefix))
                        })), (span.shrink_to_hi(), ")".to_string())]))vec![
1767                        (span.shrink_to_lo(), format!("({sugg_prefix}")),
1768                        (span.shrink_to_hi(), ")".to_string()),
1769                    ],
1770                    (true, true) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("({0}(", sugg_prefix))
                        })), (span.shrink_to_hi(), "))".to_string())]))vec![
1771                        (span.shrink_to_lo(), format!("({sugg_prefix}(")),
1772                        (span.shrink_to_hi(), "))".to_string()),
1773                    ],
1774                }
1775            });
1776            err.multipart_suggestions(sugg_msg, suggestions, Applicability::MaybeIncorrect);
1777            return true;
1778        };
1779
1780        if let ObligationCauseCode::ImplDerived(cause) = &*code {
1781            try_borrowing(cause.derived.parent_trait_pred, &[])
1782        } else if let ObligationCauseCode::WhereClause(..)
1783        | ObligationCauseCode::WhereClauseInExpr(..) = code
1784        {
1785            try_borrowing(poly_trait_pred, &never_suggest_borrow)
1786        } else {
1787            false
1788        }
1789    }
1790
1791    // Suggest borrowing the type
1792    pub(super) fn suggest_borrowing_for_object_cast(
1793        &self,
1794        err: &mut Diag<'_>,
1795        obligation: &PredicateObligation<'tcx>,
1796        self_ty: Ty<'tcx>,
1797        target_ty: Ty<'tcx>,
1798    ) {
1799        let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
1800            return;
1801        };
1802        let ty::Dynamic(predicates, _) = object_ty.kind() else {
1803            return;
1804        };
1805        let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
1806
1807        for predicate in predicates.iter() {
1808            if !self.predicate_must_hold_modulo_regions(
1809                &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
1810            ) {
1811                return;
1812            }
1813        }
1814
1815        err.span_suggestion_verbose(
1816            obligation.cause.span.shrink_to_lo(),
1817            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider borrowing the value, since `&{0}` can be coerced into `{1}`",
                self_ty, target_ty))
    })format!(
1818                "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
1819            ),
1820            "&",
1821            Applicability::MaybeIncorrect,
1822        );
1823    }
1824
1825    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
1826    /// suggest removing these references until we reach a type that implements the trait.
1827    pub(super) fn suggest_remove_reference(
1828        &self,
1829        obligation: &PredicateObligation<'tcx>,
1830        err: &mut Diag<'_>,
1831        trait_pred: ty::PolyTraitPredicate<'tcx>,
1832    ) -> bool {
1833        let mut span = obligation.cause.span;
1834        let mut trait_pred = trait_pred;
1835        let mut code = obligation.cause.code();
1836        while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
1837            // We want the root obligation, in order to detect properly handle
1838            // `for _ in &mut &mut vec![] {}`.
1839            code = c;
1840            trait_pred = parent_trait_pred;
1841        }
1842        while span.desugaring_kind().is_some() {
1843            // Remove all the hir desugaring contexts while maintaining the macro contexts.
1844            span.remove_mark();
1845        }
1846        let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
1847        let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
1848            return false;
1849        };
1850        expr_finder.visit_expr(body.value);
1851        let mut maybe_suggest = |suggested_ty, count, suggestions| {
1852            // Remapping bound vars here
1853            let trait_pred_and_suggested_ty =
1854                trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
1855
1856            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1857                obligation.param_env,
1858                trait_pred_and_suggested_ty,
1859            );
1860
1861            if self.predicate_may_hold(&new_obligation) {
1862                let msg = if count == 1 {
1863                    "consider removing the leading `&`-reference".to_string()
1864                } else {
1865                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider removing {0} leading `&`-references",
                count))
    })format!("consider removing {count} leading `&`-references")
1866                };
1867
1868                err.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable);
1869                true
1870            } else {
1871                false
1872            }
1873        };
1874
1875        // Maybe suggest removal of borrows from types in type parameters, like in
1876        // `src/test/ui/not-panic/not-panic-safe.rs`.
1877        let mut count = 0;
1878        let mut suggestions = ::alloc::vec::Vec::new()vec![];
1879        // Skipping binder here, remapping below
1880        let mut suggested_ty = trait_pred.self_ty().skip_binder();
1881        if let Some(mut hir_ty) = expr_finder.ty_result {
1882            while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
1883                count += 1;
1884                let span = hir_ty.span.until(mut_ty.ty.span);
1885                suggestions.push((span, String::new()));
1886
1887                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
1888                    break;
1889                };
1890                suggested_ty = *inner_ty;
1891
1892                hir_ty = mut_ty.ty;
1893
1894                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
1895                    return true;
1896                }
1897            }
1898        }
1899
1900        // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
1901        let Some(mut expr) = expr_finder.result else {
1902            return false;
1903        };
1904        let mut count = 0;
1905        let mut suggestions = ::alloc::vec::Vec::new()vec![];
1906        // Skipping binder here, remapping below
1907        let mut suggested_ty = trait_pred.self_ty().skip_binder();
1908        'outer: loop {
1909            while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
1910                count += 1;
1911                let span =
1912                    if let Some(borrowed_span) = borrowed.span.find_ancestor_inside(expr.span) {
1913                        expr.span.until(borrowed_span)
1914                    } else {
1915                        break 'outer;
1916                    };
1917
1918                // Double check that the span we extracted actually corresponds to a borrow,
1919                // rather than some macro garbage.
1920                match self.tcx.sess.source_map().span_to_snippet(span) {
1921                    Ok(snippet) if snippet.starts_with("&") => {}
1922                    _ => break 'outer,
1923                }
1924
1925                suggestions.push((span, String::new()));
1926
1927                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
1928                    break 'outer;
1929                };
1930                suggested_ty = *inner_ty;
1931
1932                expr = borrowed;
1933
1934                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
1935                    return true;
1936                }
1937            }
1938            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
1939                && let Res::Local(hir_id) = path.res
1940                && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id)
1941                && let hir::Node::LetStmt(local) = self.tcx.parent_hir_node(binding.hir_id)
1942                && let None = local.ty
1943                && let Some(binding_expr) = local.init
1944            {
1945                expr = binding_expr;
1946            } else {
1947                break 'outer;
1948            }
1949        }
1950        false
1951    }
1952
1953    pub(super) fn suggest_remove_await(
1954        &self,
1955        obligation: &PredicateObligation<'tcx>,
1956        err: &mut Diag<'_>,
1957    ) {
1958        if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives()
1959            && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
1960        {
1961            // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
1962            // and if not maybe suggest doing something else? If we kept the expression around we
1963            // could also check if it is an fn call (very likely) and suggest changing *that*, if
1964            // it is from the local crate.
1965
1966            // use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
1967            if let Some((_, hir::Node::Expr(await_expr))) = self.tcx.hir_parent_iter(*hir_id).nth(1)
1968                && let Some(expr_span) = expr.span.find_ancestor_inside_same_ctxt(await_expr.span)
1969            {
1970                let removal_span = self
1971                    .tcx
1972                    .sess
1973                    .source_map()
1974                    .span_extend_while_whitespace(expr_span)
1975                    .shrink_to_hi()
1976                    .to(await_expr.span.shrink_to_hi());
1977                err.span_suggestion_verbose(
1978                    removal_span,
1979                    "remove the `.await`",
1980                    "",
1981                    Applicability::MachineApplicable,
1982                );
1983            } else {
1984                err.span_label(obligation.cause.span, "remove the `.await`");
1985            }
1986            // FIXME: account for associated `async fn`s.
1987            if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
1988                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
1989                    obligation.predicate.kind().skip_binder()
1990                {
1991                    err.span_label(*span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this call returns `{0}`",
                pred.self_ty()))
    })format!("this call returns `{}`", pred.self_ty()));
1992                }
1993                if let Some(typeck_results) = &self.typeck_results
1994                    && let ty = typeck_results.expr_ty_adjusted(base)
1995                    && let ty::FnDef(def_id, _args) = ty.kind()
1996                    && let Some(hir::Node::Item(item)) = self.tcx.hir_get_if_local(*def_id)
1997                {
1998                    let (ident, _, _, _) = item.expect_fn();
1999                    let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("alternatively, consider making `fn {0}` asynchronous",
                ident))
    })format!("alternatively, consider making `fn {ident}` asynchronous");
2000                    if item.vis_span.is_empty() {
2001                        err.span_suggestion_verbose(
2002                            item.span.shrink_to_lo(),
2003                            msg,
2004                            "async ",
2005                            Applicability::MaybeIncorrect,
2006                        );
2007                    } else {
2008                        err.span_suggestion_verbose(
2009                            item.vis_span.shrink_to_hi(),
2010                            msg,
2011                            " async",
2012                            Applicability::MaybeIncorrect,
2013                        );
2014                    }
2015                }
2016            }
2017        }
2018    }
2019
2020    /// Check if the trait bound is implemented for a different mutability and note it in the
2021    /// final error.
2022    pub(super) fn suggest_change_mut(
2023        &self,
2024        obligation: &PredicateObligation<'tcx>,
2025        err: &mut Diag<'_>,
2026        trait_pred: ty::PolyTraitPredicate<'tcx>,
2027    ) {
2028        let points_at_arg =
2029            #[allow(non_exhaustive_omitted_patterns)] match obligation.cause.code() {
    ObligationCauseCode::FunctionArg { .. } => true,
    _ => false,
}matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. },);
2030
2031        let span = obligation.cause.span;
2032        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
2033            let refs_number =
2034                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
2035            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
2036                // Do not suggest removal of borrow from type arguments.
2037                return;
2038            }
2039            let trait_pred = self.resolve_vars_if_possible(trait_pred);
2040            if trait_pred.has_non_region_infer() {
2041                // Do not ICE while trying to find if a reborrow would succeed on a trait with
2042                // unresolved bindings.
2043                return;
2044            }
2045
2046            // Skipping binder here, remapping below
2047            if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind()
2048            {
2049                let suggested_ty = match mutability {
2050                    hir::Mutability::Mut => Ty::new_imm_ref(self.tcx, region, t_type),
2051                    hir::Mutability::Not => Ty::new_mut_ref(self.tcx, region, t_type),
2052                };
2053
2054                // Remapping bound vars here
2055                let trait_pred_and_suggested_ty =
2056                    trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
2057
2058                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
2059                    obligation.param_env,
2060                    trait_pred_and_suggested_ty,
2061                );
2062                let suggested_ty_would_satisfy_obligation = self
2063                    .evaluate_obligation_no_overflow(&new_obligation)
2064                    .must_apply_modulo_regions();
2065                if suggested_ty_would_satisfy_obligation {
2066                    let sp = self
2067                        .tcx
2068                        .sess
2069                        .source_map()
2070                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
2071                    if points_at_arg && mutability.is_not() && refs_number > 0 {
2072                        // If we have a call like foo(&mut buf), then don't suggest foo(&mut mut buf)
2073                        if snippet
2074                            .trim_start_matches(|c: char| c.is_whitespace() || c == '&')
2075                            .starts_with("mut")
2076                        {
2077                            return;
2078                        }
2079                        err.span_suggestion_verbose(
2080                            sp,
2081                            "consider changing this borrow's mutability",
2082                            "&mut ",
2083                            Applicability::MachineApplicable,
2084                        );
2085                    } else {
2086                        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is implemented for `{1}`, but not for `{2}`",
                trait_pred.print_modifiers_and_trait_path(), suggested_ty,
                trait_pred.skip_binder().self_ty()))
    })format!(
2087                            "`{}` is implemented for `{}`, but not for `{}`",
2088                            trait_pred.print_modifiers_and_trait_path(),
2089                            suggested_ty,
2090                            trait_pred.skip_binder().self_ty(),
2091                        ));
2092                    }
2093                }
2094            }
2095        }
2096    }
2097
2098    pub(super) fn suggest_semicolon_removal(
2099        &self,
2100        obligation: &PredicateObligation<'tcx>,
2101        err: &mut Diag<'_>,
2102        span: Span,
2103        trait_pred: ty::PolyTraitPredicate<'tcx>,
2104    ) -> bool {
2105        let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
2106        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn {sig, body: body_id, .. }, .. }) = node
2107            && let hir::ExprKind::Block(blk, _) = &self.tcx.hir_body(*body_id).value.kind
2108            && sig.decl.output.span().overlaps(span)
2109            && blk.expr.is_none()
2110            && trait_pred.self_ty().skip_binder().is_unit()
2111            && let Some(stmt) = blk.stmts.last()
2112            && let hir::StmtKind::Semi(expr) = stmt.kind
2113            // Only suggest this if the expression behind the semicolon implements the predicate
2114            && let Some(typeck_results) = &self.typeck_results
2115            && let Some(ty) = typeck_results.expr_ty_opt(expr)
2116            && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(
2117                obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty))
2118            ))
2119        {
2120            err.span_label(
2121                expr.span,
2122                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this expression has type `{0}`, which implements `{1}`",
                ty, trait_pred.print_modifiers_and_trait_path()))
    })format!(
2123                    "this expression has type `{}`, which implements `{}`",
2124                    ty,
2125                    trait_pred.print_modifiers_and_trait_path()
2126                ),
2127            );
2128            err.span_suggestion(
2129                self.tcx.sess.source_map().end_point(stmt.span),
2130                "remove this semicolon",
2131                "",
2132                Applicability::MachineApplicable,
2133            );
2134            return true;
2135        }
2136        false
2137    }
2138
2139    pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
2140        let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig, .. }, .. }) =
2141            self.tcx.hir_node_by_def_id(obligation.cause.body_id)
2142        else {
2143            return None;
2144        };
2145
2146        if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
2147    }
2148
2149    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
2150    /// applicable and signal that the error has been expanded appropriately and needs to be
2151    /// emitted.
2152    pub(super) fn suggest_impl_trait(
2153        &self,
2154        err: &mut Diag<'_>,
2155        obligation: &PredicateObligation<'tcx>,
2156        trait_pred: ty::PolyTraitPredicate<'tcx>,
2157    ) -> bool {
2158        let ObligationCauseCode::SizedReturnType = obligation.cause.code() else {
2159            return false;
2160        };
2161        let ty::Dynamic(_, _) = trait_pred.self_ty().skip_binder().kind() else {
2162            return false;
2163        };
2164        if let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
2165        | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
2166        | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(fn_sig, _), .. }) =
2167            self.tcx.hir_node_by_def_id(obligation.cause.body_id)
2168            && let hir::FnRetTy::Return(ty) = fn_sig.decl.output
2169            && let hir::TyKind::Path(qpath) = ty.kind
2170            && let hir::QPath::Resolved(None, path) = qpath
2171            && let Res::Def(DefKind::TyAlias, def_id) = path.res
2172        {
2173            // Do not suggest
2174            // type T = dyn Trait;
2175            // fn foo() -> impl T { .. }
2176            err.span_note(self.tcx.def_span(def_id), "this type alias is unsized");
2177            err.multipart_suggestion(
2178                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider boxing the return type, and wrapping all of the returned values in `Box::new`"))
    })format!(
2179                    "consider boxing the return type, and wrapping all of the returned values in \
2180                    `Box::new`",
2181                ),
2182                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ty.span.shrink_to_lo(), "Box<".to_string()),
                (ty.span.shrink_to_hi(), ">".to_string())]))vec![
2183                    (ty.span.shrink_to_lo(), "Box<".to_string()),
2184                    (ty.span.shrink_to_hi(), ">".to_string()),
2185                ],
2186                Applicability::MaybeIncorrect,
2187            );
2188            return false;
2189        }
2190
2191        err.code(E0746);
2192        err.primary_message("return type cannot be a trait object without pointer indirection");
2193        err.children.clear();
2194
2195        let mut span = obligation.cause.span;
2196        if let DefKind::Closure = self.tcx.def_kind(obligation.cause.body_id)
2197            && let parent = self.tcx.local_parent(obligation.cause.body_id)
2198            && let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(parent)
2199            && self.tcx.asyncness(parent).is_async()
2200            && let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
2201            | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
2202            | Node::TraitItem(hir::TraitItem {
2203                kind: hir::TraitItemKind::Fn(fn_sig, _), ..
2204            }) = self.tcx.hir_node_by_def_id(parent)
2205        {
2206            // Do not suggest (#147894)
2207            // async fn foo() -> dyn Display impl { .. }
2208            // and
2209            // async fn foo() -> dyn Display Box<dyn { .. }>
2210            span = fn_sig.decl.output.span();
2211            err.span(span);
2212        }
2213        let body = self.tcx.hir_body_owned_by(obligation.cause.body_id);
2214
2215        let mut visitor = ReturnsVisitor::default();
2216        visitor.visit_body(&body);
2217
2218        let (pre, impl_span) = if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
2219            && snip.starts_with("dyn ")
2220        {
2221            ("", span.with_hi(span.lo() + BytePos(4)))
2222        } else {
2223            ("dyn ", span.shrink_to_lo())
2224        };
2225
2226        err.span_suggestion_verbose(
2227            impl_span,
2228            "consider returning an `impl Trait` instead of a `dyn Trait`",
2229            "impl ",
2230            Applicability::MaybeIncorrect,
2231        );
2232
2233        let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("Box<{0}", pre))
                        })), (span.shrink_to_hi(), ">".to_string())]))vec![
2234            (span.shrink_to_lo(), format!("Box<{pre}")),
2235            (span.shrink_to_hi(), ">".to_string()),
2236        ];
2237        sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
2238            let span =
2239                expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
2240            if !span.can_be_used_for_suggestions() {
2241                ::alloc::vec::Vec::new()vec![]
2242            } else if let hir::ExprKind::Call(path, ..) = expr.kind
2243                && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, method)) = path.kind
2244                && method.ident.name == sym::new
2245                && let hir::TyKind::Path(hir::QPath::Resolved(.., box_path)) = ty.kind
2246                && box_path
2247                    .res
2248                    .opt_def_id()
2249                    .is_some_and(|def_id| self.tcx.is_lang_item(def_id, LangItem::OwnedBox))
2250            {
2251                // Don't box `Box::new`
2252                ::alloc::vec::Vec::new()vec![]
2253            } else {
2254                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), "Box::new(".to_string()),
                (span.shrink_to_hi(), ")".to_string())]))vec![
2255                    (span.shrink_to_lo(), "Box::new(".to_string()),
2256                    (span.shrink_to_hi(), ")".to_string()),
2257                ]
2258            }
2259        }));
2260
2261        err.multipart_suggestion(
2262            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("alternatively, box the return type, and wrap all of the returned values in `Box::new`"))
    })format!(
2263                "alternatively, box the return type, and wrap all of the returned values in \
2264                 `Box::new`",
2265            ),
2266            sugg,
2267            Applicability::MaybeIncorrect,
2268        );
2269
2270        true
2271    }
2272
2273    pub(super) fn report_closure_arg_mismatch(
2274        &self,
2275        span: Span,
2276        found_span: Option<Span>,
2277        found: ty::TraitRef<'tcx>,
2278        expected: ty::TraitRef<'tcx>,
2279        cause: &ObligationCauseCode<'tcx>,
2280        found_node: Option<Node<'_>>,
2281        param_env: ty::ParamEnv<'tcx>,
2282    ) -> Diag<'a> {
2283        pub(crate) fn build_fn_sig_ty<'tcx>(
2284            infcx: &InferCtxt<'tcx>,
2285            trait_ref: ty::TraitRef<'tcx>,
2286        ) -> Ty<'tcx> {
2287            let inputs = trait_ref.args.type_at(1);
2288            let sig = match inputs.kind() {
2289                ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
2290                    infcx.tcx.mk_fn_sig(
2291                        *inputs,
2292                        infcx.next_ty_var(DUMMY_SP),
2293                        false,
2294                        hir::Safety::Safe,
2295                        ExternAbi::Rust,
2296                    )
2297                }
2298                _ => infcx.tcx.mk_fn_sig(
2299                    [inputs],
2300                    infcx.next_ty_var(DUMMY_SP),
2301                    false,
2302                    hir::Safety::Safe,
2303                    ExternAbi::Rust,
2304                ),
2305            };
2306
2307            Ty::new_fn_ptr(infcx.tcx, ty::Binder::dummy(sig))
2308        }
2309
2310        let argument_kind = match expected.self_ty().kind() {
2311            ty::Closure(..) => "closure",
2312            ty::Coroutine(..) => "coroutine",
2313            _ => "function",
2314        };
2315        let mut err = {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("type mismatch in {0} arguments",
                            argument_kind))
                })).with_code(E0631)
}struct_span_code_err!(
2316            self.dcx(),
2317            span,
2318            E0631,
2319            "type mismatch in {argument_kind} arguments",
2320        );
2321
2322        err.span_label(span, "expected due to this");
2323
2324        let found_span = found_span.unwrap_or(span);
2325        err.span_label(found_span, "found signature defined here");
2326
2327        let expected = build_fn_sig_ty(self, expected);
2328        let found = build_fn_sig_ty(self, found);
2329
2330        let (expected_str, found_str) = self.cmp(expected, found);
2331
2332        let signature_kind = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} signature", argument_kind))
    })format!("{argument_kind} signature");
2333        err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
2334
2335        self.note_conflicting_fn_args(&mut err, cause, expected, found, param_env);
2336        self.note_conflicting_closure_bounds(cause, &mut err);
2337
2338        if let Some(found_node) = found_node {
2339            hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
2340        }
2341
2342        err
2343    }
2344
2345    fn note_conflicting_fn_args(
2346        &self,
2347        err: &mut Diag<'_>,
2348        cause: &ObligationCauseCode<'tcx>,
2349        expected: Ty<'tcx>,
2350        found: Ty<'tcx>,
2351        param_env: ty::ParamEnv<'tcx>,
2352    ) {
2353        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else {
2354            return;
2355        };
2356        let ty::FnPtr(sig_tys, hdr) = expected.kind() else {
2357            return;
2358        };
2359        let expected = sig_tys.with(*hdr);
2360        let ty::FnPtr(sig_tys, hdr) = found.kind() else {
2361            return;
2362        };
2363        let found = sig_tys.with(*hdr);
2364        let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else {
2365            return;
2366        };
2367        let hir::ExprKind::Path(path) = arg.kind else {
2368            return;
2369        };
2370        let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(expected).inputs();
2371        let found_inputs = self.tcx.instantiate_bound_regions_with_erased(found).inputs();
2372        let both_tys = expected_inputs.iter().copied().zip(found_inputs.iter().copied());
2373
2374        let arg_expr = |infcx: &InferCtxt<'tcx>, name, expected: Ty<'tcx>, found: Ty<'tcx>| {
2375            let (expected_ty, expected_refs) = get_deref_type_and_refs(expected);
2376            let (found_ty, found_refs) = get_deref_type_and_refs(found);
2377
2378            if infcx.can_eq(param_env, found_ty, expected_ty) {
2379                if found_refs.len() == expected_refs.len()
2380                    && found_refs.iter().eq(expected_refs.iter())
2381                {
2382                    name
2383                } else if found_refs.len() > expected_refs.len() {
2384                    let refs = &found_refs[..found_refs.len() - expected_refs.len()];
2385                    if found_refs[..expected_refs.len()].iter().eq(expected_refs.iter()) {
2386                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                refs.iter().map(|mutbl|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("&{0}",
                                                mutbl.prefix_str()))
                                    })).collect::<Vec<_>>().join(""), name))
    })format!(
2387                            "{}{name}",
2388                            refs.iter()
2389                                .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2390                                .collect::<Vec<_>>()
2391                                .join(""),
2392                        )
2393                    } else {
2394                        // The refs have different mutability.
2395                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}*{1}",
                refs.iter().map(|mutbl|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("&{0}",
                                                mutbl.prefix_str()))
                                    })).collect::<Vec<_>>().join(""), name))
    })format!(
2396                            "{}*{name}",
2397                            refs.iter()
2398                                .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2399                                .collect::<Vec<_>>()
2400                                .join(""),
2401                        )
2402                    }
2403                } else if expected_refs.len() > found_refs.len() {
2404                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                (0..(expected_refs.len() -
                                            found_refs.len())).map(|_|
                                "*").collect::<Vec<_>>().join(""), name))
    })format!(
2405                        "{}{name}",
2406                        (0..(expected_refs.len() - found_refs.len()))
2407                            .map(|_| "*")
2408                            .collect::<Vec<_>>()
2409                            .join(""),
2410                    )
2411                } else {
2412                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                found_refs.iter().map(|mutbl|
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("&{0}",
                                                    mutbl.prefix_str()))
                                        })).chain(found_refs.iter().map(|_|
                                    "*".to_string())).collect::<Vec<_>>().join(""), name))
    })format!(
2413                        "{}{name}",
2414                        found_refs
2415                            .iter()
2416                            .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2417                            .chain(found_refs.iter().map(|_| "*".to_string()))
2418                            .collect::<Vec<_>>()
2419                            .join(""),
2420                    )
2421                }
2422            } else {
2423                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", found))
    })format!("/* {found} */")
2424            }
2425        };
2426        let args_have_same_underlying_type = both_tys.clone().all(|(expected, found)| {
2427            let (expected_ty, _) = get_deref_type_and_refs(expected);
2428            let (found_ty, _) = get_deref_type_and_refs(found);
2429            self.can_eq(param_env, found_ty, expected_ty)
2430        });
2431        let (closure_names, call_names): (Vec<_>, Vec<_>) = if args_have_same_underlying_type
2432            && !expected_inputs.is_empty()
2433            && expected_inputs.len() == found_inputs.len()
2434            && let Some(typeck) = &self.typeck_results
2435            && let Res::Def(res_kind, fn_def_id) = typeck.qpath_res(&path, *arg_hir_id)
2436            && res_kind.is_fn_like()
2437        {
2438            let closure: Vec<_> = self
2439                .tcx
2440                .fn_arg_idents(fn_def_id)
2441                .iter()
2442                .enumerate()
2443                .map(|(i, ident)| {
2444                    if let Some(ident) = ident
2445                        && !#[allow(non_exhaustive_omitted_patterns)] match ident {
    Ident { name: kw::Underscore | kw::SelfLower, .. } => true,
    _ => false,
}matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
2446                    {
2447                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", ident))
    })format!("{ident}")
2448                    } else {
2449                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}")
2450                    }
2451                })
2452                .collect();
2453            let args = closure
2454                .iter()
2455                .zip(both_tys)
2456                .map(|(name, (expected, found))| {
2457                    arg_expr(self.infcx, name.to_owned(), expected, found)
2458                })
2459                .collect();
2460            (closure, args)
2461        } else {
2462            let closure_args = expected_inputs
2463                .iter()
2464                .enumerate()
2465                .map(|(i, _)| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}"))
2466                .collect::<Vec<_>>();
2467            let call_args = both_tys
2468                .enumerate()
2469                .map(|(i, (expected, found))| {
2470                    arg_expr(self.infcx, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}"), expected, found)
2471                })
2472                .collect::<Vec<_>>();
2473            (closure_args, call_args)
2474        };
2475        let closure_names: Vec<_> = closure_names
2476            .into_iter()
2477            .zip(expected_inputs.iter())
2478            .map(|(name, ty)| {
2479                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}{0}",
                if ty.has_infer_types() {
                    String::new()
                } else if ty.references_error() {
                    ": /* type */".to_string()
                } else {
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(": {0}", ty))
                        })
                }, name))
    })format!(
2480                    "{name}{}",
2481                    if ty.has_infer_types() {
2482                        String::new()
2483                    } else if ty.references_error() {
2484                        ": /* type */".to_string()
2485                    } else {
2486                        format!(": {ty}")
2487                    }
2488                )
2489            })
2490            .collect();
2491        err.multipart_suggestion(
2492            "consider wrapping the function in a closure",
2493            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(arg.span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("|{0}| ",
                                    closure_names.join(", ")))
                        })),
                (arg.span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("({0})",
                                    call_names.join(", ")))
                        }))]))vec![
2494                (arg.span.shrink_to_lo(), format!("|{}| ", closure_names.join(", "))),
2495                (arg.span.shrink_to_hi(), format!("({})", call_names.join(", "))),
2496            ],
2497            Applicability::MaybeIncorrect,
2498        );
2499    }
2500
2501    // Add a note if there are two `Fn`-family bounds that have conflicting argument
2502    // requirements, which will always cause a closure to have a type error.
2503    fn note_conflicting_closure_bounds(
2504        &self,
2505        cause: &ObligationCauseCode<'tcx>,
2506        err: &mut Diag<'_>,
2507    ) {
2508        // First, look for an `WhereClauseInExpr`, which means we can get
2509        // the uninstantiated predicate list of the called function. And check
2510        // that the predicate that we failed to satisfy is a `Fn`-like trait.
2511        if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = *cause
2512            && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
2513            && let Some(pred) = predicates.predicates.get(idx)
2514            && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
2515            && self.tcx.is_fn_trait(trait_pred.def_id())
2516        {
2517            let expected_self =
2518                self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
2519            let expected_args =
2520                self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.args));
2521
2522            // Find another predicate whose self-type is equal to the expected self type,
2523            // but whose args don't match.
2524            let other_pred = predicates.into_iter().enumerate().find(|&(other_idx, (pred, _))| {
2525                match pred.kind().skip_binder() {
2526                    ty::ClauseKind::Trait(trait_pred)
2527                        if self.tcx.is_fn_trait(trait_pred.def_id())
2528                            && other_idx != idx
2529                            // Make sure that the self type matches
2530                            // (i.e. constraining this closure)
2531                            && expected_self
2532                                == self.tcx.anonymize_bound_vars(
2533                                    pred.kind().rebind(trait_pred.self_ty()),
2534                                )
2535                            // But the args don't match (i.e. incompatible args)
2536                            && expected_args
2537                                != self.tcx.anonymize_bound_vars(
2538                                    pred.kind().rebind(trait_pred.trait_ref.args),
2539                                ) =>
2540                    {
2541                        true
2542                    }
2543                    _ => false,
2544                }
2545            });
2546            // If we found one, then it's very likely the cause of the error.
2547            if let Some((_, (_, other_pred_span))) = other_pred {
2548                err.span_note(
2549                    other_pred_span,
2550                    "closure inferred to have a different signature due to this bound",
2551                );
2552            }
2553        }
2554    }
2555
2556    pub(super) fn suggest_fully_qualified_path(
2557        &self,
2558        err: &mut Diag<'_>,
2559        item_def_id: DefId,
2560        span: Span,
2561        trait_ref: DefId,
2562    ) {
2563        if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id)
2564            && let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind
2565        {
2566            err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}s cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`",
                self.tcx.def_kind_descr(assoc_item.as_def_kind(),
                    item_def_id)))
    })format!(
2567                "{}s cannot be accessed directly on a `trait`, they can only be \
2568                        accessed through a specific `impl`",
2569                self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
2570            ));
2571
2572            if !assoc_item.is_impl_trait_in_trait() {
2573                err.span_suggestion_verbose(
2574                    span,
2575                    "use the fully qualified path to an implementation",
2576                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<Type as {0}>::{1}",
                self.tcx.def_path_str(trait_ref), assoc_item.name()))
    })format!(
2577                        "<Type as {}>::{}",
2578                        self.tcx.def_path_str(trait_ref),
2579                        assoc_item.name()
2580                    ),
2581                    Applicability::HasPlaceholders,
2582                );
2583            }
2584        }
2585    }
2586
2587    /// Adds an async-await specific note to the diagnostic when the future does not implement
2588    /// an auto trait because of a captured type.
2589    ///
2590    /// ```text
2591    /// note: future does not implement `Qux` as this value is used across an await
2592    ///   --> $DIR/issue-64130-3-other.rs:17:5
2593    ///    |
2594    /// LL |     let x = Foo;
2595    ///    |         - has type `Foo`
2596    /// LL |     baz().await;
2597    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
2598    /// LL | }
2599    ///    | - `x` is later dropped here
2600    /// ```
2601    ///
2602    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
2603    /// is "replaced" with a different message and a more specific error.
2604    ///
2605    /// ```text
2606    /// error: future cannot be sent between threads safely
2607    ///   --> $DIR/issue-64130-2-send.rs:21:5
2608    ///    |
2609    /// LL | fn is_send<T: Send>(t: T) { }
2610    ///    |               ---- required by this bound in `is_send`
2611    /// ...
2612    /// LL |     is_send(bar());
2613    ///    |     ^^^^^^^ future returned by `bar` is not send
2614    ///    |
2615    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
2616    ///            implemented for `Foo`
2617    /// note: future is not send as this value is used across an await
2618    ///   --> $DIR/issue-64130-2-send.rs:15:5
2619    ///    |
2620    /// LL |     let x = Foo;
2621    ///    |         - has type `Foo`
2622    /// LL |     baz().await;
2623    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
2624    /// LL | }
2625    ///    | - `x` is later dropped here
2626    /// ```
2627    ///
2628    /// Returns `true` if an async-await specific note was added to the diagnostic.
2629    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("maybe_note_obligation_cause_for_async_await",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2629u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["obligation.predicate",
                                                    "obligation.cause.span"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&obligation.predicate)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&obligation.cause.span)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: bool = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let (mut trait_ref, mut target_ty) =
                match obligation.predicate.kind().skip_binder() {
                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) =>
                        (Some(p), Some(p.self_ty())),
                    _ => (None, None),
                };
            let mut coroutine = None;
            let mut outer_coroutine = None;
            let mut next_code = Some(obligation.cause.code());
            let mut seen_upvar_tys_infer_tuple = false;
            while let Some(code) = next_code {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2668",
                                        "rustc_trait_selection::error_reporting::traits::suggestions",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                        ::tracing_core::__macro_support::Option::Some(2668u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                        ::tracing_core::field::FieldSet::new(&["code"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = __CALLSITE.metadata().fields().iter();
                                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&code) as
                                                            &dyn Value))])
                            });
                    } else { ; }
                };
                match code {
                    ObligationCauseCode::FunctionArg { parent_code, .. } => {
                        next_code = Some(parent_code);
                    }
                    ObligationCauseCode::ImplDerived(cause) => {
                        let ty =
                            cause.derived.parent_trait_pred.skip_binder().self_ty();
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2675",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(2675u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&["message",
                                                                "parent_trait_ref", "self_ty.kind"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&format_args!("ImplDerived")
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&cause.derived.parent_trait_pred)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&ty.kind())
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        match *ty.kind() {
                            ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
                                coroutine = coroutine.or(Some(did));
                                outer_coroutine = Some(did);
                            }
                            ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
                                seen_upvar_tys_infer_tuple = true;
                            }
                            _ if coroutine.is_none() => {
                                trait_ref =
                                    Some(cause.derived.parent_trait_pred.skip_binder());
                                target_ty = Some(ty);
                            }
                            _ => {}
                        }
                        next_code = Some(&cause.derived.parent_code);
                    }
                    ObligationCauseCode::WellFormedDerived(derived_obligation) |
                        ObligationCauseCode::BuiltinDerived(derived_obligation) => {
                        let ty =
                            derived_obligation.parent_trait_pred.skip_binder().self_ty();
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2705",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(2705u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&["parent_trait_ref",
                                                                "self_ty.kind"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&derived_obligation.parent_trait_pred)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&ty.kind())
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        match *ty.kind() {
                            ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
                                coroutine = coroutine.or(Some(did));
                                outer_coroutine = Some(did);
                            }
                            ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
                                seen_upvar_tys_infer_tuple = true;
                            }
                            _ if coroutine.is_none() => {
                                trait_ref =
                                    Some(derived_obligation.parent_trait_pred.skip_binder());
                                target_ty = Some(ty);
                            }
                            _ => {}
                        }
                        next_code = Some(&derived_obligation.parent_code);
                    }
                    _ => break,
                }
            }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2736",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2736u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["coroutine",
                                                    "trait_ref", "target_ty"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&coroutine)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&trait_ref)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&target_ty)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
                (coroutine, trait_ref, target_ty) else { return false; };
            let span = self.tcx.def_span(coroutine_did);
            let coroutine_did_root =
                self.tcx.typeck_root_def_id(coroutine_did);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2746",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2746u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["coroutine_did",
                                                    "coroutine_did_root", "typeck_results.hir_owner", "span"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&coroutine_did)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&coroutine_did_root)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&self.typeck_results.as_ref().map(|t|
                                                                            t.hir_owner)) as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&span) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            let coroutine_body =
                coroutine_did.as_local().and_then(|def_id|
                        self.tcx.hir_maybe_body_owned_by(def_id));
            let mut visitor = AwaitsVisitor::default();
            if let Some(body) = coroutine_body { visitor.visit_body(&body); }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2759",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2759u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["awaits"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&visitor.awaits)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let target_ty_erased =
                self.tcx.erase_and_anonymize_regions(target_ty);
            let ty_matches =
                |ty| -> bool
                    {
                        let ty_erased =
                            self.tcx.instantiate_bound_regions_with_erased(ty);
                        let ty_erased =
                            self.tcx.erase_and_anonymize_regions(ty_erased);
                        let eq = ty_erased == target_ty_erased;
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2780",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(2780u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&["ty_erased",
                                                                "target_ty_erased", "eq"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&ty_erased)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&target_ty_erased)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&eq) as
                                                                    &dyn Value))])
                                    });
                            } else { ; }
                        };
                        eq
                    };
            let coroutine_data =
                match &self.typeck_results {
                    Some(t) if t.hir_owner.to_def_id() == coroutine_did_root =>
                        CoroutineData(t),
                    _ if coroutine_did.is_local() => {
                        CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
                    }
                    _ => return false,
                };
            let coroutine_within_in_progress_typeck =
                match &self.typeck_results {
                    Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
                    _ => false,
                };
            let mut interior_or_upvar_span = None;
            let from_awaited_ty =
                coroutine_data.get_from_await_ty(visitor, self.tcx,
                    ty_matches);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2804",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2804u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["from_awaited_ty"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&from_awaited_ty)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            if coroutine_did.is_local() &&
                        !coroutine_within_in_progress_typeck &&
                    let Some(coroutine_info) =
                        self.tcx.mir_coroutine_witnesses(coroutine_did) {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2812",
                                        "rustc_trait_selection::error_reporting::traits::suggestions",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                        ::tracing_core::__macro_support::Option::Some(2812u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                        ::tracing_core::field::FieldSet::new(&["coroutine_info"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = __CALLSITE.metadata().fields().iter();
                                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&coroutine_info)
                                                            as &dyn Value))])
                            });
                    } else { ; }
                };
                'find_source:
                    for (variant, source_info) in
                    coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
                    {
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2816",
                                            "rustc_trait_selection::error_reporting::traits::suggestions",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                            ::tracing_core::__macro_support::Option::Some(2816u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                            ::tracing_core::field::FieldSet::new(&["variant"],
                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&variant) as
                                                                &dyn Value))])
                                });
                        } else { ; }
                    };
                    for &local in variant {
                        let decl = &coroutine_info.field_tys[local];
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2819",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(2819u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&["decl"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&decl) as
                                                                    &dyn Value))])
                                    });
                            } else { ; }
                        };
                        if ty_matches(ty::Binder::dummy(decl.ty)) &&
                                !decl.ignore_for_traits {
                            interior_or_upvar_span =
                                Some(CoroutineInteriorOrUpvar::Interior(decl.source_info.span,
                                        Some((source_info.span, from_awaited_ty))));
                            break 'find_source;
                        }
                    }
                }
            }
            if interior_or_upvar_span.is_none() {
                interior_or_upvar_span =
                    coroutine_data.try_get_upvar_span(self, coroutine_did,
                        ty_matches);
            }
            if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
                interior_or_upvar_span =
                    Some(CoroutineInteriorOrUpvar::Interior(span, None));
            }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:2840",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2840u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["interior_or_upvar_span"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&interior_or_upvar_span)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            if let Some(interior_or_upvar_span) = interior_or_upvar_span {
                let is_async = self.tcx.coroutine_is_async(coroutine_did);
                self.note_obligation_cause_for_async_await(err,
                    interior_or_upvar_span, is_async, outer_coroutine,
                    trait_ref, target_ty, obligation, next_code);
                true
            } else { false }
        }
    }
}#[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
2630    pub fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
2631        &self,
2632        err: &mut Diag<'_, G>,
2633        obligation: &PredicateObligation<'tcx>,
2634    ) -> bool {
2635        // Attempt to detect an async-await error by looking at the obligation causes, looking
2636        // for a coroutine to be present.
2637        //
2638        // When a future does not implement a trait because of a captured type in one of the
2639        // coroutines somewhere in the call stack, then the result is a chain of obligations.
2640        //
2641        // Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
2642        // future is passed as an argument to a function C which requires a `Send` type, then the
2643        // chain looks something like this:
2644        //
2645        // - `BuiltinDerivedObligation` with a coroutine witness (B)
2646        // - `BuiltinDerivedObligation` with a coroutine (B)
2647        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
2648        // - `BuiltinDerivedObligation` with a coroutine witness (A)
2649        // - `BuiltinDerivedObligation` with a coroutine (A)
2650        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
2651        // - `BindingObligation` with `impl_send` (Send requirement)
2652        //
2653        // The first obligation in the chain is the most useful and has the coroutine that captured
2654        // the type. The last coroutine (`outer_coroutine` below) has information about where the
2655        // bound was introduced. At least one coroutine should be present for this diagnostic to be
2656        // modified.
2657        let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
2658            ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) => (Some(p), Some(p.self_ty())),
2659            _ => (None, None),
2660        };
2661        let mut coroutine = None;
2662        let mut outer_coroutine = None;
2663        let mut next_code = Some(obligation.cause.code());
2664
2665        let mut seen_upvar_tys_infer_tuple = false;
2666
2667        while let Some(code) = next_code {
2668            debug!(?code);
2669            match code {
2670                ObligationCauseCode::FunctionArg { parent_code, .. } => {
2671                    next_code = Some(parent_code);
2672                }
2673                ObligationCauseCode::ImplDerived(cause) => {
2674                    let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
2675                    debug!(
2676                        parent_trait_ref = ?cause.derived.parent_trait_pred,
2677                        self_ty.kind = ?ty.kind(),
2678                        "ImplDerived",
2679                    );
2680
2681                    match *ty.kind() {
2682                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
2683                            coroutine = coroutine.or(Some(did));
2684                            outer_coroutine = Some(did);
2685                        }
2686                        ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
2687                            // By introducing a tuple of upvar types into the chain of obligations
2688                            // of a coroutine, the first non-coroutine item is now the tuple itself,
2689                            // we shall ignore this.
2690
2691                            seen_upvar_tys_infer_tuple = true;
2692                        }
2693                        _ if coroutine.is_none() => {
2694                            trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
2695                            target_ty = Some(ty);
2696                        }
2697                        _ => {}
2698                    }
2699
2700                    next_code = Some(&cause.derived.parent_code);
2701                }
2702                ObligationCauseCode::WellFormedDerived(derived_obligation)
2703                | ObligationCauseCode::BuiltinDerived(derived_obligation) => {
2704                    let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
2705                    debug!(
2706                        parent_trait_ref = ?derived_obligation.parent_trait_pred,
2707                        self_ty.kind = ?ty.kind(),
2708                    );
2709
2710                    match *ty.kind() {
2711                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
2712                            coroutine = coroutine.or(Some(did));
2713                            outer_coroutine = Some(did);
2714                        }
2715                        ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
2716                            // By introducing a tuple of upvar types into the chain of obligations
2717                            // of a coroutine, the first non-coroutine item is now the tuple itself,
2718                            // we shall ignore this.
2719
2720                            seen_upvar_tys_infer_tuple = true;
2721                        }
2722                        _ if coroutine.is_none() => {
2723                            trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
2724                            target_ty = Some(ty);
2725                        }
2726                        _ => {}
2727                    }
2728
2729                    next_code = Some(&derived_obligation.parent_code);
2730                }
2731                _ => break,
2732            }
2733        }
2734
2735        // Only continue if a coroutine was found.
2736        debug!(?coroutine, ?trait_ref, ?target_ty);
2737        let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
2738            (coroutine, trait_ref, target_ty)
2739        else {
2740            return false;
2741        };
2742
2743        let span = self.tcx.def_span(coroutine_did);
2744
2745        let coroutine_did_root = self.tcx.typeck_root_def_id(coroutine_did);
2746        debug!(
2747            ?coroutine_did,
2748            ?coroutine_did_root,
2749            typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
2750            ?span,
2751        );
2752
2753        let coroutine_body =
2754            coroutine_did.as_local().and_then(|def_id| self.tcx.hir_maybe_body_owned_by(def_id));
2755        let mut visitor = AwaitsVisitor::default();
2756        if let Some(body) = coroutine_body {
2757            visitor.visit_body(&body);
2758        }
2759        debug!(awaits = ?visitor.awaits);
2760
2761        // Look for a type inside the coroutine interior that matches the target type to get
2762        // a span.
2763        let target_ty_erased = self.tcx.erase_and_anonymize_regions(target_ty);
2764        let ty_matches = |ty| -> bool {
2765            // Careful: the regions for types that appear in the
2766            // coroutine interior are not generally known, so we
2767            // want to erase them when comparing (and anyway,
2768            // `Send` and other bounds are generally unaffected by
2769            // the choice of region). When erasing regions, we
2770            // also have to erase late-bound regions. This is
2771            // because the types that appear in the coroutine
2772            // interior generally contain "bound regions" to
2773            // represent regions that are part of the suspended
2774            // coroutine frame. Bound regions are preserved by
2775            // `erase_and_anonymize_regions` and so we must also call
2776            // `instantiate_bound_regions_with_erased`.
2777            let ty_erased = self.tcx.instantiate_bound_regions_with_erased(ty);
2778            let ty_erased = self.tcx.erase_and_anonymize_regions(ty_erased);
2779            let eq = ty_erased == target_ty_erased;
2780            debug!(?ty_erased, ?target_ty_erased, ?eq);
2781            eq
2782        };
2783
2784        // Get the typeck results from the infcx if the coroutine is the function we are currently
2785        // type-checking; otherwise, get them by performing a query. This is needed to avoid
2786        // cycles. If we can't use resolved types because the coroutine comes from another crate,
2787        // we still provide a targeted error but without all the relevant spans.
2788        let coroutine_data = match &self.typeck_results {
2789            Some(t) if t.hir_owner.to_def_id() == coroutine_did_root => CoroutineData(t),
2790            _ if coroutine_did.is_local() => {
2791                CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
2792            }
2793            _ => return false,
2794        };
2795
2796        let coroutine_within_in_progress_typeck = match &self.typeck_results {
2797            Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
2798            _ => false,
2799        };
2800
2801        let mut interior_or_upvar_span = None;
2802
2803        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, self.tcx, ty_matches);
2804        debug!(?from_awaited_ty);
2805
2806        // Avoid disclosing internal information to downstream crates.
2807        if coroutine_did.is_local()
2808            // Try to avoid cycles.
2809            && !coroutine_within_in_progress_typeck
2810            && let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
2811        {
2812            debug!(?coroutine_info);
2813            'find_source: for (variant, source_info) in
2814                coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
2815            {
2816                debug!(?variant);
2817                for &local in variant {
2818                    let decl = &coroutine_info.field_tys[local];
2819                    debug!(?decl);
2820                    if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
2821                        interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
2822                            decl.source_info.span,
2823                            Some((source_info.span, from_awaited_ty)),
2824                        ));
2825                        break 'find_source;
2826                    }
2827                }
2828            }
2829        }
2830
2831        if interior_or_upvar_span.is_none() {
2832            interior_or_upvar_span =
2833                coroutine_data.try_get_upvar_span(self, coroutine_did, ty_matches);
2834        }
2835
2836        if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
2837            interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(span, None));
2838        }
2839
2840        debug!(?interior_or_upvar_span);
2841        if let Some(interior_or_upvar_span) = interior_or_upvar_span {
2842            let is_async = self.tcx.coroutine_is_async(coroutine_did);
2843            self.note_obligation_cause_for_async_await(
2844                err,
2845                interior_or_upvar_span,
2846                is_async,
2847                outer_coroutine,
2848                trait_ref,
2849                target_ty,
2850                obligation,
2851                next_code,
2852            );
2853            true
2854        } else {
2855            false
2856        }
2857    }
2858
2859    /// Unconditionally adds the diagnostic note described in
2860    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
2861    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("note_obligation_cause_for_async_await",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2861u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let source_map = self.tcx.sess.source_map();
            let (await_or_yield, an_await_or_yield) =
                if is_async {
                    ("await", "an await")
                } else { ("yield", "a yield") };
            let future_or_coroutine =
                if is_async { "future" } else { "coroutine" };
            let trait_explanation =
                if let Some(name @ (sym::Send | sym::Sync)) =
                        self.tcx.get_diagnostic_name(trait_pred.def_id()) {
                    let (trait_name, trait_verb) =
                        if name == sym::Send {
                            ("`Send`", "sent")
                        } else { ("`Sync`", "shared") };
                    err.code = None;
                    err.primary_message(::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("{0} cannot be {1} between threads safely",
                                        future_or_coroutine, trait_verb))
                            }));
                    let original_span = err.span.primary_span().unwrap();
                    let mut span = MultiSpan::from_span(original_span);
                    let message =
                        outer_coroutine.and_then(|coroutine_did|
                                    {
                                        Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
                                                CoroutineKind::Coroutine(_) =>
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("coroutine is not {0}",
                                                                    trait_name))
                                                        }),
                                                CoroutineKind::Desugared(CoroutineDesugaring::Async,
                                                    CoroutineSource::Fn) =>
                                                    self.tcx.parent(coroutine_did).as_local().map(|parent_did|
                                                                        self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
                                                                    self.tcx.hir_opt_name(parent_hir_id)).map(|name|
                                                                {
                                                                    ::alloc::__export::must_use({
                                                                            ::alloc::fmt::format(format_args!("future returned by `{0}` is not {1}",
                                                                                    name, trait_name))
                                                                        })
                                                                })?,
                                                CoroutineKind::Desugared(CoroutineDesugaring::Async,
                                                    CoroutineSource::Block) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("future created by async block is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::Async,
                                                    CoroutineSource::Closure) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("future created by async closure is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
                                                    CoroutineSource::Fn) =>
                                                    self.tcx.parent(coroutine_did).as_local().map(|parent_did|
                                                                        self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
                                                                    self.tcx.hir_opt_name(parent_hir_id)).map(|name|
                                                                {
                                                                    ::alloc::__export::must_use({
                                                                            ::alloc::fmt::format(format_args!("async iterator returned by `{0}` is not {1}",
                                                                                    name, trait_name))
                                                                        })
                                                                })?,
                                                CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
                                                    CoroutineSource::Block) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("async iterator created by async gen block is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
                                                    CoroutineSource::Closure) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("async iterator created by async gen closure is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::Gen,
                                                    CoroutineSource::Fn) => {
                                                    self.tcx.parent(coroutine_did).as_local().map(|parent_did|
                                                                        self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
                                                                    self.tcx.hir_opt_name(parent_hir_id)).map(|name|
                                                                {
                                                                    ::alloc::__export::must_use({
                                                                            ::alloc::fmt::format(format_args!("iterator returned by `{0}` is not {1}",
                                                                                    name, trait_name))
                                                                        })
                                                                })?
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::Gen,
                                                    CoroutineSource::Block) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("iterator created by gen block is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                                CoroutineKind::Desugared(CoroutineDesugaring::Gen,
                                                    CoroutineSource::Closure) => {
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("iterator created by gen closure is not {0}",
                                                                    trait_name))
                                                        })
                                                }
                                            })
                                    }).unwrap_or_else(||
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0} is not {1}",
                                                future_or_coroutine, trait_name))
                                    }));
                    span.push_span_label(original_span, message);
                    err.span(span);
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("is not {0}", trait_name))
                        })
                } else {
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("does not implement `{0}`",
                                    trait_pred.print_modifiers_and_trait_path()))
                        })
                };
            let mut explain_yield =
                |interior_span: Span, yield_span: Span|
                    {
                        let mut span = MultiSpan::from_span(yield_span);
                        let snippet =
                            match source_map.span_to_snippet(interior_span) {
                                Ok(snippet) if !snippet.contains('\n') =>
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("`{0}`", snippet))
                                        }),
                                _ => "the value".to_string(),
                            };
                        span.push_span_label(yield_span,
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0} occurs here, with {1} maybe used later",
                                            await_or_yield, snippet))
                                }));
                        span.push_span_label(interior_span,
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("has type `{0}` which {1}",
                                            target_ty, trait_explanation))
                                }));
                        err.span_note(span,
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0} {1} as this value is used across {2}",
                                            future_or_coroutine, trait_explanation, an_await_or_yield))
                                }));
                    };
            match interior_or_upvar_span {
                CoroutineInteriorOrUpvar::Interior(interior_span,
                    interior_extra_info) => {
                    if let Some((yield_span, from_awaited_ty)) =
                            interior_extra_info {
                        if let Some(await_span) = from_awaited_ty {
                            let mut span = MultiSpan::from_span(await_span);
                            span.push_span_label(await_span,
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("await occurs here on type `{0}`, which {1}",
                                                target_ty, trait_explanation))
                                    }));
                            err.span_note(span,
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("future {0} as it awaits another future which {0}",
                                                trait_explanation))
                                    }));
                        } else { explain_yield(interior_span, yield_span); }
                    }
                }
                CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
                    let non_send =
                        match target_ty.kind() {
                            ty::Ref(_, ref_ty, mutability) =>
                                match self.evaluate_obligation(obligation) {
                                    Ok(eval) if !eval.may_apply() =>
                                        Some((ref_ty, mutability.is_mut())),
                                    _ => None,
                                },
                            _ => None,
                        };
                    let (span_label, span_note) =
                        match non_send {
                            Some((ref_ty, is_mut)) => {
                                let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
                                let ref_kind = if is_mut { "&mut" } else { "&" };
                                (::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("has type `{0}` which {1}, because `{2}` is not `{3}`",
                                                    target_ty, trait_explanation, ref_ty, ref_ty_trait))
                                        }),
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("captured value {0} because `{1}` references cannot be sent unless their referent is `{2}`",
                                                    trait_explanation, ref_kind, ref_ty_trait))
                                        }))
                            }
                            None =>
                                (::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("has type `{0}` which {1}",
                                                    target_ty, trait_explanation))
                                        }),
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("captured value {0}",
                                                    trait_explanation))
                                        })),
                        };
                    let mut span = MultiSpan::from_span(upvar_span);
                    span.push_span_label(upvar_span, span_label);
                    err.span_note(span, span_note);
                }
            }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3084",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3084u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["next_code"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&next_code)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            self.note_obligation_cause_code(obligation.cause.body_id, err,
                obligation.predicate, obligation.param_env,
                next_code.unwrap(), &mut Vec::new(), &mut Default::default());
        }
    }
}#[instrument(level = "debug", skip_all)]
2862    fn note_obligation_cause_for_async_await<G: EmissionGuarantee>(
2863        &self,
2864        err: &mut Diag<'_, G>,
2865        interior_or_upvar_span: CoroutineInteriorOrUpvar,
2866        is_async: bool,
2867        outer_coroutine: Option<DefId>,
2868        trait_pred: ty::TraitPredicate<'tcx>,
2869        target_ty: Ty<'tcx>,
2870        obligation: &PredicateObligation<'tcx>,
2871        next_code: Option<&ObligationCauseCode<'tcx>>,
2872    ) {
2873        let source_map = self.tcx.sess.source_map();
2874
2875        let (await_or_yield, an_await_or_yield) =
2876            if is_async { ("await", "an await") } else { ("yield", "a yield") };
2877        let future_or_coroutine = if is_async { "future" } else { "coroutine" };
2878
2879        // Special case the primary error message when send or sync is the trait that was
2880        // not implemented.
2881        let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
2882            self.tcx.get_diagnostic_name(trait_pred.def_id())
2883        {
2884            let (trait_name, trait_verb) =
2885                if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
2886
2887            err.code = None;
2888            err.primary_message(format!(
2889                "{future_or_coroutine} cannot be {trait_verb} between threads safely"
2890            ));
2891
2892            let original_span = err.span.primary_span().unwrap();
2893            let mut span = MultiSpan::from_span(original_span);
2894
2895            let message = outer_coroutine
2896                .and_then(|coroutine_did| {
2897                    Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
2898                        CoroutineKind::Coroutine(_) => format!("coroutine is not {trait_name}"),
2899                        CoroutineKind::Desugared(
2900                            CoroutineDesugaring::Async,
2901                            CoroutineSource::Fn,
2902                        ) => self
2903                            .tcx
2904                            .parent(coroutine_did)
2905                            .as_local()
2906                            .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2907                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2908                            .map(|name| {
2909                                format!("future returned by `{name}` is not {trait_name}")
2910                            })?,
2911                        CoroutineKind::Desugared(
2912                            CoroutineDesugaring::Async,
2913                            CoroutineSource::Block,
2914                        ) => {
2915                            format!("future created by async block is not {trait_name}")
2916                        }
2917                        CoroutineKind::Desugared(
2918                            CoroutineDesugaring::Async,
2919                            CoroutineSource::Closure,
2920                        ) => {
2921                            format!("future created by async closure is not {trait_name}")
2922                        }
2923                        CoroutineKind::Desugared(
2924                            CoroutineDesugaring::AsyncGen,
2925                            CoroutineSource::Fn,
2926                        ) => self
2927                            .tcx
2928                            .parent(coroutine_did)
2929                            .as_local()
2930                            .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2931                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2932                            .map(|name| {
2933                                format!("async iterator returned by `{name}` is not {trait_name}")
2934                            })?,
2935                        CoroutineKind::Desugared(
2936                            CoroutineDesugaring::AsyncGen,
2937                            CoroutineSource::Block,
2938                        ) => {
2939                            format!("async iterator created by async gen block is not {trait_name}")
2940                        }
2941                        CoroutineKind::Desugared(
2942                            CoroutineDesugaring::AsyncGen,
2943                            CoroutineSource::Closure,
2944                        ) => {
2945                            format!(
2946                                "async iterator created by async gen closure is not {trait_name}"
2947                            )
2948                        }
2949                        CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn) => {
2950                            self.tcx
2951                                .parent(coroutine_did)
2952                                .as_local()
2953                                .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2954                                .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2955                                .map(|name| {
2956                                    format!("iterator returned by `{name}` is not {trait_name}")
2957                                })?
2958                        }
2959                        CoroutineKind::Desugared(
2960                            CoroutineDesugaring::Gen,
2961                            CoroutineSource::Block,
2962                        ) => {
2963                            format!("iterator created by gen block is not {trait_name}")
2964                        }
2965                        CoroutineKind::Desugared(
2966                            CoroutineDesugaring::Gen,
2967                            CoroutineSource::Closure,
2968                        ) => {
2969                            format!("iterator created by gen closure is not {trait_name}")
2970                        }
2971                    })
2972                })
2973                .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
2974
2975            span.push_span_label(original_span, message);
2976            err.span(span);
2977
2978            format!("is not {trait_name}")
2979        } else {
2980            format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
2981        };
2982
2983        let mut explain_yield = |interior_span: Span, yield_span: Span| {
2984            let mut span = MultiSpan::from_span(yield_span);
2985            let snippet = match source_map.span_to_snippet(interior_span) {
2986                // #70935: If snippet contains newlines, display "the value" instead
2987                // so that we do not emit complex diagnostics.
2988                Ok(snippet) if !snippet.contains('\n') => format!("`{snippet}`"),
2989                _ => "the value".to_string(),
2990            };
2991            // note: future is not `Send` as this value is used across an await
2992            //   --> $DIR/issue-70935-complex-spans.rs:13:9
2993            //    |
2994            // LL |            baz(|| async {
2995            //    |  ______________-
2996            //    | |
2997            //    | |
2998            // LL | |              foo(tx.clone());
2999            // LL | |          }).await;
3000            //    | |          - ^^^^^^ await occurs here, with value maybe used later
3001            //    | |__________|
3002            //    |            has type `closure` which is not `Send`
3003            // note: value is later dropped here
3004            // LL | |          }).await;
3005            //    | |                  ^
3006            //
3007            span.push_span_label(
3008                yield_span,
3009                format!("{await_or_yield} occurs here, with {snippet} maybe used later"),
3010            );
3011            span.push_span_label(
3012                interior_span,
3013                format!("has type `{target_ty}` which {trait_explanation}"),
3014            );
3015            err.span_note(
3016                span,
3017                format!("{future_or_coroutine} {trait_explanation} as this value is used across {an_await_or_yield}"),
3018            );
3019        };
3020        match interior_or_upvar_span {
3021            CoroutineInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
3022                if let Some((yield_span, from_awaited_ty)) = interior_extra_info {
3023                    if let Some(await_span) = from_awaited_ty {
3024                        // The type causing this obligation is one being awaited at await_span.
3025                        let mut span = MultiSpan::from_span(await_span);
3026                        span.push_span_label(
3027                            await_span,
3028                            format!(
3029                                "await occurs here on type `{target_ty}`, which {trait_explanation}"
3030                            ),
3031                        );
3032                        err.span_note(
3033                            span,
3034                            format!(
3035                                "future {trait_explanation} as it awaits another future which {trait_explanation}"
3036                            ),
3037                        );
3038                    } else {
3039                        // Look at the last interior type to get a span for the `.await`.
3040                        explain_yield(interior_span, yield_span);
3041                    }
3042                }
3043            }
3044            CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
3045                // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
3046                let non_send = match target_ty.kind() {
3047                    ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(obligation) {
3048                        Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
3049                        _ => None,
3050                    },
3051                    _ => None,
3052                };
3053
3054                let (span_label, span_note) = match non_send {
3055                    // if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
3056                    // include suggestions to make `T: Sync` so that `&T: Send`,
3057                    // or to make `T: Send` so that `&mut T: Send`
3058                    Some((ref_ty, is_mut)) => {
3059                        let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
3060                        let ref_kind = if is_mut { "&mut" } else { "&" };
3061                        (
3062                            format!(
3063                                "has type `{target_ty}` which {trait_explanation}, because `{ref_ty}` is not `{ref_ty_trait}`"
3064                            ),
3065                            format!(
3066                                "captured value {trait_explanation} because `{ref_kind}` references cannot be sent unless their referent is `{ref_ty_trait}`"
3067                            ),
3068                        )
3069                    }
3070                    None => (
3071                        format!("has type `{target_ty}` which {trait_explanation}"),
3072                        format!("captured value {trait_explanation}"),
3073                    ),
3074                };
3075
3076                let mut span = MultiSpan::from_span(upvar_span);
3077                span.push_span_label(upvar_span, span_label);
3078                err.span_note(span, span_note);
3079            }
3080        }
3081
3082        // Add a note for the item obligation that remains - normally a note pointing to the
3083        // bound that introduced the obligation (e.g. `T: Send`).
3084        debug!(?next_code);
3085        self.note_obligation_cause_code(
3086            obligation.cause.body_id,
3087            err,
3088            obligation.predicate,
3089            obligation.param_env,
3090            next_code.unwrap(),
3091            &mut Vec::new(),
3092            &mut Default::default(),
3093        );
3094    }
3095
3096    pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
3097        &self,
3098        body_id: LocalDefId,
3099        err: &mut Diag<'_, G>,
3100        predicate: T,
3101        param_env: ty::ParamEnv<'tcx>,
3102        cause_code: &ObligationCauseCode<'tcx>,
3103        obligated_types: &mut Vec<Ty<'tcx>>,
3104        seen_requirements: &mut FxHashSet<DefId>,
3105    ) where
3106        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
3107    {
3108        let tcx = self.tcx;
3109        let predicate = predicate.upcast(tcx);
3110        let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| {
3111            if let Some(pred) = predicate.as_trait_clause()
3112                && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3113                && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
3114            {
3115                err.span_suggestion_verbose(
3116                    expr.span.until(inner.span),
3117                    "references are always `Sized`, even if they point to unsized data; consider \
3118                     not dereferencing the expression",
3119                    String::new(),
3120                    Applicability::MaybeIncorrect,
3121                );
3122            }
3123        };
3124        match *cause_code {
3125            ObligationCauseCode::ExprAssignable
3126            | ObligationCauseCode::MatchExpressionArm { .. }
3127            | ObligationCauseCode::Pattern { .. }
3128            | ObligationCauseCode::IfExpression { .. }
3129            | ObligationCauseCode::IfExpressionWithNoElse
3130            | ObligationCauseCode::MainFunctionType
3131            | ObligationCauseCode::LangFunctionType(_)
3132            | ObligationCauseCode::IntrinsicType
3133            | ObligationCauseCode::MethodReceiver
3134            | ObligationCauseCode::ReturnNoExpression
3135            | ObligationCauseCode::Misc
3136            | ObligationCauseCode::WellFormed(..)
3137            | ObligationCauseCode::MatchImpl(..)
3138            | ObligationCauseCode::ReturnValue(_)
3139            | ObligationCauseCode::BlockTailExpression(..)
3140            | ObligationCauseCode::AwaitableExpr(_)
3141            | ObligationCauseCode::ForLoopIterator
3142            | ObligationCauseCode::QuestionMark
3143            | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
3144            | ObligationCauseCode::LetElse
3145            | ObligationCauseCode::UnOp { .. }
3146            | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
3147            | ObligationCauseCode::AlwaysApplicableImpl
3148            | ObligationCauseCode::ConstParam(_)
3149            | ObligationCauseCode::ReferenceOutlivesReferent(..)
3150            | ObligationCauseCode::ObjectTypeBound(..) => {}
3151            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
3152                if let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id)
3153                    && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id)
3154                    && tcx.sess.source_map().lookup_char_pos(lhs.span.lo()).line
3155                        != tcx.sess.source_map().lookup_char_pos(rhs.span.hi()).line
3156                {
3157                    err.span_label(lhs.span, "");
3158                    err.span_label(rhs.span, "");
3159                }
3160            }
3161            ObligationCauseCode::RustCall => {
3162                if let Some(pred) = predicate.as_trait_clause()
3163                    && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3164                {
3165                    err.note("argument required to be sized due to `extern \"rust-call\"` ABI");
3166                }
3167            }
3168            ObligationCauseCode::SliceOrArrayElem => {
3169                err.note("slice and array elements must have `Sized` type");
3170            }
3171            ObligationCauseCode::ArrayLen(array_ty) => {
3172                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the length of array `{0}` must be type `usize`",
                array_ty))
    })format!("the length of array `{array_ty}` must be type `usize`"));
3173            }
3174            ObligationCauseCode::TupleElem => {
3175                err.note("only the last element of a tuple may have a dynamically sized type");
3176            }
3177            ObligationCauseCode::DynCompatible(span) => {
3178                err.multipart_suggestion(
3179                    "you might have meant to use `Self` to refer to the implementing type",
3180                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span, "Self".into())]))vec![(span, "Self".into())],
3181                    Applicability::MachineApplicable,
3182                );
3183            }
3184            ObligationCauseCode::WhereClause(item_def_id, span)
3185            | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
3186            | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..)
3187                if !span.is_dummy() =>
3188            {
3189                if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code {
3190                    if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id)
3191                        && let hir::ExprKind::Call(_, args) = expr.kind
3192                        && let Some(expr) = args.get(*pos)
3193                    {
3194                        suggest_remove_deref(err, &expr);
3195                    } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id)
3196                        && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind
3197                        && let Some(expr) = args.get(*pos)
3198                    {
3199                        suggest_remove_deref(err, &expr);
3200                    }
3201                }
3202                let item_name = tcx.def_path_str(item_def_id);
3203                let short_item_name = { let _guard = ForceTrimmedGuard::new(); tcx.def_path_str(item_def_id) }with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
3204                let mut multispan = MultiSpan::from(span);
3205                let sm = tcx.sess.source_map();
3206                if let Some(ident) = tcx.opt_item_ident(item_def_id) {
3207                    let same_line =
3208                        match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
3209                            (Ok(l), Ok(r)) => l.line == r.line,
3210                            _ => true,
3211                        };
3212                    if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
3213                        multispan.push_span_label(
3214                            ident.span,
3215                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by a bound in this {0}",
                tcx.def_kind(item_def_id).descr(item_def_id)))
    })format!(
3216                                "required by a bound in this {}",
3217                                tcx.def_kind(item_def_id).descr(item_def_id)
3218                            ),
3219                        );
3220                    }
3221                }
3222                let mut a = "a";
3223                let mut this = "this bound";
3224                let mut note = None;
3225                let mut help = None;
3226                if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
3227                    match clause {
3228                        ty::ClauseKind::Trait(trait_pred) => {
3229                            let def_id = trait_pred.def_id();
3230                            let visible_item = if let Some(local) = def_id.as_local() {
3231                                let ty = trait_pred.self_ty();
3232                                // when `TraitA: TraitB` and `S` only impl TraitA,
3233                                // we check if `TraitB` can be reachable from `S`
3234                                // to determine whether to note `TraitA` is sealed trait.
3235                                if let ty::Adt(adt, _) = ty.kind() {
3236                                    let visibilities = &tcx.resolutions(()).effective_visibilities;
3237                                    visibilities.effective_vis(local).is_none_or(|v| {
3238                                        v.at_level(Level::Reexported)
3239                                            .is_accessible_from(adt.did(), tcx)
3240                                    })
3241                                } else {
3242                                    // FIXME(xizheyin): if the type is not ADT, we should not suggest it
3243                                    true
3244                                }
3245                            } else {
3246                                // Check for foreign traits being reachable.
3247                                tcx.visible_parent_map(()).get(&def_id).is_some()
3248                            };
3249                            if tcx.is_lang_item(def_id, LangItem::Sized) {
3250                                // Check if this is an implicit bound, even in foreign crates.
3251                                if tcx
3252                                    .generics_of(item_def_id)
3253                                    .own_params
3254                                    .iter()
3255                                    .any(|param| tcx.def_span(param.def_id) == span)
3256                                {
3257                                    a = "an implicit `Sized`";
3258                                    this =
3259                                        "the implicit `Sized` requirement on this type parameter";
3260                                }
3261                                if let Some(hir::Node::TraitItem(hir::TraitItem {
3262                                    generics,
3263                                    kind: hir::TraitItemKind::Type(bounds, None),
3264                                    ..
3265                                })) = tcx.hir_get_if_local(item_def_id)
3266                                    // Do not suggest relaxing if there is an explicit `Sized` obligation.
3267                                    && !bounds.iter()
3268                                        .filter_map(|bound| bound.trait_ref())
3269                                        .any(|tr| tr.trait_def_id().is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)))
3270                                {
3271                                    let (span, separator) = if let [.., last] = bounds {
3272                                        (last.span().shrink_to_hi(), " +")
3273                                    } else {
3274                                        (generics.span.shrink_to_hi(), ":")
3275                                    };
3276                                    err.span_suggestion_verbose(
3277                                        span,
3278                                        "consider relaxing the implicit `Sized` restriction",
3279                                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} ?Sized", separator))
    })format!("{separator} ?Sized"),
3280                                        Applicability::MachineApplicable,
3281                                    );
3282                                }
3283                            }
3284                            if let DefKind::Trait = tcx.def_kind(item_def_id)
3285                                && !visible_item
3286                            {
3287                                note = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{1}` is a \"sealed trait\", because to implement it you also need to implement `{0}`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it",
                {
                    let _guard = NoTrimmedGuard::new();
                    tcx.def_path_str(def_id)
                }, short_item_name))
    })format!(
3288                                    "`{short_item_name}` is a \"sealed trait\", because to implement it \
3289                                    you also need to implement `{}`, which is not accessible; this is \
3290                                    usually done to force you to use one of the provided types that \
3291                                    already implement it",
3292                                    with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3293                                ));
3294                                let impls_of = tcx.trait_impls_of(def_id);
3295                                let impls = impls_of
3296                                    .non_blanket_impls()
3297                                    .values()
3298                                    .flatten()
3299                                    .chain(impls_of.blanket_impls().iter())
3300                                    .collect::<Vec<_>>();
3301                                if !impls.is_empty() {
3302                                    let len = impls.len();
3303                                    let mut types = impls
3304                                        .iter()
3305                                        .map(|&&t| {
3306                                            {
    let _guard = NoTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("  {0}",
                    tcx.type_of(t).instantiate_identity()))
        })
}with_no_trimmed_paths!(format!(
3307                                                "  {}",
3308                                                tcx.type_of(t).instantiate_identity(),
3309                                            ))
3310                                        })
3311                                        .collect::<Vec<_>>();
3312                                    let post = if types.len() > 9 {
3313                                        types.truncate(8);
3314                                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\nand {0} others", len - 8))
    })format!("\nand {} others", len - 8)
3315                                    } else {
3316                                        String::new()
3317                                    };
3318                                    help = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the following type{0} implement{1} the trait:\n{2}{3}",
                if len == 1 { "" } else { "s" },
                if len == 1 { "s" } else { "" }, types.join("\n"), post))
    })format!(
3319                                        "the following type{} implement{} the trait:\n{}{post}",
3320                                        pluralize!(len),
3321                                        if len == 1 { "s" } else { "" },
3322                                        types.join("\n"),
3323                                    ));
3324                                }
3325                            }
3326                        }
3327                        ty::ClauseKind::ConstArgHasType(..) => {
3328                            let descr =
3329                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by a const generic parameter in `{0}`",
                item_name))
    })format!("required by a const generic parameter in `{item_name}`");
3330                            if span.is_visible(sm) {
3331                                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by this const generic parameter in `{0}`",
                short_item_name))
    })format!(
3332                                    "required by this const generic parameter in `{short_item_name}`"
3333                                );
3334                                multispan.push_span_label(span, msg);
3335                                err.span_note(multispan, descr);
3336                            } else {
3337                                err.span_note(tcx.def_span(item_def_id), descr);
3338                            }
3339                            return;
3340                        }
3341                        _ => (),
3342                    }
3343                }
3344
3345                // If this is from a format string literal desugaring,
3346                // we've already said "required by this formatting parameter"
3347                let is_in_fmt_lit = if let Some(s) = err.span.primary_span() {
3348                    #[allow(non_exhaustive_omitted_patterns)] match s.desugaring_kind() {
    Some(DesugaringKind::FormatLiteral { .. }) => true,
    _ => false,
}matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. }))
3349                } else {
3350                    false
3351                };
3352                if !is_in_fmt_lit {
3353                    let descr = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by {0} bound in `{1}`", a,
                item_name))
    })format!("required by {a} bound in `{item_name}`");
3354                    if span.is_visible(sm) {
3355                        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by {0} in `{1}`", this,
                short_item_name))
    })format!("required by {this} in `{short_item_name}`");
3356                        multispan.push_span_label(span, msg);
3357                        err.span_note(multispan, descr);
3358                    } else {
3359                        err.span_note(tcx.def_span(item_def_id), descr);
3360                    }
3361                }
3362                if let Some(note) = note {
3363                    err.note(note);
3364                }
3365                if let Some(help) = help {
3366                    err.help(help);
3367                }
3368            }
3369            ObligationCauseCode::WhereClause(..)
3370            | ObligationCauseCode::WhereClauseInExpr(..)
3371            | ObligationCauseCode::HostEffectInExpr(..) => {
3372                // We hold the `DefId` of the item introducing the obligation, but displaying it
3373                // doesn't add user usable information. It always point at an associated item.
3374            }
3375            ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => {
3376                err.span_note(span, "required by a bound in an opaque type");
3377                if let Some(definition_def_id) = definition_def_id
3378                    // If there are any stalled coroutine obligations, then this
3379                    // error may be due to that, and not because the body has more
3380                    // where-clauses.
3381                    && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty()
3382                {
3383                    // FIXME(compiler-errors): We could probably point to something
3384                    // specific here if we tried hard enough...
3385                    err.span_note(
3386                        tcx.def_span(definition_def_id),
3387                        "this definition site has more where clauses than the opaque type",
3388                    );
3389                }
3390            }
3391            ObligationCauseCode::Coercion { source, target } => {
3392                let source =
3393                    tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path());
3394                let target =
3395                    tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path());
3396                err.note({
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("required for the cast from `{0}` to `{1}`",
                    source, target))
        })
}with_forced_trimmed_paths!(format!(
3397                    "required for the cast from `{source}` to `{target}`",
3398                )));
3399            }
3400            ObligationCauseCode::RepeatElementCopy { is_constable, elt_span } => {
3401                err.note(
3402                    "the `Copy` trait is required because this value will be copied for each element of the array",
3403                );
3404                let sm = tcx.sess.source_map();
3405                if #[allow(non_exhaustive_omitted_patterns)] match is_constable {
    IsConstable::Fn | IsConstable::Ctor => true,
    _ => false,
}matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
3406                    && let Ok(_) = sm.span_to_snippet(elt_span)
3407                {
3408                    err.multipart_suggestion(
3409                        "create an inline `const` block",
3410                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(elt_span.shrink_to_lo(), "const { ".to_string()),
                (elt_span.shrink_to_hi(), " }".to_string())]))vec![
3411                            (elt_span.shrink_to_lo(), "const { ".to_string()),
3412                            (elt_span.shrink_to_hi(), " }".to_string()),
3413                        ],
3414                        Applicability::MachineApplicable,
3415                    );
3416                } else {
3417                    // FIXME: we may suggest array::repeat instead
3418                    err.help("consider using `core::array::from_fn` to initialize the array");
3419                    err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information");
3420                }
3421            }
3422            ObligationCauseCode::VariableType(hir_id) => {
3423                if let Some(typeck_results) = &self.typeck_results
3424                    && let Some(ty) = typeck_results.node_type_opt(hir_id)
3425                    && let ty::Error(_) = ty.kind()
3426                {
3427                    err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` isn\'t satisfied, but the type of this pattern is `{{type error}}`",
                predicate))
    })format!(
3428                        "`{predicate}` isn't satisfied, but the type of this pattern is \
3429                         `{{type error}}`",
3430                    ));
3431                    err.downgrade_to_delayed_bug();
3432                }
3433                let mut local = true;
3434                match tcx.parent_hir_node(hir_id) {
3435                    Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
3436                        err.span_suggestion_verbose(
3437                            ty.span.shrink_to_lo(),
3438                            "consider borrowing here",
3439                            "&",
3440                            Applicability::MachineApplicable,
3441                        );
3442                    }
3443                    Node::LetStmt(hir::LetStmt {
3444                        init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }),
3445                        ..
3446                    }) => {
3447                        // When encountering an assignment of an unsized trait, like
3448                        // `let x = ""[..];`, provide a suggestion to borrow the initializer in
3449                        // order to use have a slice instead.
3450                        err.span_suggestion_verbose(
3451                            span.shrink_to_lo(),
3452                            "consider borrowing here",
3453                            "&",
3454                            Applicability::MachineApplicable,
3455                        );
3456                    }
3457                    Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => {
3458                        // When encountering an assignment of an unsized trait, like `let x = *"";`,
3459                        // we check if the RHS is a deref operation, to suggest removing it.
3460                        suggest_remove_deref(err, &expr);
3461                    }
3462                    Node::Param(param) => {
3463                        err.span_suggestion_verbose(
3464                            param.ty_span.shrink_to_lo(),
3465                            "function arguments must have a statically known size, borrowed types \
3466                            always have a known size",
3467                            "&",
3468                            Applicability::MachineApplicable,
3469                        );
3470                        local = false;
3471                    }
3472                    _ => {}
3473                }
3474                if local {
3475                    err.note("all local variables must have a statically known size");
3476                }
3477            }
3478            ObligationCauseCode::SizedArgumentType(hir_id) => {
3479                let mut ty = None;
3480                let borrowed_msg = "function arguments must have a statically known size, borrowed \
3481                                    types always have a known size";
3482                if let Some(hir_id) = hir_id
3483                    && let hir::Node::Param(param) = self.tcx.hir_node(hir_id)
3484                    && let Some(decl) = self.tcx.parent_hir_node(hir_id).fn_decl()
3485                    && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
3486                {
3487                    // We use `contains` because the type might be surrounded by parentheses,
3488                    // which makes `ty_span` and `t.span` disagree with each other, but one
3489                    // fully contains the other: `foo: (dyn Foo + Bar)`
3490                    //                                 ^-------------^
3491                    //                                 ||
3492                    //                                 |t.span
3493                    //                                 param._ty_span
3494                    ty = Some(t);
3495                } else if let Some(hir_id) = hir_id
3496                    && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id)
3497                {
3498                    ty = Some(t);
3499                }
3500                if let Some(ty) = ty {
3501                    match ty.kind {
3502                        hir::TyKind::TraitObject(traits, _) => {
3503                            let (span, kw) = match traits {
3504                                [first, ..] if first.span.lo() == ty.span.lo() => {
3505                                    // Missing `dyn` in front of trait object.
3506                                    (ty.span.shrink_to_lo(), "dyn ")
3507                                }
3508                                [first, ..] => (ty.span.until(first.span), ""),
3509                                [] => ::rustc_middle::util::bug::span_bug_fmt(ty.span,
    format_args!("trait object with no traits: {0:?}", ty))span_bug!(ty.span, "trait object with no traits: {ty:?}"),
3510                            };
3511                            let needs_parens = traits.len() != 1;
3512                            // Don't recommend impl Trait as a closure argument
3513                            if let Some(hir_id) = hir_id
3514                                && #[allow(non_exhaustive_omitted_patterns)] match self.tcx.parent_hir_node(hir_id)
    {
    hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. }) => true,
    _ => false,
}matches!(
3515                                    self.tcx.parent_hir_node(hir_id),
3516                                    hir::Node::Item(hir::Item {
3517                                        kind: hir::ItemKind::Fn { .. },
3518                                        ..
3519                                    })
3520                                )
3521                            {
3522                                err.span_suggestion_verbose(
3523                                    span,
3524                                    "you can use `impl Trait` as the argument type",
3525                                    "impl ",
3526                                    Applicability::MaybeIncorrect,
3527                                );
3528                            }
3529                            let sugg = if !needs_parens {
3530                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("&{0}", kw))
                        }))]))vec![(span.shrink_to_lo(), format!("&{kw}"))]
3531                            } else {
3532                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("&({0}", kw))
                        })), (ty.span.shrink_to_hi(), ")".to_string())]))vec![
3533                                    (span.shrink_to_lo(), format!("&({kw}")),
3534                                    (ty.span.shrink_to_hi(), ")".to_string()),
3535                                ]
3536                            };
3537                            err.multipart_suggestion(
3538                                borrowed_msg,
3539                                sugg,
3540                                Applicability::MachineApplicable,
3541                            );
3542                        }
3543                        hir::TyKind::Slice(_ty) => {
3544                            err.span_suggestion_verbose(
3545                                ty.span.shrink_to_lo(),
3546                                "function arguments must have a statically known size, borrowed \
3547                                 slices always have a known size",
3548                                "&",
3549                                Applicability::MachineApplicable,
3550                            );
3551                        }
3552                        hir::TyKind::Path(_) => {
3553                            err.span_suggestion_verbose(
3554                                ty.span.shrink_to_lo(),
3555                                borrowed_msg,
3556                                "&",
3557                                Applicability::MachineApplicable,
3558                            );
3559                        }
3560                        _ => {}
3561                    }
3562                } else {
3563                    err.note("all function arguments must have a statically known size");
3564                }
3565                if tcx.sess.opts.unstable_features.is_nightly_build()
3566                    && !tcx.features().unsized_fn_params()
3567                {
3568                    err.help("unsized fn params are gated as an unstable feature");
3569                }
3570            }
3571            ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => {
3572                err.note("the return type of a function must have a statically known size");
3573            }
3574            ObligationCauseCode::SizedYieldType => {
3575                err.note("the yield type of a coroutine must have a statically known size");
3576            }
3577            ObligationCauseCode::AssignmentLhsSized => {
3578                err.note("the left-hand-side of an assignment must have a statically known size");
3579            }
3580            ObligationCauseCode::TupleInitializerSized => {
3581                err.note("tuples must have a statically known size to be initialized");
3582            }
3583            ObligationCauseCode::StructInitializerSized => {
3584                err.note("structs must have a statically known size to be initialized");
3585            }
3586            ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
3587                match *item {
3588                    AdtKind::Struct => {
3589                        if last {
3590                            err.note(
3591                                "the last field of a packed struct may only have a \
3592                                dynamically sized type if it does not need drop to be run",
3593                            );
3594                        } else {
3595                            err.note(
3596                                "only the last field of a struct may have a dynamically sized type",
3597                            );
3598                        }
3599                    }
3600                    AdtKind::Union => {
3601                        err.note("no field of a union may have a dynamically sized type");
3602                    }
3603                    AdtKind::Enum => {
3604                        err.note("no field of an enum variant may have a dynamically sized type");
3605                    }
3606                }
3607                err.help("change the field's type to have a statically known size");
3608                err.span_suggestion_verbose(
3609                    span.shrink_to_lo(),
3610                    "borrowed types always have a statically known size",
3611                    "&",
3612                    Applicability::MachineApplicable,
3613                );
3614                err.multipart_suggestion(
3615                    "the `Box` type always has a statically known size and allocates its contents \
3616                     in the heap",
3617                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), "Box<".to_string()),
                (span.shrink_to_hi(), ">".to_string())]))vec![
3618                        (span.shrink_to_lo(), "Box<".to_string()),
3619                        (span.shrink_to_hi(), ">".to_string()),
3620                    ],
3621                    Applicability::MachineApplicable,
3622                );
3623            }
3624            ObligationCauseCode::SizedConstOrStatic => {
3625                err.note("statics and constants must have a statically known size");
3626            }
3627            ObligationCauseCode::InlineAsmSized => {
3628                err.note("all inline asm arguments must have a statically known size");
3629            }
3630            ObligationCauseCode::SizedClosureCapture(closure_def_id) => {
3631                err.note(
3632                    "all values captured by value by a closure must have a statically known size",
3633                );
3634                let hir::ExprKind::Closure(closure) =
3635                    tcx.hir_node_by_def_id(closure_def_id).expect_expr().kind
3636                else {
3637                    ::rustc_middle::util::bug::bug_fmt(format_args!("expected closure in SizedClosureCapture obligation"));bug!("expected closure in SizedClosureCapture obligation");
3638                };
3639                if let hir::CaptureBy::Value { .. } = closure.capture_clause
3640                    && let Some(span) = closure.fn_arg_span
3641                {
3642                    err.span_label(span, "this closure captures all values by move");
3643                }
3644            }
3645            ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => {
3646                let what = match tcx.coroutine_kind(coroutine_def_id) {
3647                    None
3648                    | Some(hir::CoroutineKind::Coroutine(_))
3649                    | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => {
3650                        "yield"
3651                    }
3652                    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
3653                        "await"
3654                    }
3655                    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => {
3656                        "yield`/`await"
3657                    }
3658                };
3659                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("all values live across `{0}` must have a statically known size",
                what))
    })format!(
3660                    "all values live across `{what}` must have a statically known size"
3661                ));
3662            }
3663            ObligationCauseCode::SharedStatic => {
3664                err.note("shared static variables must have a type that implements `Sync`");
3665            }
3666            ObligationCauseCode::BuiltinDerived(ref data) => {
3667                let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
3668                let ty = parent_trait_ref.skip_binder().self_ty();
3669                if parent_trait_ref.references_error() {
3670                    // NOTE(eddyb) this was `.cancel()`, but `err`
3671                    // is borrowed, so we can't fully defuse it.
3672                    err.downgrade_to_delayed_bug();
3673                    return;
3674                }
3675
3676                // If the obligation for a tuple is set directly by a Coroutine or Closure,
3677                // then the tuple must be the one containing capture types.
3678                let is_upvar_tys_infer_tuple = if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Tuple(..) => true,
    _ => false,
}matches!(ty.kind(), ty::Tuple(..)) {
3679                    false
3680                } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
3681                    let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
3682                    let nested_ty = parent_trait_ref.skip_binder().self_ty();
3683                    #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
    ty::Coroutine(..) => true,
    _ => false,
}matches!(nested_ty.kind(), ty::Coroutine(..))
3684                        || #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
    ty::Closure(..) => true,
    _ => false,
}matches!(nested_ty.kind(), ty::Closure(..))
3685                } else {
3686                    false
3687                };
3688
3689                let is_builtin_async_fn_trait =
3690                    tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some();
3691
3692                if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait {
3693                    let mut msg = || {
3694                        let ty_str = tcx.short_string(ty, err.long_ty_path());
3695                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required because it appears within the type `{0}`",
                ty_str))
    })format!("required because it appears within the type `{ty_str}`")
3696                    };
3697                    match *ty.kind() {
3698                        ty::Adt(def, _) => {
3699                            let msg = msg();
3700                            match tcx.opt_item_ident(def.did()) {
3701                                Some(ident) => {
3702                                    err.span_note(ident.span, msg);
3703                                }
3704                                None => {
3705                                    err.note(msg);
3706                                }
3707                            }
3708                        }
3709                        ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => {
3710                            // If the previous type is async fn, this is the future generated by the body of an async function.
3711                            // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below).
3712                            let is_future = tcx.ty_is_opaque_future(ty);
3713                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3713",
                        "rustc_trait_selection::error_reporting::traits::suggestions",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                        ::tracing_core::__macro_support::Option::Some(3713u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        "obligated_types", "is_future"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("note_obligation_cause_code: check for async fn")
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&obligated_types)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&is_future)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(
3714                                ?obligated_types,
3715                                ?is_future,
3716                                "note_obligation_cause_code: check for async fn"
3717                            );
3718                            if is_future
3719                                && obligated_types.last().is_some_and(|ty| match ty.kind() {
3720                                    ty::Coroutine(last_def_id, ..) => {
3721                                        tcx.coroutine_is_async(*last_def_id)
3722                                    }
3723                                    _ => false,
3724                                })
3725                            {
3726                                // See comment above; skip printing twice.
3727                            } else {
3728                                let msg = msg();
3729                                err.span_note(tcx.def_span(def_id), msg);
3730                            }
3731                        }
3732                        ty::Coroutine(def_id, _) => {
3733                            let sp = tcx.def_span(def_id);
3734
3735                            // Special-case this to say "async block" instead of `[static coroutine]`.
3736                            let kind = tcx.coroutine_kind(def_id).unwrap();
3737                            err.span_note(
3738                                sp,
3739                                {
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("required because it\'s used within this {0:#}",
                    kind))
        })
}with_forced_trimmed_paths!(format!(
3740                                    "required because it's used within this {kind:#}",
3741                                )),
3742                            );
3743                        }
3744                        ty::CoroutineWitness(..) => {
3745                            // Skip printing coroutine-witnesses, since we'll drill into
3746                            // the bad field in another derived obligation cause.
3747                        }
3748                        ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => {
3749                            err.span_note(
3750                                tcx.def_span(def_id),
3751                                "required because it's used within this closure",
3752                            );
3753                        }
3754                        ty::Str => {
3755                            err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes");
3756                        }
3757                        _ => {
3758                            let msg = msg();
3759                            err.note(msg);
3760                        }
3761                    };
3762                }
3763
3764                obligated_types.push(ty);
3765
3766                let parent_predicate = parent_trait_ref;
3767                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
3768                    // #74711: avoid a stack overflow
3769                    ensure_sufficient_stack(|| {
3770                        self.note_obligation_cause_code(
3771                            body_id,
3772                            err,
3773                            parent_predicate,
3774                            param_env,
3775                            &data.parent_code,
3776                            obligated_types,
3777                            seen_requirements,
3778                        )
3779                    });
3780                } else {
3781                    ensure_sufficient_stack(|| {
3782                        self.note_obligation_cause_code(
3783                            body_id,
3784                            err,
3785                            parent_predicate,
3786                            param_env,
3787                            cause_code.peel_derives(),
3788                            obligated_types,
3789                            seen_requirements,
3790                        )
3791                    });
3792                }
3793            }
3794            ObligationCauseCode::ImplDerived(ref data) => {
3795                let mut parent_trait_pred =
3796                    self.resolve_vars_if_possible(data.derived.parent_trait_pred);
3797                let parent_def_id = parent_trait_pred.def_id();
3798                if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id)
3799                    && !tcx.features().enabled(sym::try_trait_v2)
3800                {
3801                    // If `#![feature(try_trait_v2)]` is not enabled, then there's no point on
3802                    // talking about `FromResidual<Result<A, B>>`, as the end user has nothing they
3803                    // can do about it. As far as they are concerned, `?` is compiler magic.
3804                    return;
3805                }
3806                if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) {
3807                    let parent_predicate =
3808                        self.resolve_vars_if_possible(data.derived.parent_trait_pred);
3809
3810                    // Skip PinDerefMutHelper in suggestions, but still show downstream suggestions.
3811                    ensure_sufficient_stack(|| {
3812                        self.note_obligation_cause_code(
3813                            body_id,
3814                            err,
3815                            parent_predicate,
3816                            param_env,
3817                            &data.derived.parent_code,
3818                            obligated_types,
3819                            seen_requirements,
3820                        )
3821                    });
3822                    return;
3823                }
3824                let self_ty_str =
3825                    tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
3826                let trait_name = tcx.short_string(
3827                    parent_trait_pred.print_modifiers_and_trait_path(),
3828                    err.long_ty_path(),
3829                );
3830                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required for `{0}` to implement `{1}`",
                self_ty_str, trait_name))
    })format!("required for `{self_ty_str}` to implement `{trait_name}`");
3831                let mut is_auto_trait = false;
3832                match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
3833                    Some(Node::Item(hir::Item {
3834                        kind: hir::ItemKind::Trait(_, is_auto, _, ident, ..),
3835                        ..
3836                    })) => {
3837                        // FIXME: we should do something else so that it works even on crate foreign
3838                        // auto traits.
3839                        is_auto_trait = #[allow(non_exhaustive_omitted_patterns)] match is_auto {
    hir::IsAuto::Yes => true,
    _ => false,
}matches!(is_auto, hir::IsAuto::Yes);
3840                        err.span_note(ident.span, msg);
3841                    }
3842                    Some(Node::Item(hir::Item {
3843                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
3844                        ..
3845                    })) => {
3846                        let mut spans = Vec::with_capacity(2);
3847                        if let Some(of_trait) = of_trait
3848                            && !of_trait.trait_ref.path.span.in_derive_expansion()
3849                        {
3850                            spans.push(of_trait.trait_ref.path.span);
3851                        }
3852                        spans.push(self_ty.span);
3853                        let mut spans: MultiSpan = spans.into();
3854                        let mut derived = false;
3855                        if #[allow(non_exhaustive_omitted_patterns)] match self_ty.span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Macro(MacroKind::Derive, _) => true,
    _ => false,
}matches!(
3856                            self_ty.span.ctxt().outer_expn_data().kind,
3857                            ExpnKind::Macro(MacroKind::Derive, _)
3858                        ) || #[allow(non_exhaustive_omitted_patterns)] match of_trait.map(|t|
            t.trait_ref.path.span.ctxt().outer_expn_data().kind) {
    Some(ExpnKind::Macro(MacroKind::Derive, _)) => true,
    _ => false,
}matches!(
3859                            of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
3860                            Some(ExpnKind::Macro(MacroKind::Derive, _))
3861                        ) {
3862                            derived = true;
3863                            spans.push_span_label(
3864                                data.span,
3865                                if data.span.in_derive_expansion() {
3866                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("type parameter would need to implement `{0}`",
                trait_name))
    })format!("type parameter would need to implement `{trait_name}`")
3867                                } else {
3868                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unsatisfied trait bound"))
    })format!("unsatisfied trait bound")
3869                                },
3870                            );
3871                        } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) {
3872                            // `Sized` may be an explicit or implicit trait bound. If it is
3873                            // implicit, mention it as such.
3874                            if let Some(pred) = predicate.as_trait_clause()
3875                                && self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3876                                && self
3877                                    .tcx
3878                                    .generics_of(data.impl_or_alias_def_id)
3879                                    .own_params
3880                                    .iter()
3881                                    .any(|param| self.tcx.def_span(param.def_id) == data.span)
3882                            {
3883                                spans.push_span_label(
3884                                    data.span,
3885                                    "unsatisfied trait bound implicitly introduced here",
3886                                );
3887                            } else {
3888                                spans.push_span_label(
3889                                    data.span,
3890                                    "unsatisfied trait bound introduced here",
3891                                );
3892                            }
3893                        }
3894                        err.span_note(spans, msg);
3895                        if derived && trait_name != "Copy" {
3896                            err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider manually implementing `{0}` to avoid undesired bounds",
                trait_name))
    })format!(
3897                                "consider manually implementing `{trait_name}` to avoid undesired \
3898                                 bounds",
3899                            ));
3900                        }
3901                        point_at_assoc_type_restriction(
3902                            tcx,
3903                            err,
3904                            &self_ty_str,
3905                            &trait_name,
3906                            predicate,
3907                            &generics,
3908                            &data,
3909                        );
3910                    }
3911                    _ => {
3912                        err.note(msg);
3913                    }
3914                };
3915
3916                let mut parent_predicate = parent_trait_pred;
3917                let mut data = &data.derived;
3918                let mut count = 0;
3919                seen_requirements.insert(parent_def_id);
3920                if is_auto_trait {
3921                    // We don't want to point at the ADT saying "required because it appears within
3922                    // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
3923                    while let ObligationCauseCode::BuiltinDerived(derived) = &*data.parent_code {
3924                        let child_trait_ref =
3925                            self.resolve_vars_if_possible(derived.parent_trait_pred);
3926                        let child_def_id = child_trait_ref.def_id();
3927                        if seen_requirements.insert(child_def_id) {
3928                            break;
3929                        }
3930                        data = derived;
3931                        parent_predicate = child_trait_ref.upcast(tcx);
3932                        parent_trait_pred = child_trait_ref;
3933                    }
3934                }
3935                while let ObligationCauseCode::ImplDerived(child) = &*data.parent_code {
3936                    // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
3937                    let child_trait_pred =
3938                        self.resolve_vars_if_possible(child.derived.parent_trait_pred);
3939                    let child_def_id = child_trait_pred.def_id();
3940                    if seen_requirements.insert(child_def_id) {
3941                        break;
3942                    }
3943                    count += 1;
3944                    data = &child.derived;
3945                    parent_predicate = child_trait_pred.upcast(tcx);
3946                    parent_trait_pred = child_trait_pred;
3947                }
3948                if count > 0 {
3949                    err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} redundant requirement{1} hidden",
                count, if count == 1 { "" } else { "s" }))
    })format!(
3950                        "{} redundant requirement{} hidden",
3951                        count,
3952                        pluralize!(count)
3953                    ));
3954                    let self_ty = tcx.short_string(
3955                        parent_trait_pred.skip_binder().self_ty(),
3956                        err.long_ty_path(),
3957                    );
3958                    let trait_path = tcx.short_string(
3959                        parent_trait_pred.print_modifiers_and_trait_path(),
3960                        err.long_ty_path(),
3961                    );
3962                    err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required for `{0}` to implement `{1}`",
                self_ty, trait_path))
    })format!("required for `{self_ty}` to implement `{trait_path}`"));
3963                }
3964                // #74711: avoid a stack overflow
3965                ensure_sufficient_stack(|| {
3966                    self.note_obligation_cause_code(
3967                        body_id,
3968                        err,
3969                        parent_predicate,
3970                        param_env,
3971                        &data.parent_code,
3972                        obligated_types,
3973                        seen_requirements,
3974                    )
3975                });
3976            }
3977            ObligationCauseCode::ImplDerivedHost(ref data) => {
3978                let self_ty = tcx.short_string(
3979                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty()),
3980                    err.long_ty_path(),
3981                );
3982                let trait_path = tcx.short_string(
3983                    data.derived
3984                        .parent_host_pred
3985                        .map_bound(|pred| pred.trait_ref)
3986                        .print_only_trait_path(),
3987                    err.long_ty_path(),
3988                );
3989                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required for `{1}` to implement `{0} {2}`",
                data.derived.parent_host_pred.skip_binder().constness,
                self_ty, trait_path))
    })format!(
3990                    "required for `{self_ty}` to implement `{} {trait_path}`",
3991                    data.derived.parent_host_pred.skip_binder().constness,
3992                );
3993                match tcx.hir_get_if_local(data.impl_def_id) {
3994                    Some(Node::Item(hir::Item {
3995                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
3996                        ..
3997                    })) => {
3998                        let mut spans = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [self_ty.span]))vec![self_ty.span];
3999                        spans.extend(of_trait.map(|t| t.trait_ref.path.span));
4000                        let mut spans: MultiSpan = spans.into();
4001                        spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
4002                        err.span_note(spans, msg);
4003                    }
4004                    _ => {
4005                        err.note(msg);
4006                    }
4007                }
4008                ensure_sufficient_stack(|| {
4009                    self.note_obligation_cause_code(
4010                        body_id,
4011                        err,
4012                        data.derived.parent_host_pred,
4013                        param_env,
4014                        &data.derived.parent_code,
4015                        obligated_types,
4016                        seen_requirements,
4017                    )
4018                });
4019            }
4020            ObligationCauseCode::BuiltinDerivedHost(ref data) => {
4021                ensure_sufficient_stack(|| {
4022                    self.note_obligation_cause_code(
4023                        body_id,
4024                        err,
4025                        data.parent_host_pred,
4026                        param_env,
4027                        &data.parent_code,
4028                        obligated_types,
4029                        seen_requirements,
4030                    )
4031                });
4032            }
4033            ObligationCauseCode::WellFormedDerived(ref data) => {
4034                let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
4035                let parent_predicate = parent_trait_ref;
4036                // #74711: avoid a stack overflow
4037                ensure_sufficient_stack(|| {
4038                    self.note_obligation_cause_code(
4039                        body_id,
4040                        err,
4041                        parent_predicate,
4042                        param_env,
4043                        &data.parent_code,
4044                        obligated_types,
4045                        seen_requirements,
4046                    )
4047                });
4048            }
4049            ObligationCauseCode::TypeAlias(ref nested, span, def_id) => {
4050                // #74711: avoid a stack overflow
4051                ensure_sufficient_stack(|| {
4052                    self.note_obligation_cause_code(
4053                        body_id,
4054                        err,
4055                        predicate,
4056                        param_env,
4057                        nested,
4058                        obligated_types,
4059                        seen_requirements,
4060                    )
4061                });
4062                let mut multispan = MultiSpan::from(span);
4063                multispan.push_span_label(span, "required by this bound");
4064                err.span_note(
4065                    multispan,
4066                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by a bound on the type alias `{0}`",
                tcx.item_name(def_id)))
    })format!("required by a bound on the type alias `{}`", tcx.item_name(def_id)),
4067                );
4068            }
4069            ObligationCauseCode::FunctionArg {
4070                arg_hir_id, call_hir_id, ref parent_code, ..
4071            } => {
4072                self.note_function_argument_obligation(
4073                    body_id,
4074                    err,
4075                    arg_hir_id,
4076                    parent_code,
4077                    param_env,
4078                    predicate,
4079                    call_hir_id,
4080                );
4081                ensure_sufficient_stack(|| {
4082                    self.note_obligation_cause_code(
4083                        body_id,
4084                        err,
4085                        predicate,
4086                        param_env,
4087                        parent_code,
4088                        obligated_types,
4089                        seen_requirements,
4090                    )
4091                });
4092            }
4093            // Suppress `compare_type_predicate_entailment` errors for RPITITs, since they
4094            // should be implied by the parent method.
4095            ObligationCauseCode::CompareImplItem { trait_item_def_id, .. }
4096                if tcx.is_impl_trait_in_trait(trait_item_def_id) => {}
4097            ObligationCauseCode::CompareImplItem { trait_item_def_id, kind, .. } => {
4098                let item_name = tcx.item_name(trait_item_def_id);
4099                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the requirement `{0}` appears on the `impl`\'s {1} `{2}` but not on the corresponding trait\'s {1}",
                predicate, kind, item_name))
    })format!(
4100                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
4101                     `{item_name}` but not on the corresponding trait's {kind}",
4102                );
4103                let sp = tcx
4104                    .opt_item_ident(trait_item_def_id)
4105                    .map(|i| i.span)
4106                    .unwrap_or_else(|| tcx.def_span(trait_item_def_id));
4107                let mut assoc_span: MultiSpan = sp.into();
4108                assoc_span.push_span_label(
4109                    sp,
4110                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this trait\'s {0} doesn\'t have the requirement `{1}`",
                kind, predicate))
    })format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
4111                );
4112                if let Some(ident) = tcx
4113                    .opt_associated_item(trait_item_def_id)
4114                    .and_then(|i| tcx.opt_item_ident(i.container_id(tcx)))
4115                {
4116                    assoc_span.push_span_label(ident.span, "in this trait");
4117                }
4118                err.span_note(assoc_span, msg);
4119            }
4120            ObligationCauseCode::TrivialBound => {
4121                tcx.disabled_nightly_features(err, [(String::new(), sym::trivial_bounds)]);
4122            }
4123            ObligationCauseCode::OpaqueReturnType(expr_info) => {
4124                let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
4125                    let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
4126                    let expr = tcx.hir_expect_expr(hir_id);
4127                    (expr_ty, expr)
4128                } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
4129                    && let body = tcx.hir_body(body_id)
4130                    && let hir::ExprKind::Block(block, _) = body.value.kind
4131                    && let Some(expr) = block.expr
4132                    && let Some(expr_ty) = self
4133                        .typeck_results
4134                        .as_ref()
4135                        .and_then(|typeck| typeck.node_type_opt(expr.hir_id))
4136                    && let Some(pred) = predicate.as_clause()
4137                    && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
4138                    && self.can_eq(param_env, pred.self_ty(), expr_ty)
4139                {
4140                    let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
4141                    (expr_ty, expr)
4142                } else {
4143                    return;
4144                };
4145                err.span_label(
4146                    expr.span,
4147                    {
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("return type was inferred to be `{0}` here",
                    expr_ty))
        })
}with_forced_trimmed_paths!(format!(
4148                        "return type was inferred to be `{expr_ty}` here",
4149                    )),
4150                );
4151                suggest_remove_deref(err, &expr);
4152            }
4153            ObligationCauseCode::UnsizedNonPlaceExpr(span) => {
4154                err.span_note(
4155                    span,
4156                    "unsized values must be place expressions and cannot be put in temporaries",
4157                );
4158            }
4159            ObligationCauseCode::CompareEii { .. } => {
4160                {
    ::core::panicking::panic_fmt(format_args!("trait bounds on EII not yet supported "));
}panic!("trait bounds on EII not yet supported ")
4161            }
4162        }
4163    }
4164
4165    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("suggest_await_before_try",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(4165u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["obligation",
                                                    "trait_pred", "span", "trait_pred.self_ty"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_pred)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&trait_pred.self_ty())
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let future_trait =
                self.tcx.require_lang_item(LangItem::Future, span);
            let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
            let impls_future =
                self.type_implements_trait(future_trait,
                    [self.tcx.instantiate_bound_regions_with_erased(self_ty)],
                    obligation.param_env);
            if !impls_future.must_apply_modulo_regions() { return; }
            let item_def_id =
                self.tcx.associated_item_def_ids(future_trait)[0];
            let projection_ty =
                trait_pred.map_bound(|trait_pred|
                        {
                            Ty::new_projection(self.tcx, item_def_id,
                                [trait_pred.self_ty()])
                        });
            let InferOk { value: projection_ty, .. } =
                self.at(&obligation.cause,
                        obligation.param_env).normalize(projection_ty);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:4200",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(4200u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["normalized_projection_type"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&self.resolve_vars_if_possible(projection_ty))
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let try_obligation =
                self.mk_trait_obligation_with_new_self_ty(obligation.param_env,
                    trait_pred.map_bound(|trait_pred|
                            (trait_pred, projection_ty.skip_binder())));
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:4207",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(4207u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["try_trait_obligation"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&try_obligation)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            if self.predicate_may_hold(&try_obligation) &&
                        let Ok(snippet) =
                            self.tcx.sess.source_map().span_to_snippet(span) &&
                    snippet.ends_with('?') {
                match self.tcx.coroutine_kind(obligation.cause.body_id) {
                    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
                        _)) => {
                        err.span_suggestion_verbose(span.with_hi(span.hi() -
                                        BytePos(1)).shrink_to_hi(),
                            "consider `await`ing on the `Future`", ".await",
                            Applicability::MaybeIncorrect);
                    }
                    _ => {
                        let mut span: MultiSpan =
                            span.with_lo(span.hi() - BytePos(1)).into();
                        span.push_span_label(self.tcx.def_span(obligation.cause.body_id),
                            "this is not `async`");
                        err.span_note(span,
                            "this implements `Future` and its output type supports \
                        `?`, but the future cannot be awaited in a synchronous function");
                    }
                }
            }
        }
    }
}#[instrument(
4166        level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
4167    )]
4168    pub(super) fn suggest_await_before_try(
4169        &self,
4170        err: &mut Diag<'_>,
4171        obligation: &PredicateObligation<'tcx>,
4172        trait_pred: ty::PolyTraitPredicate<'tcx>,
4173        span: Span,
4174    ) {
4175        let future_trait = self.tcx.require_lang_item(LangItem::Future, span);
4176
4177        let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
4178        let impls_future = self.type_implements_trait(
4179            future_trait,
4180            [self.tcx.instantiate_bound_regions_with_erased(self_ty)],
4181            obligation.param_env,
4182        );
4183        if !impls_future.must_apply_modulo_regions() {
4184            return;
4185        }
4186
4187        let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
4188        // `<T as Future>::Output`
4189        let projection_ty = trait_pred.map_bound(|trait_pred| {
4190            Ty::new_projection(
4191                self.tcx,
4192                item_def_id,
4193                // Future::Output has no args
4194                [trait_pred.self_ty()],
4195            )
4196        });
4197        let InferOk { value: projection_ty, .. } =
4198            self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
4199
4200        debug!(
4201            normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
4202        );
4203        let try_obligation = self.mk_trait_obligation_with_new_self_ty(
4204            obligation.param_env,
4205            trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
4206        );
4207        debug!(try_trait_obligation = ?try_obligation);
4208        if self.predicate_may_hold(&try_obligation)
4209            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
4210            && snippet.ends_with('?')
4211        {
4212            match self.tcx.coroutine_kind(obligation.cause.body_id) {
4213                Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
4214                    err.span_suggestion_verbose(
4215                        span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
4216                        "consider `await`ing on the `Future`",
4217                        ".await",
4218                        Applicability::MaybeIncorrect,
4219                    );
4220                }
4221                _ => {
4222                    let mut span: MultiSpan = span.with_lo(span.hi() - BytePos(1)).into();
4223                    span.push_span_label(
4224                        self.tcx.def_span(obligation.cause.body_id),
4225                        "this is not `async`",
4226                    );
4227                    err.span_note(
4228                        span,
4229                        "this implements `Future` and its output type supports \
4230                        `?`, but the future cannot be awaited in a synchronous function",
4231                    );
4232                }
4233            }
4234        }
4235    }
4236
4237    pub(super) fn suggest_floating_point_literal(
4238        &self,
4239        obligation: &PredicateObligation<'tcx>,
4240        err: &mut Diag<'_>,
4241        trait_pred: ty::PolyTraitPredicate<'tcx>,
4242    ) {
4243        let rhs_span = match obligation.cause.code() {
4244            ObligationCauseCode::BinOp { rhs_span, rhs_is_lit, .. } if *rhs_is_lit => rhs_span,
4245            _ => return,
4246        };
4247        if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind()
4248            && let ty::Infer(InferTy::IntVar(_)) =
4249                trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
4250        {
4251            err.span_suggestion_verbose(
4252                rhs_span.shrink_to_hi(),
4253                "consider using a floating-point literal by writing it with `.0`",
4254                ".0",
4255                Applicability::MaybeIncorrect,
4256            );
4257        }
4258    }
4259
4260    pub fn can_suggest_derive(
4261        &self,
4262        obligation: &PredicateObligation<'tcx>,
4263        trait_pred: ty::PolyTraitPredicate<'tcx>,
4264    ) -> bool {
4265        if trait_pred.polarity() == ty::PredicatePolarity::Negative {
4266            return false;
4267        }
4268        let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
4269            return false;
4270        };
4271        let (adt, args) = match trait_pred.skip_binder().self_ty().kind() {
4272            ty::Adt(adt, args) if adt.did().is_local() => (adt, args),
4273            _ => return false,
4274        };
4275        let is_derivable_trait = match diagnostic_name {
4276            sym::Copy | sym::Clone => true,
4277            _ if adt.is_union() => false,
4278            sym::PartialEq | sym::PartialOrd => {
4279                let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
4280                trait_pred.skip_binder().self_ty() == rhs_ty
4281            }
4282            sym::Eq | sym::Ord | sym::Hash | sym::Debug | sym::Default => true,
4283            _ => false,
4284        };
4285        is_derivable_trait &&
4286            // Ensure all fields impl the trait.
4287            adt.all_fields().all(|field| {
4288                let field_ty = ty::GenericArg::from(field.ty(self.tcx, args));
4289                let trait_args = match diagnostic_name {
4290                    sym::PartialEq | sym::PartialOrd => {
4291                        Some(field_ty)
4292                    }
4293                    _ => None,
4294                };
4295                let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
4296                    trait_ref: ty::TraitRef::new(self.tcx,
4297                        trait_pred.def_id(),
4298                        [field_ty].into_iter().chain(trait_args),
4299                    ),
4300                    ..*tr
4301                });
4302                let field_obl = Obligation::new(
4303                    self.tcx,
4304                    obligation.cause.clone(),
4305                    obligation.param_env,
4306                    trait_pred,
4307                );
4308                self.predicate_must_hold_modulo_regions(&field_obl)
4309            })
4310    }
4311
4312    pub fn suggest_derive(
4313        &self,
4314        obligation: &PredicateObligation<'tcx>,
4315        err: &mut Diag<'_>,
4316        trait_pred: ty::PolyTraitPredicate<'tcx>,
4317    ) {
4318        let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
4319            return;
4320        };
4321        let adt = match trait_pred.skip_binder().self_ty().kind() {
4322            ty::Adt(adt, _) if adt.did().is_local() => adt,
4323            _ => return,
4324        };
4325        if self.can_suggest_derive(obligation, trait_pred) {
4326            err.span_suggestion_verbose(
4327                self.tcx.def_span(adt.did()).shrink_to_lo(),
4328                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider annotating `{0}` with `#[derive({1})]`",
                trait_pred.skip_binder().self_ty(), diagnostic_name))
    })format!(
4329                    "consider annotating `{}` with `#[derive({})]`",
4330                    trait_pred.skip_binder().self_ty(),
4331                    diagnostic_name,
4332                ),
4333                // FIXME(const_trait_impl) derive_const as suggestion?
4334                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[derive({0})]\n",
                diagnostic_name))
    })format!("#[derive({diagnostic_name})]\n"),
4335                Applicability::MaybeIncorrect,
4336            );
4337        }
4338    }
4339
4340    pub(super) fn suggest_dereferencing_index(
4341        &self,
4342        obligation: &PredicateObligation<'tcx>,
4343        err: &mut Diag<'_>,
4344        trait_pred: ty::PolyTraitPredicate<'tcx>,
4345    ) {
4346        if let ObligationCauseCode::ImplDerived(_) = obligation.cause.code()
4347            && self
4348                .tcx
4349                .is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
4350            && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
4351            && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
4352            && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
4353        {
4354            err.span_suggestion_verbose(
4355                obligation.cause.span.shrink_to_lo(),
4356                "dereference this index",
4357                '*',
4358                Applicability::MachineApplicable,
4359            );
4360        }
4361    }
4362
4363    fn note_function_argument_obligation<G: EmissionGuarantee>(
4364        &self,
4365        body_id: LocalDefId,
4366        err: &mut Diag<'_, G>,
4367        arg_hir_id: HirId,
4368        parent_code: &ObligationCauseCode<'tcx>,
4369        param_env: ty::ParamEnv<'tcx>,
4370        failed_pred: ty::Predicate<'tcx>,
4371        call_hir_id: HirId,
4372    ) {
4373        let tcx = self.tcx;
4374        if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
4375            && let Some(typeck_results) = &self.typeck_results
4376        {
4377            if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr
4378                && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id)
4379                && let Some(failed_pred) = failed_pred.as_trait_clause()
4380                && let pred = failed_pred.map_bound(|pred| pred.with_replaced_self_ty(tcx, ty))
4381                && self.predicate_must_hold_modulo_regions(&Obligation::misc(
4382                    tcx, expr.span, body_id, param_env, pred,
4383                ))
4384                && expr.span.hi() != rcvr.span.hi()
4385            {
4386                let should_sugg = match tcx.hir_node(call_hir_id) {
4387                    Node::Expr(hir::Expr {
4388                        kind: hir::ExprKind::MethodCall(_, call_receiver, _, _),
4389                        ..
4390                    }) if let Some((DefKind::AssocFn, did)) =
4391                        typeck_results.type_dependent_def(call_hir_id)
4392                        && call_receiver.hir_id == arg_hir_id =>
4393                    {
4394                        // Avoid suggesting removing a method call if the argument is the receiver of the parent call and
4395                        // removing the receiver would make the method inaccessible. i.e. `x.a().b()`, suggesting removing
4396                        // `.a()` could change the type and make `.b()` unavailable.
4397                        if tcx.inherent_impl_of_assoc(did).is_some() {
4398                            // if we're calling an inherent impl method, just try to make sure that the receiver type stays the same.
4399                            Some(ty) == typeck_results.node_type_opt(arg_hir_id)
4400                        } else {
4401                            // we're calling a trait method, so we just check removing the method call still satisfies the trait.
4402                            let trait_id = tcx
4403                                .trait_of_assoc(did)
4404                                .unwrap_or_else(|| tcx.impl_trait_id(tcx.parent(did)));
4405                            let args = typeck_results.node_args(call_hir_id);
4406                            let tr = ty::TraitRef::from_assoc(tcx, trait_id, args)
4407                                .with_replaced_self_ty(tcx, ty);
4408                            self.type_implements_trait(tr.def_id, tr.args, param_env)
4409                                .must_apply_modulo_regions()
4410                        }
4411                    }
4412                    _ => true,
4413                };
4414
4415                if should_sugg {
4416                    err.span_suggestion_verbose(
4417                        expr.span.with_lo(rcvr.span.hi()),
4418                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider removing this method call, as the receiver has type `{0}` and `{1}` trivially holds",
                ty, pred))
    })format!(
4419                            "consider removing this method call, as the receiver has type `{ty}` and \
4420                            `{pred}` trivially holds",
4421                        ),
4422                        "",
4423                        Applicability::MaybeIncorrect,
4424                    );
4425                }
4426            }
4427            if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
4428                let inner_expr = expr.peel_blocks();
4429                let ty = typeck_results
4430                    .expr_ty_adjusted_opt(inner_expr)
4431                    .unwrap_or(Ty::new_misc_error(tcx));
4432                let span = inner_expr.span;
4433                if Some(span) != err.span.primary_span()
4434                    && !span.in_external_macro(tcx.sess.source_map())
4435                {
4436                    err.span_label(
4437                        span,
4438                        if ty.references_error() {
4439                            String::new()
4440                        } else {
4441                            let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4442                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this tail expression is of type `{0}`",
                ty))
    })format!("this tail expression is of type `{ty}`")
4443                        },
4444                    );
4445                    if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
4446                        && let ty::ClauseKind::Trait(pred) = clause
4447                        && tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
4448                    {
4449                        if let [stmt, ..] = block.stmts
4450                            && let hir::StmtKind::Semi(value) = stmt.kind
4451                            && let hir::ExprKind::Closure(hir::Closure {
4452                                body, fn_decl_span, ..
4453                            }) = value.kind
4454                            && let body = tcx.hir_body(*body)
4455                            && !#[allow(non_exhaustive_omitted_patterns)] match body.value.kind {
    hir::ExprKind::Block(..) => true,
    _ => false,
}matches!(body.value.kind, hir::ExprKind::Block(..))
4456                        {
4457                            // Check if the failed predicate was an expectation of a closure type
4458                            // and if there might have been a `{ |args|` typo instead of `|args| {`.
4459                            err.multipart_suggestion(
4460                                "you might have meant to open the closure body instead of placing \
4461                                 a closure within a block",
4462                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(expr.span.with_hi(value.span.lo()), String::new()),
                (fn_decl_span.shrink_to_hi(), " {".to_string())]))vec![
4463                                    (expr.span.with_hi(value.span.lo()), String::new()),
4464                                    (fn_decl_span.shrink_to_hi(), " {".to_string()),
4465                                ],
4466                                Applicability::MaybeIncorrect,
4467                            );
4468                        } else {
4469                            // Maybe the bare block was meant to be a closure.
4470                            err.span_suggestion_verbose(
4471                                expr.span.shrink_to_lo(),
4472                                "you might have meant to create the closure instead of a block",
4473                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("|{0}| ",
                (0..pred.trait_ref.args.len() -
                                        1).map(|_| "_").collect::<Vec<_>>().join(", ")))
    })format!(
4474                                    "|{}| ",
4475                                    (0..pred.trait_ref.args.len() - 1)
4476                                        .map(|_| "_")
4477                                        .collect::<Vec<_>>()
4478                                        .join(", ")
4479                                ),
4480                                Applicability::MaybeIncorrect,
4481                            );
4482                        }
4483                    }
4484                }
4485            }
4486
4487            // FIXME: visit the ty to see if there's any closure involved, and if there is,
4488            // check whether its evaluated return type is the same as the one corresponding
4489            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
4490            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
4491            let mut type_diffs = ::alloc::vec::Vec::new()vec![];
4492            if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = *parent_code
4493                && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
4494                && let where_clauses =
4495                    self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
4496                && let Some(where_pred) = where_clauses.predicates.get(idx)
4497            {
4498                if let Some(where_pred) = where_pred.as_trait_clause()
4499                    && let Some(failed_pred) = failed_pred.as_trait_clause()
4500                    && where_pred.def_id() == failed_pred.def_id()
4501                {
4502                    self.enter_forall(where_pred, |where_pred| {
4503                        let failed_pred = self.instantiate_binder_with_fresh_vars(
4504                            expr.span,
4505                            BoundRegionConversionTime::FnCall,
4506                            failed_pred,
4507                        );
4508
4509                        let zipped =
4510                            iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
4511                        for (expected, actual) in zipped {
4512                            self.probe(|_| {
4513                                match self
4514                                    .at(&ObligationCause::misc(expr.span, body_id), param_env)
4515                                    // Doesn't actually matter if we define opaque types here, this is just used for
4516                                    // diagnostics, and the result is never kept around.
4517                                    .eq(DefineOpaqueTypes::Yes, expected, actual)
4518                                {
4519                                    Ok(_) => (), // We ignore nested obligations here for now.
4520                                    Err(err) => type_diffs.push(err),
4521                                }
4522                            })
4523                        }
4524                    })
4525                } else if let Some(where_pred) = where_pred.as_projection_clause()
4526                    && let Some(failed_pred) = failed_pred.as_projection_clause()
4527                    && let Some(found) = failed_pred.skip_binder().term.as_type()
4528                {
4529                    type_diffs = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [TypeError::Sorts(ty::error::ExpectedFound {
                        expected: where_pred.skip_binder().projection_term.expect_ty(self.tcx).to_ty(self.tcx),
                        found,
                    })]))vec![TypeError::Sorts(ty::error::ExpectedFound {
4530                        expected: where_pred
4531                            .skip_binder()
4532                            .projection_term
4533                            .expect_ty(self.tcx)
4534                            .to_ty(self.tcx),
4535                        found,
4536                    })];
4537                }
4538            }
4539            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
4540                && let hir::Path { res: Res::Local(hir_id), .. } = path
4541                && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
4542                && let hir::Node::LetStmt(local) = self.tcx.parent_hir_node(binding.hir_id)
4543                && let Some(binding_expr) = local.init
4544            {
4545                // If the expression we're calling on is a binding, we want to point at the
4546                // `let` when talking about the type. Otherwise we'll point at every part
4547                // of the method chain with the type.
4548                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
4549            } else {
4550                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
4551            }
4552        }
4553        let call_node = tcx.hir_node(call_hir_id);
4554        if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) =
4555            call_node
4556        {
4557            if Some(rcvr.span) == err.span.primary_span() {
4558                err.replace_span_with(path.ident.span, true);
4559            }
4560        }
4561
4562        if let Node::Expr(expr) = call_node {
4563            if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
4564            | hir::ExprKind::MethodCall(
4565                hir::PathSegment { ident: Ident { span, .. }, .. },
4566                ..,
4567            ) = expr.kind
4568            {
4569                if Some(*span) != err.span.primary_span() {
4570                    let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true })
4571                    {
4572                        "required by this formatting parameter"
4573                    } else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) {
4574                        "required by a formatting parameter in this expression"
4575                    } else {
4576                        "required by a bound introduced by this call"
4577                    };
4578                    err.span_label(*span, msg);
4579                }
4580            }
4581
4582            if let hir::ExprKind::MethodCall(_, expr, ..) = expr.kind {
4583                self.suggest_option_method_if_applicable(failed_pred, param_env, err, expr);
4584            }
4585        }
4586    }
4587
4588    fn suggest_option_method_if_applicable<G: EmissionGuarantee>(
4589        &self,
4590        failed_pred: ty::Predicate<'tcx>,
4591        param_env: ty::ParamEnv<'tcx>,
4592        err: &mut Diag<'_, G>,
4593        expr: &hir::Expr<'_>,
4594    ) {
4595        let tcx = self.tcx;
4596        let infcx = self.infcx;
4597        let Some(typeck_results) = self.typeck_results.as_ref() else { return };
4598
4599        // Make sure we're dealing with the `Option` type.
4600        let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
4601            return;
4602        };
4603        if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
4604            return;
4605        }
4606
4607        // Given the predicate `fn(&T): FnOnce<(U,)>`, extract `fn(&T)` and `(U,)`,
4608        // then suggest `Option::as_deref(_mut)` if `U` can deref to `T`
4609        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, .. }))
4610            = failed_pred.kind().skip_binder()
4611            && tcx.is_fn_trait(trait_ref.def_id)
4612            && let [self_ty, found_ty] = trait_ref.args.as_slice()
4613            && let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
4614            && let fn_sig @ ty::FnSig {
4615                abi: ExternAbi::Rust,
4616                c_variadic: false,
4617                safety: hir::Safety::Safe,
4618                ..
4619            } = fn_ty.fn_sig(tcx).skip_binder()
4620
4621            // Extract first param of fn sig with peeled refs, e.g. `fn(&T)` -> `T`
4622            && let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
4623            && !target_ty.has_escaping_bound_vars()
4624
4625            // Extract first tuple element out of fn trait, e.g. `FnOnce<(U,)>` -> `U`
4626            && let Some(ty::Tuple(tys)) = found_ty.as_type().map(Ty::kind)
4627            && let &[found_ty] = tys.as_slice()
4628            && !found_ty.has_escaping_bound_vars()
4629
4630            // Extract `<U as Deref>::Target` assoc type and check that it is `T`
4631            && let Some(deref_target_did) = tcx.lang_items().deref_target()
4632            && let projection = Ty::new_projection_from_args(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
4633            && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
4634            && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
4635            && infcx.can_eq(param_env, deref_target, target_ty)
4636        {
4637            let help = if let hir::Mutability::Mut = needs_mut
4638                && let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()
4639                && infcx
4640                    .type_implements_trait(deref_mut_did, iter::once(found_ty), param_env)
4641                    .must_apply_modulo_regions()
4642            {
4643                Some(("call `Option::as_deref_mut()` first", ".as_deref_mut()"))
4644            } else if let hir::Mutability::Not = needs_mut {
4645                Some(("call `Option::as_deref()` first", ".as_deref()"))
4646            } else {
4647                None
4648            };
4649
4650            if let Some((msg, sugg)) = help {
4651                err.span_suggestion_with_style(
4652                    expr.span.shrink_to_hi(),
4653                    msg,
4654                    sugg,
4655                    Applicability::MaybeIncorrect,
4656                    SuggestionStyle::ShowAlways,
4657                );
4658            }
4659        }
4660    }
4661
4662    fn look_for_iterator_item_mistakes<G: EmissionGuarantee>(
4663        &self,
4664        assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
4665        typeck_results: &TypeckResults<'tcx>,
4666        type_diffs: &[TypeError<'tcx>],
4667        param_env: ty::ParamEnv<'tcx>,
4668        path_segment: &hir::PathSegment<'_>,
4669        args: &[hir::Expr<'_>],
4670        prev_ty: Ty<'_>,
4671        err: &mut Diag<'_, G>,
4672    ) {
4673        let tcx = self.tcx;
4674        // Special case for iterator chains, we look at potential failures of `Iterator::Item`
4675        // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`.
4676        for entry in assocs_in_this_method {
4677            let Some((_span, (def_id, ty))) = entry else {
4678                continue;
4679            };
4680            for diff in type_diffs {
4681                let TypeError::Sorts(expected_found) = diff else {
4682                    continue;
4683                };
4684                if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4685                    && path_segment.ident.name == sym::iter
4686                    && self.can_eq(
4687                        param_env,
4688                        Ty::new_ref(
4689                            tcx,
4690                            tcx.lifetimes.re_erased,
4691                            expected_found.found,
4692                            ty::Mutability::Not,
4693                        ),
4694                        *ty,
4695                    )
4696                    && let [] = args
4697                {
4698                    // Used `.iter()` when `.into_iter()` was likely meant.
4699                    err.span_suggestion_verbose(
4700                        path_segment.ident.span,
4701                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider consuming the `{0}` to construct the `Iterator`",
                prev_ty))
    })format!("consider consuming the `{prev_ty}` to construct the `Iterator`"),
4702                        "into_iter".to_string(),
4703                        Applicability::MachineApplicable,
4704                    );
4705                }
4706                if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4707                    && path_segment.ident.name == sym::into_iter
4708                    && self.can_eq(
4709                        param_env,
4710                        expected_found.found,
4711                        Ty::new_ref(tcx, tcx.lifetimes.re_erased, *ty, ty::Mutability::Not),
4712                    )
4713                    && let [] = args
4714                {
4715                    // Used `.into_iter()` when `.iter()` was likely meant.
4716                    err.span_suggestion_verbose(
4717                        path_segment.ident.span,
4718                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider not consuming the `{0}` to construct the `Iterator`",
                prev_ty))
    })format!(
4719                            "consider not consuming the `{prev_ty}` to construct the `Iterator`"
4720                        ),
4721                        "iter".to_string(),
4722                        Applicability::MachineApplicable,
4723                    );
4724                }
4725                if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
4726                    && path_segment.ident.name == sym::map
4727                    && self.can_eq(param_env, expected_found.found, *ty)
4728                    && let [arg] = args
4729                    && let hir::ExprKind::Closure(closure) = arg.kind
4730                {
4731                    let body = tcx.hir_body(closure.body);
4732                    if let hir::ExprKind::Block(block, None) = body.value.kind
4733                        && let None = block.expr
4734                        && let [.., stmt] = block.stmts
4735                        && let hir::StmtKind::Semi(expr) = stmt.kind
4736                        // FIXME: actually check the expected vs found types, but right now
4737                        // the expected is a projection that we need to resolve.
4738                        // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
4739                        && expected_found.found.is_unit()
4740                        // FIXME: this happens with macro calls. Need to figure out why the stmt
4741                        // `println!();` doesn't include the `;` in its `Span`. (#133845)
4742                        // We filter these out to avoid ICEs with debug assertions on caused by
4743                        // empty suggestions.
4744                        && expr.span.hi() != stmt.span.hi()
4745                    {
4746                        err.span_suggestion_verbose(
4747                            expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
4748                            "consider removing this semicolon",
4749                            String::new(),
4750                            Applicability::MachineApplicable,
4751                        );
4752                    }
4753                    let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
4754                        && let Some(expr) = block.expr
4755                    {
4756                        expr
4757                    } else {
4758                        body.value
4759                    };
4760                    if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
4761                        && path_segment.ident.name == sym::clone
4762                        && let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
4763                        && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
4764                        && self.can_eq(param_env, expr_ty, rcvr_ty)
4765                        && let ty::Ref(_, ty, _) = expr_ty.kind()
4766                    {
4767                        err.span_label(
4768                            span,
4769                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this method call is cloning the reference `{0}`, not `{1}` which doesn\'t implement `Clone`",
                expr_ty, ty))
    })format!(
4770                                "this method call is cloning the reference `{expr_ty}`, not \
4771                                 `{ty}` which doesn't implement `Clone`",
4772                            ),
4773                        );
4774                        let ty::Param(..) = ty.kind() else {
4775                            continue;
4776                        };
4777                        let node =
4778                            tcx.hir_node_by_def_id(tcx.hir_get_parent_item(expr.hir_id).def_id);
4779
4780                        let pred = ty::Binder::dummy(ty::TraitPredicate {
4781                            trait_ref: ty::TraitRef::new(
4782                                tcx,
4783                                tcx.require_lang_item(LangItem::Clone, span),
4784                                [*ty],
4785                            ),
4786                            polarity: ty::PredicatePolarity::Positive,
4787                        });
4788                        let Some(generics) = node.generics() else {
4789                            continue;
4790                        };
4791                        let Some(body_id) = node.body_id() else {
4792                            continue;
4793                        };
4794                        suggest_restriction(
4795                            tcx,
4796                            tcx.hir_body_owner_def_id(body_id),
4797                            generics,
4798                            &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("type parameter `{0}`", ty))
    })format!("type parameter `{ty}`"),
4799                            err,
4800                            node.fn_sig(),
4801                            None,
4802                            pred,
4803                            None,
4804                        );
4805                    }
4806                }
4807            }
4808        }
4809    }
4810
4811    fn point_at_chain<G: EmissionGuarantee>(
4812        &self,
4813        expr: &hir::Expr<'_>,
4814        typeck_results: &TypeckResults<'tcx>,
4815        type_diffs: Vec<TypeError<'tcx>>,
4816        param_env: ty::ParamEnv<'tcx>,
4817        err: &mut Diag<'_, G>,
4818    ) {
4819        let mut primary_spans = ::alloc::vec::Vec::new()vec![];
4820        let mut span_labels = ::alloc::vec::Vec::new()vec![];
4821
4822        let tcx = self.tcx;
4823
4824        let mut print_root_expr = true;
4825        let mut assocs = ::alloc::vec::Vec::new()vec![];
4826        let mut expr = expr;
4827        let mut prev_ty = self.resolve_vars_if_possible(
4828            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4829        );
4830        while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {
4831            // Point at every method call in the chain with the resulting type.
4832            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
4833            //               ^^^^^^ ^^^^^^^^^^^
4834            expr = rcvr_expr;
4835            let assocs_in_this_method =
4836                self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
4837            prev_ty = self.resolve_vars_if_possible(
4838                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4839            );
4840            self.look_for_iterator_item_mistakes(
4841                &assocs_in_this_method,
4842                typeck_results,
4843                &type_diffs,
4844                param_env,
4845                path_segment,
4846                args,
4847                prev_ty,
4848                err,
4849            );
4850            assocs.push(assocs_in_this_method);
4851
4852            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
4853                && let hir::Path { res: Res::Local(hir_id), .. } = path
4854                && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
4855            {
4856                let parent = self.tcx.parent_hir_node(binding.hir_id);
4857                // We've reached the root of the method call chain...
4858                if let hir::Node::LetStmt(local) = parent
4859                    && let Some(binding_expr) = local.init
4860                {
4861                    // ...and it is a binding. Get the binding creation and continue the chain.
4862                    expr = binding_expr;
4863                }
4864                if let hir::Node::Param(param) = parent {
4865                    // ...and it is an fn argument.
4866                    let prev_ty = self.resolve_vars_if_possible(
4867                        typeck_results
4868                            .node_type_opt(param.hir_id)
4869                            .unwrap_or(Ty::new_misc_error(tcx)),
4870                    );
4871                    let assocs_in_this_method = self.probe_assoc_types_at_expr(
4872                        &type_diffs,
4873                        param.ty_span,
4874                        prev_ty,
4875                        param.hir_id,
4876                        param_env,
4877                    );
4878                    if assocs_in_this_method.iter().any(|a| a.is_some()) {
4879                        assocs.push(assocs_in_this_method);
4880                        print_root_expr = false;
4881                    }
4882                    break;
4883                }
4884            }
4885        }
4886        // We want the type before deref coercions, otherwise we talk about `&[_]`
4887        // instead of `Vec<_>`.
4888        if let Some(ty) = typeck_results.expr_ty_opt(expr)
4889            && print_root_expr
4890        {
4891            let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4892            // Point at the root expression
4893            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
4894            // ^^^^^^^^^^^^^
4895            span_labels.push((expr.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this expression has type `{0}`",
                ty))
    })format!("this expression has type `{ty}`")));
4896        };
4897        // Only show this if it is not a "trivial" expression (not a method
4898        // chain) and there are associated types to talk about.
4899        let mut assocs = assocs.into_iter().peekable();
4900        while let Some(assocs_in_method) = assocs.next() {
4901            let Some(prev_assoc_in_method) = assocs.peek() else {
4902                for entry in assocs_in_method {
4903                    let Some((span, (assoc, ty))) = entry else {
4904                        continue;
4905                    };
4906                    if primary_spans.is_empty()
4907                        || type_diffs.iter().any(|diff| {
4908                            let TypeError::Sorts(expected_found) = diff else {
4909                                return false;
4910                            };
4911                            self.can_eq(param_env, expected_found.found, ty)
4912                        })
4913                    {
4914                        // FIXME: this doesn't quite work for `Iterator::collect`
4915                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
4916                        // to point at the `.into_iter()` call, but as long as we
4917                        // still point at the other method calls that might have
4918                        // introduced the issue, this is fine for now.
4919                        primary_spans.push(span);
4920                    }
4921                    span_labels.push((
4922                        span,
4923                        {
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("`{0}` is `{1}` here",
                    self.tcx.def_path_str(assoc), ty))
        })
}with_forced_trimmed_paths!(format!(
4924                            "`{}` is `{ty}` here",
4925                            self.tcx.def_path_str(assoc),
4926                        )),
4927                    ));
4928                }
4929                break;
4930            };
4931            for (entry, prev_entry) in
4932                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
4933            {
4934                match (entry, prev_entry) {
4935                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
4936                        let ty_str = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4937
4938                        let assoc = { let _guard = ForceTrimmedGuard::new(); self.tcx.def_path_str(assoc) }with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
4939                        if !self.can_eq(param_env, ty, *prev_ty) {
4940                            if type_diffs.iter().any(|diff| {
4941                                let TypeError::Sorts(expected_found) = diff else {
4942                                    return false;
4943                                };
4944                                self.can_eq(param_env, expected_found.found, ty)
4945                            }) {
4946                                primary_spans.push(span);
4947                            }
4948                            span_labels
4949                                .push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` changed to `{1}` here",
                assoc, ty_str))
    })format!("`{assoc}` changed to `{ty_str}` here")));
4950                        } else {
4951                            span_labels.push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` remains `{1}` here", assoc,
                ty_str))
    })format!("`{assoc}` remains `{ty_str}` here")));
4952                        }
4953                    }
4954                    (Some((span, (assoc, ty))), None) => {
4955                        span_labels.push((
4956                            span,
4957                            {
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("`{0}` is `{1}` here",
                    self.tcx.def_path_str(assoc), self.ty_to_string(ty)))
        })
}with_forced_trimmed_paths!(format!(
4958                                "`{}` is `{}` here",
4959                                self.tcx.def_path_str(assoc),
4960                                self.ty_to_string(ty),
4961                            )),
4962                        ));
4963                    }
4964                    (None, Some(_)) | (None, None) => {}
4965                }
4966            }
4967        }
4968        if !primary_spans.is_empty() {
4969            let mut multi_span: MultiSpan = primary_spans.into();
4970            for (span, label) in span_labels {
4971                multi_span.push_span_label(span, label);
4972            }
4973            err.span_note(
4974                multi_span,
4975                "the method call chain might not have had the expected associated types",
4976            );
4977        }
4978    }
4979
4980    fn probe_assoc_types_at_expr(
4981        &self,
4982        type_diffs: &[TypeError<'tcx>],
4983        span: Span,
4984        prev_ty: Ty<'tcx>,
4985        body_id: HirId,
4986        param_env: ty::ParamEnv<'tcx>,
4987    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
4988        let ocx = ObligationCtxt::new(self.infcx);
4989        let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
4990        for diff in type_diffs {
4991            let TypeError::Sorts(expected_found) = diff else {
4992                continue;
4993            };
4994            let ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. }) =
4995                expected_found.expected.kind()
4996            else {
4997                continue;
4998            };
4999
5000            // Make `Self` be equivalent to the type of the call chain
5001            // expression we're looking at now, so that we can tell what
5002            // for example `Iterator::Item` is at this point in the chain.
5003            let args = GenericArgs::for_item(self.tcx, *def_id, |param, _| {
5004                if param.index == 0 {
5005                    if true {
    match param.kind {
        ty::GenericParamDefKind::Type { .. } => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "ty::GenericParamDefKind::Type { .. }",
                ::core::option::Option::None);
        }
    };
};debug_assert_matches!(param.kind, ty::GenericParamDefKind::Type { .. });
5006                    return prev_ty.into();
5007                }
5008                self.var_for_def(span, param)
5009            });
5010            // This will hold the resolved type of the associated type, if the
5011            // current expression implements the trait that associated type is
5012            // in. For example, this would be what `Iterator::Item` is here.
5013            let ty = self.infcx.next_ty_var(span);
5014            // This corresponds to `<ExprTy as Iterator>::Item = _`.
5015            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
5016                ty::ClauseKind::Projection(ty::ProjectionPredicate {
5017                    projection_term: ty::AliasTerm::new_from_args(self.tcx, *def_id, args),
5018                    term: ty.into(),
5019                }),
5020            ));
5021            let body_def_id = self.tcx.hir_enclosing_body_owner(body_id);
5022            // Add `<ExprTy as Iterator>::Item = _` obligation.
5023            ocx.register_obligation(Obligation::misc(
5024                self.tcx,
5025                span,
5026                body_def_id,
5027                param_env,
5028                projection,
5029            ));
5030            if ocx.try_evaluate_obligations().is_empty()
5031                && let ty = self.resolve_vars_if_possible(ty)
5032                && !ty.is_ty_var()
5033            {
5034                assocs_in_this_method.push(Some((span, (*def_id, ty))));
5035            } else {
5036                // `<ExprTy as Iterator>` didn't select, so likely we've
5037                // reached the end of the iterator chain, like the originating
5038                // `Vec<_>` or the `ty` couldn't be determined.
5039                // Keep the space consistent for later zipping.
5040                assocs_in_this_method.push(None);
5041            }
5042        }
5043        assocs_in_this_method
5044    }
5045
5046    /// If the type that failed selection is an array or a reference to an array,
5047    /// but the trait is implemented for slices, suggest that the user converts
5048    /// the array into a slice.
5049    pub(super) fn suggest_convert_to_slice(
5050        &self,
5051        err: &mut Diag<'_>,
5052        obligation: &PredicateObligation<'tcx>,
5053        trait_pred: ty::PolyTraitPredicate<'tcx>,
5054        candidate_impls: &[ImplCandidate<'tcx>],
5055        span: Span,
5056    ) {
5057        if span.in_external_macro(self.tcx.sess.source_map()) {
5058            return;
5059        }
5060        // We can only suggest the slice coercion for function and binary operation arguments,
5061        // since the suggestion would make no sense in turbofish or call
5062        let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
5063            obligation.cause.code()
5064        else {
5065            return;
5066        };
5067
5068        // Three cases where we can make a suggestion:
5069        // 1. `[T; _]` (array of T)
5070        // 2. `&[T; _]` (reference to array of T)
5071        // 3. `&mut [T; _]` (mutable reference to array of T)
5072        let (element_ty, mut mutability) = match *trait_pred.skip_binder().self_ty().kind() {
5073            ty::Array(element_ty, _) => (element_ty, None),
5074
5075            ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() {
5076                ty::Array(element_ty, _) => (element_ty, Some(mutability)),
5077                _ => return,
5078            },
5079
5080            _ => return,
5081        };
5082
5083        // Go through all the candidate impls to see if any of them is for
5084        // slices of `element_ty` with `mutability`.
5085        let mut is_slice = |candidate: Ty<'tcx>| match *candidate.kind() {
5086            ty::RawPtr(t, m) | ty::Ref(_, t, m) => {
5087                if let ty::Slice(e) = *t.kind()
5088                    && e == element_ty
5089                    && m == mutability.unwrap_or(m)
5090                {
5091                    // Use the candidate's mutability going forward.
5092                    mutability = Some(m);
5093                    true
5094                } else {
5095                    false
5096                }
5097            }
5098            _ => false,
5099        };
5100
5101        // Grab the first candidate that matches, if any, and make a suggestion.
5102        if let Some(slice_ty) = candidate_impls
5103            .iter()
5104            .map(|trait_ref| trait_ref.trait_ref.self_ty())
5105            .find(|t| is_slice(*t))
5106        {
5107            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("convert the array to a `{0}` slice instead",
                slice_ty))
    })format!("convert the array to a `{slice_ty}` slice instead");
5108
5109            if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
5110                let mut suggestions = ::alloc::vec::Vec::new()vec![];
5111                if snippet.starts_with('&') {
5112                } else if let Some(hir::Mutability::Mut) = mutability {
5113                    suggestions.push((span.shrink_to_lo(), "&mut ".into()));
5114                } else {
5115                    suggestions.push((span.shrink_to_lo(), "&".into()));
5116                }
5117                suggestions.push((span.shrink_to_hi(), "[..]".into()));
5118                err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
5119            } else {
5120                err.span_help(span, msg);
5121            }
5122        }
5123    }
5124
5125    /// If the type failed selection but the trait is implemented for `(T,)`, suggest that the user
5126    /// creates a unary tuple
5127    ///
5128    /// This is a common gotcha when using libraries that emulate variadic functions with traits for tuples.
5129    pub(super) fn suggest_tuple_wrapping(
5130        &self,
5131        err: &mut Diag<'_>,
5132        root_obligation: &PredicateObligation<'tcx>,
5133        obligation: &PredicateObligation<'tcx>,
5134    ) {
5135        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else {
5136            return;
5137        };
5138
5139        let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return };
5140
5141        let trait_ref = root_pred.map_bound(|root_pred| {
5142            root_pred.trait_ref.with_replaced_self_ty(
5143                self.tcx,
5144                Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()]),
5145            )
5146        });
5147
5148        let obligation =
5149            Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref);
5150
5151        if self.predicate_must_hold_modulo_regions(&obligation) {
5152            let arg_span = self.tcx.hir_span(*arg_hir_id);
5153            err.multipart_suggestion(
5154                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use a unary tuple instead"))
    })format!("use a unary tuple instead"),
5155                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(arg_span.shrink_to_lo(), "(".into()),
                (arg_span.shrink_to_hi(), ",)".into())]))vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())],
5156                Applicability::MaybeIncorrect,
5157            );
5158        }
5159    }
5160
5161    pub(super) fn suggest_shadowed_inherent_method(
5162        &self,
5163        err: &mut Diag<'_>,
5164        obligation: &PredicateObligation<'tcx>,
5165        trait_predicate: ty::PolyTraitPredicate<'tcx>,
5166    ) {
5167        let ObligationCauseCode::FunctionArg { call_hir_id, .. } = obligation.cause.code() else {
5168            return;
5169        };
5170        let Node::Expr(call) = self.tcx.hir_node(*call_hir_id) else { return };
5171        let hir::ExprKind::MethodCall(segment, rcvr, args, ..) = call.kind else { return };
5172        let Some(typeck) = &self.typeck_results else { return };
5173        let Some(rcvr_ty) = typeck.expr_ty_adjusted_opt(rcvr) else { return };
5174        let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
5175        let autoderef = (self.autoderef_steps)(rcvr_ty);
5176        for (ty, def_id) in autoderef.iter().filter_map(|(ty, obligations)| {
5177            if let ty::Adt(def, _) = ty.kind()
5178                && *ty != rcvr_ty.peel_refs()
5179                && obligations.iter().all(|obligation| self.predicate_may_hold(obligation))
5180            {
5181                Some((ty, def.did()))
5182            } else {
5183                None
5184            }
5185        }) {
5186            for impl_def_id in self.tcx.inherent_impls(def_id) {
5187                if *impl_def_id == trait_predicate.def_id() {
5188                    continue;
5189                }
5190                for m in self
5191                    .tcx
5192                    .provided_trait_methods(*impl_def_id)
5193                    .filter(|m| m.name() == segment.ident.name)
5194                {
5195                    let fn_sig = self.tcx.fn_sig(m.def_id);
5196                    if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 {
5197                        continue;
5198                    }
5199                    let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder();
5200                    let (mutability, _ty) = match rcvr_ty.kind() {
5201                        ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty),
5202                        ty::Ref(_, ty, _) => ("&", ty),
5203                        _ => ("", &rcvr_ty),
5204                    };
5205                    let path = self.tcx.def_path_str(def_id);
5206                    err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("there\'s an inherent method on `{0}` of the same name, which can be auto-dereferenced from `{1}`",
                ty, rcvr_ty))
    })format!(
5207                        "there's an inherent method on `{ty}` of the same name, which can be \
5208                         auto-dereferenced from `{rcvr_ty}`"
5209                    ));
5210                    err.multipart_suggestion(
5211                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("to access the inherent method on `{0}`, use the fully-qualified path",
                ty))
    })format!(
5212                            "to access the inherent method on `{ty}`, use the fully-qualified path",
5213                        ),
5214                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(call.span.until(rcvr.span),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{2}::{0}({1}", m.name(),
                                    mutability, path))
                        })),
                match &args {
                    [] =>
                        (rcvr.span.shrink_to_hi().with_hi(call.span.hi()),
                            ")".to_string()),
                    [first, ..] =>
                        (rcvr.span.between(first.span), ", ".to_string()),
                }]))vec![
5215                            (
5216                                call.span.until(rcvr.span),
5217                                format!("{path}::{}({}", m.name(), mutability),
5218                            ),
5219                            match &args {
5220                                [] => (
5221                                    rcvr.span.shrink_to_hi().with_hi(call.span.hi()),
5222                                    ")".to_string(),
5223                                ),
5224                                [first, ..] => (rcvr.span.between(first.span), ", ".to_string()),
5225                            },
5226                        ],
5227                        Applicability::MaybeIncorrect,
5228                    );
5229                }
5230            }
5231        }
5232    }
5233
5234    pub(super) fn explain_hrtb_projection(
5235        &self,
5236        diag: &mut Diag<'_>,
5237        pred: ty::PolyTraitPredicate<'tcx>,
5238        param_env: ty::ParamEnv<'tcx>,
5239        cause: &ObligationCause<'tcx>,
5240    ) {
5241        if pred.skip_binder().has_escaping_bound_vars() && pred.skip_binder().has_non_region_infer()
5242        {
5243            self.probe(|_| {
5244                let ocx = ObligationCtxt::new(self);
5245                self.enter_forall(pred, |pred| {
5246                    let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
5247                    ocx.register_obligation(Obligation::new(
5248                        self.tcx,
5249                        ObligationCause::dummy(),
5250                        param_env,
5251                        pred,
5252                    ));
5253                });
5254                if !ocx.try_evaluate_obligations().is_empty() {
5255                    // encountered errors.
5256                    return;
5257                }
5258
5259                if let ObligationCauseCode::FunctionArg {
5260                    call_hir_id,
5261                    arg_hir_id,
5262                    parent_code: _,
5263                } = cause.code()
5264                {
5265                    let arg_span = self.tcx.hir_span(*arg_hir_id);
5266                    let mut sp: MultiSpan = arg_span.into();
5267
5268                    sp.push_span_label(
5269                        arg_span,
5270                        "the trait solver is unable to infer the \
5271                        generic types that should be inferred from this argument",
5272                    );
5273                    sp.push_span_label(
5274                        self.tcx.hir_span(*call_hir_id),
5275                        "add turbofish arguments to this call to \
5276                        specify the types manually, even if it's redundant",
5277                    );
5278                    diag.span_note(
5279                        sp,
5280                        "this is a known limitation of the trait solver that \
5281                        will be lifted in the future",
5282                    );
5283                } else {
5284                    let mut sp: MultiSpan = cause.span.into();
5285                    sp.push_span_label(
5286                        cause.span,
5287                        "try adding turbofish arguments to this expression to \
5288                        specify the types manually, even if it's redundant",
5289                    );
5290                    diag.span_note(
5291                        sp,
5292                        "this is a known limitation of the trait solver that \
5293                        will be lifted in the future",
5294                    );
5295                }
5296            });
5297        }
5298    }
5299
5300    pub(super) fn suggest_desugaring_async_fn_in_trait(
5301        &self,
5302        err: &mut Diag<'_>,
5303        trait_pred: ty::PolyTraitPredicate<'tcx>,
5304    ) {
5305        // Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
5306        if self.tcx.features().return_type_notation() {
5307            return;
5308        }
5309
5310        let trait_def_id = trait_pred.def_id();
5311
5312        // Only suggest specifying auto traits
5313        if !self.tcx.trait_is_auto(trait_def_id) {
5314            return;
5315        }
5316
5317        // Look for an RPITIT
5318        let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) =
5319            trait_pred.self_ty().skip_binder().kind()
5320        else {
5321            return;
5322        };
5323        let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
5324            self.tcx.opt_rpitit_info(*def_id)
5325        else {
5326            return;
5327        };
5328
5329        let auto_trait = self.tcx.def_path_str(trait_def_id);
5330        // ... which is a local function
5331        let Some(fn_def_id) = fn_def_id.as_local() else {
5332            // If it's not local, we can at least mention that the method is async, if it is.
5333            if self.tcx.asyncness(fn_def_id).is_async() {
5334                err.span_note(
5335                    self.tcx.def_span(fn_def_id),
5336                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}::{1}` is an `async fn` in trait, which does not automatically imply that its future is `{2}`",
                alias_ty.trait_ref(self.tcx), self.tcx.item_name(fn_def_id),
                auto_trait))
    })format!(
5337                        "`{}::{}` is an `async fn` in trait, which does not \
5338                    automatically imply that its future is `{auto_trait}`",
5339                        alias_ty.trait_ref(self.tcx),
5340                        self.tcx.item_name(fn_def_id)
5341                    ),
5342                );
5343            }
5344            return;
5345        };
5346        let hir::Node::TraitItem(item) = self.tcx.hir_node_by_def_id(fn_def_id) else {
5347            return;
5348        };
5349
5350        // ... whose signature is `async` (i.e. this is an AFIT)
5351        let (sig, body) = item.expect_fn();
5352        let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(opaq_def, ..), .. }) =
5353            sig.decl.output
5354        else {
5355            // This should never happen, but let's not ICE.
5356            return;
5357        };
5358
5359        // Check that this is *not* a nested `impl Future` RPIT in an async fn
5360        // (i.e. `async fn foo() -> impl Future`)
5361        if opaq_def.def_id.to_def_id() != opaque_def_id {
5362            return;
5363        }
5364
5365        let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait(
5366            self.tcx,
5367            *sig,
5368            *body,
5369            opaque_def_id.expect_local(),
5370            &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}", auto_trait))
    })format!(" + {auto_trait}"),
5371        ) else {
5372            return;
5373        };
5374
5375        let function_name = self.tcx.def_path_str(fn_def_id);
5376        err.multipart_suggestion(
5377            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` can be made part of the associated future\'s guarantees for all implementations of `{1}`",
                auto_trait, function_name))
    })format!(
5378                "`{auto_trait}` can be made part of the associated future's \
5379                guarantees for all implementations of `{function_name}`"
5380            ),
5381            sugg,
5382            Applicability::MachineApplicable,
5383        );
5384    }
5385
5386    pub fn ty_kind_suggestion(
5387        &self,
5388        param_env: ty::ParamEnv<'tcx>,
5389        ty: Ty<'tcx>,
5390    ) -> Option<String> {
5391        let tcx = self.infcx.tcx;
5392        let implements_default = |ty| {
5393            let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
5394                return false;
5395            };
5396            self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
5397        };
5398
5399        Some(match *ty.kind() {
5400            ty::Never | ty::Error(_) => return None,
5401            ty::Bool => "false".to_string(),
5402            ty::Char => "\'x\'".to_string(),
5403            ty::Int(_) | ty::Uint(_) => "42".into(),
5404            ty::Float(_) => "3.14159".into(),
5405            ty::Slice(_) => "[]".to_string(),
5406            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
5407                "vec![]".to_string()
5408            }
5409            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
5410                "String::new()".to_string()
5411            }
5412            ty::Adt(def, args) if def.is_box() => {
5413                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Box::new({0})",
                self.ty_kind_suggestion(param_env, args[0].expect_ty())?))
    })format!("Box::new({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
5414            }
5415            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
5416                "None".to_string()
5417            }
5418            ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
5419                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Ok({0})",
                self.ty_kind_suggestion(param_env, args[0].expect_ty())?))
    })format!("Ok({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
5420            }
5421            ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
5422            ty::Ref(_, ty, mutability) => {
5423                if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
5424                    "\"\"".to_string()
5425                } else {
5426                    let ty = self.ty_kind_suggestion(param_env, ty)?;
5427                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("&{0}{1}", mutability.prefix_str(),
                ty))
    })format!("&{}{ty}", mutability.prefix_str())
5428                }
5429            }
5430            ty::Array(ty, len) if let Some(len) = len.try_to_target_usize(tcx) => {
5431                if len == 0 {
5432                    "[]".to_string()
5433                } else if self.type_is_copy_modulo_regions(param_env, ty) || len == 1 {
5434                    // Can only suggest `[ty; 0]` if sz == 1 or copy
5435                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("[{0}; {1}]",
                self.ty_kind_suggestion(param_env, ty)?, len))
    })format!("[{}; {}]", self.ty_kind_suggestion(param_env, ty)?, len)
5436                } else {
5437                    "/* value */".to_string()
5438                }
5439            }
5440            ty::Tuple(tys) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0}{1})",
                tys.iter().map(|ty|
                                    self.ty_kind_suggestion(param_env,
                                        ty)).collect::<Option<Vec<String>>>()?.join(", "),
                if tys.len() == 1 { "," } else { "" }))
    })format!(
5441                "({}{})",
5442                tys.iter()
5443                    .map(|ty| self.ty_kind_suggestion(param_env, ty))
5444                    .collect::<Option<Vec<String>>>()?
5445                    .join(", "),
5446                if tys.len() == 1 { "," } else { "" }
5447            ),
5448            _ => "/* value */".to_string(),
5449        })
5450    }
5451
5452    // For E0277 when use `?` operator, suggest adding
5453    // a suitable return type in `FnSig`, and a default
5454    // return value at the end of the function's body.
5455    pub(super) fn suggest_add_result_as_return_type(
5456        &self,
5457        obligation: &PredicateObligation<'tcx>,
5458        err: &mut Diag<'_>,
5459        trait_pred: ty::PolyTraitPredicate<'tcx>,
5460    ) {
5461        if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
5462            return;
5463        }
5464
5465        // Only suggest for local function and associated method,
5466        // because this suggest adding both return type in
5467        // the `FnSig` and a default return value in the body, so it
5468        // is not suitable for foreign function without a local body,
5469        // and neither for trait method which may be also implemented
5470        // in other place, so shouldn't change it's FnSig.
5471        fn choose_suggest_items<'tcx, 'hir>(
5472            tcx: TyCtxt<'tcx>,
5473            node: hir::Node<'hir>,
5474        ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
5475            match node {
5476                hir::Node::Item(item)
5477                    if let hir::ItemKind::Fn { sig, body: body_id, .. } = item.kind =>
5478                {
5479                    Some((sig.decl, body_id))
5480                }
5481                hir::Node::ImplItem(item)
5482                    if let hir::ImplItemKind::Fn(sig, body_id) = item.kind =>
5483                {
5484                    let parent = tcx.parent_hir_node(item.hir_id());
5485                    if let hir::Node::Item(item) = parent
5486                        && let hir::ItemKind::Impl(imp) = item.kind
5487                        && imp.of_trait.is_none()
5488                    {
5489                        return Some((sig.decl, body_id));
5490                    }
5491                    None
5492                }
5493                _ => None,
5494            }
5495        }
5496
5497        let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
5498        if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node)
5499            && let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output
5500            && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
5501            && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
5502            && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
5503            && self.tcx.is_diagnostic_item(sym::Result, def.did())
5504        {
5505            let mut sugg_spans =
5506                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ret_span,
                    " -> Result<(), Box<dyn std::error::Error>>".to_string())]))vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())];
5507            let body = self.tcx.hir_body(body_id);
5508            if let hir::ExprKind::Block(b, _) = body.value.kind
5509                && b.expr.is_none()
5510            {
5511                // The span of '}' in the end of block.
5512                let span = self.tcx.sess.source_map().end_point(b.span);
5513                sugg_spans.push((
5514                    span.shrink_to_lo(),
5515                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", "    Ok(())\n",
                self.tcx.sess.source_map().indentation_before(span).unwrap_or_default()))
    })format!(
5516                        "{}{}",
5517                        "    Ok(())\n",
5518                        self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(),
5519                    ),
5520                ));
5521            }
5522            err.multipart_suggestion(
5523                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider adding return type"))
    })format!("consider adding return type"),
5524                sugg_spans,
5525                Applicability::MaybeIncorrect,
5526            );
5527        }
5528    }
5529
5530    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("suggest_unsized_bound_if_applicable",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5530u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
                obligation.predicate.kind().skip_binder() else { return; };
            let (ObligationCauseCode::WhereClause(item_def_id, span) |
                    ObligationCauseCode::WhereClauseInExpr(item_def_id, span,
                    ..)) =
                *obligation.cause.code().peel_derives() else { return; };
            if span.is_dummy() { return; }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5550",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5550u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["pred",
                                                    "item_def_id", "span"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&pred) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&item_def_id)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&span) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            let (Some(node), true) =
                (self.tcx.hir_get_if_local(item_def_id),
                    self.tcx.is_lang_item(pred.def_id(),
                        LangItem::Sized)) else { return; };
            let Some(generics) = node.generics() else { return; };
            let sized_trait = self.tcx.lang_items().sized_trait();
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5563",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5563u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["generics.params"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&generics.params)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5564",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5564u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["generics.predicates"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&generics.predicates)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let Some(param) =
                generics.params.iter().find(|param|
                        param.span == span) else { return; };
            let explicitly_sized =
                generics.bounds_for_param(param.def_id).flat_map(|bp|
                            bp.bounds).any(|bound|
                        bound.trait_ref().and_then(|tr| tr.trait_def_id()) ==
                            sized_trait);
            if explicitly_sized { return; }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5577",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5577u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&["param"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&param) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            match node {
                hir::Node::Item(item @ hir::Item {
                    kind: hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) |
                        hir::ItemKind::Union(..), .. }) => {
                    if self.suggest_indirection_for_unsized(err, item, param) {
                        return;
                    }
                }
                _ => {}
            };
            let (span, separator, open_paren_sp) =
                if let Some((s, open_paren_sp)) =
                        generics.bounds_span_for_suggestions(param.def_id) {
                    (s, " +", open_paren_sp)
                } else {
                    (param.name.ident().span.shrink_to_hi(), ":", None)
                };
            let mut suggs = ::alloc::vec::Vec::new();
            let suggestion =
                ::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("{0} ?Sized", separator))
                    });
            if let Some(open_paren_sp) = open_paren_sp {
                suggs.push((open_paren_sp, "(".to_string()));
                suggs.push((span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("){0}", suggestion))
                            })));
            } else { suggs.push((span, suggestion)); }
            err.multipart_suggestion("consider relaxing the implicit `Sized` restriction",
                suggs, Applicability::MachineApplicable);
        }
    }
}#[instrument(level = "debug", skip_all)]
5531    pub(super) fn suggest_unsized_bound_if_applicable(
5532        &self,
5533        err: &mut Diag<'_>,
5534        obligation: &PredicateObligation<'tcx>,
5535    ) {
5536        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
5537            obligation.predicate.kind().skip_binder()
5538        else {
5539            return;
5540        };
5541        let (ObligationCauseCode::WhereClause(item_def_id, span)
5542        | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)) =
5543            *obligation.cause.code().peel_derives()
5544        else {
5545            return;
5546        };
5547        if span.is_dummy() {
5548            return;
5549        }
5550        debug!(?pred, ?item_def_id, ?span);
5551
5552        let (Some(node), true) = (
5553            self.tcx.hir_get_if_local(item_def_id),
5554            self.tcx.is_lang_item(pred.def_id(), LangItem::Sized),
5555        ) else {
5556            return;
5557        };
5558
5559        let Some(generics) = node.generics() else {
5560            return;
5561        };
5562        let sized_trait = self.tcx.lang_items().sized_trait();
5563        debug!(?generics.params);
5564        debug!(?generics.predicates);
5565        let Some(param) = generics.params.iter().find(|param| param.span == span) else {
5566            return;
5567        };
5568        // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
5569        // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
5570        let explicitly_sized = generics
5571            .bounds_for_param(param.def_id)
5572            .flat_map(|bp| bp.bounds)
5573            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
5574        if explicitly_sized {
5575            return;
5576        }
5577        debug!(?param);
5578        match node {
5579            hir::Node::Item(
5580                item @ hir::Item {
5581                    // Only suggest indirection for uses of type parameters in ADTs.
5582                    kind:
5583                        hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
5584                    ..
5585                },
5586            ) => {
5587                if self.suggest_indirection_for_unsized(err, item, param) {
5588                    return;
5589                }
5590            }
5591            _ => {}
5592        };
5593
5594        // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
5595        let (span, separator, open_paren_sp) =
5596            if let Some((s, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
5597                (s, " +", open_paren_sp)
5598            } else {
5599                (param.name.ident().span.shrink_to_hi(), ":", None)
5600            };
5601
5602        let mut suggs = vec![];
5603        let suggestion = format!("{separator} ?Sized");
5604
5605        if let Some(open_paren_sp) = open_paren_sp {
5606            suggs.push((open_paren_sp, "(".to_string()));
5607            suggs.push((span, format!("){suggestion}")));
5608        } else {
5609            suggs.push((span, suggestion));
5610        }
5611
5612        err.multipart_suggestion(
5613            "consider relaxing the implicit `Sized` restriction",
5614            suggs,
5615            Applicability::MachineApplicable,
5616        );
5617    }
5618
5619    fn suggest_indirection_for_unsized(
5620        &self,
5621        err: &mut Diag<'_>,
5622        item: &hir::Item<'tcx>,
5623        param: &hir::GenericParam<'tcx>,
5624    ) -> bool {
5625        // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
5626        // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
5627        // is not. Look for invalid "bare" parameter uses, and suggest using indirection.
5628        let mut visitor = FindTypeParam { param: param.name.ident().name, .. };
5629        visitor.visit_item(item);
5630        if visitor.invalid_spans.is_empty() {
5631            return false;
5632        }
5633        let mut multispan: MultiSpan = param.span.into();
5634        multispan.push_span_label(
5635            param.span,
5636            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this could be changed to `{0}: ?Sized`...",
                param.name.ident()))
    })format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
5637        );
5638        for sp in visitor.invalid_spans {
5639            multispan.push_span_label(
5640                sp,
5641                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("...if indirection were used here: `Box<{0}>`",
                param.name.ident()))
    })format!("...if indirection were used here: `Box<{}>`", param.name.ident()),
5642            );
5643        }
5644        err.span_help(
5645            multispan,
5646            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you could relax the implicit `Sized` bound on `{0}` if it were used through indirection like `&{0}` or `Box<{0}>`",
                param.name.ident()))
    })format!(
5647                "you could relax the implicit `Sized` bound on `{T}` if it were \
5648                used through indirection like `&{T}` or `Box<{T}>`",
5649                T = param.name.ident(),
5650            ),
5651        );
5652        true
5653    }
5654    pub(crate) fn suggest_swapping_lhs_and_rhs<T>(
5655        &self,
5656        err: &mut Diag<'_>,
5657        predicate: T,
5658        param_env: ty::ParamEnv<'tcx>,
5659        cause_code: &ObligationCauseCode<'tcx>,
5660    ) where
5661        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
5662    {
5663        let tcx = self.tcx;
5664        let predicate = predicate.upcast(tcx);
5665        match *cause_code {
5666            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, rhs_span, .. }
5667                if let Some(typeck_results) = &self.typeck_results
5668                    && let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id)
5669                    && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id)
5670                    && let Some(lhs_ty) = typeck_results.expr_ty_opt(lhs)
5671                    && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) =>
5672            {
5673                if let Some(pred) = predicate.as_trait_clause()
5674                    && tcx.is_lang_item(pred.def_id(), LangItem::PartialEq)
5675                    && self
5676                        .infcx
5677                        .type_implements_trait(pred.def_id(), [rhs_ty, lhs_ty], param_env)
5678                        .must_apply_modulo_regions()
5679                {
5680                    let lhs_span = tcx.hir_span(lhs_hir_id);
5681                    let sm = tcx.sess.source_map();
5682                    if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_span)
5683                        && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_span)
5684                    {
5685                        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` implements `PartialEq<{1}>`",
                rhs_ty, lhs_ty))
    })format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`"));
5686                        err.multipart_suggestion(
5687                            "consider swapping the equality",
5688                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(lhs_span, rhs_snippet), (rhs_span, lhs_snippet)]))vec![(lhs_span, rhs_snippet), (rhs_span, lhs_snippet)],
5689                            Applicability::MaybeIncorrect,
5690                        );
5691                    }
5692                }
5693            }
5694            _ => {}
5695        }
5696    }
5697}
5698
5699/// Add a hint to add a missing borrow or remove an unnecessary one.
5700fn hint_missing_borrow<'tcx>(
5701    infcx: &InferCtxt<'tcx>,
5702    param_env: ty::ParamEnv<'tcx>,
5703    span: Span,
5704    found: Ty<'tcx>,
5705    expected: Ty<'tcx>,
5706    found_node: Node<'_>,
5707    err: &mut Diag<'_>,
5708) {
5709    if #[allow(non_exhaustive_omitted_patterns)] match found_node {
    Node::TraitItem(..) => true,
    _ => false,
}matches!(found_node, Node::TraitItem(..)) {
5710        return;
5711    }
5712
5713    let found_args = match found.kind() {
5714        ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
5715        kind => {
5716            ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("found was converted to a FnPtr above but is now {0:?}",
        kind))span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
5717        }
5718    };
5719    let expected_args = match expected.kind() {
5720        ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
5721        kind => {
5722            ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("expected was converted to a FnPtr above but is now {0:?}",
        kind))span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
5723        }
5724    };
5725
5726    // This could be a variant constructor, for example.
5727    let Some(fn_decl) = found_node.fn_decl() else {
5728        return;
5729    };
5730
5731    let args = fn_decl.inputs.iter();
5732
5733    let mut to_borrow = Vec::new();
5734    let mut remove_borrow = Vec::new();
5735
5736    for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
5737        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
5738        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
5739
5740        if infcx.can_eq(param_env, found_ty, expected_ty) {
5741            // FIXME: This could handle more exotic cases like mutability mismatches too!
5742            if found_refs.len() < expected_refs.len()
5743                && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]
5744            {
5745                to_borrow.push((
5746                    arg.span.shrink_to_lo(),
5747                    expected_refs[..expected_refs.len() - found_refs.len()]
5748                        .iter()
5749                        .map(|mutbl| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("&{0}", mutbl.prefix_str()))
    })format!("&{}", mutbl.prefix_str()))
5750                        .collect::<Vec<_>>()
5751                        .join(""),
5752                ));
5753            } else if found_refs.len() > expected_refs.len() {
5754                let mut span = arg.span.shrink_to_lo();
5755                let mut left = found_refs.len() - expected_refs.len();
5756                let mut ty = arg;
5757                while let hir::TyKind::Ref(_, mut_ty) = &ty.kind
5758                    && left > 0
5759                {
5760                    span = span.with_hi(mut_ty.ty.span.lo());
5761                    ty = mut_ty.ty;
5762                    left -= 1;
5763                }
5764                if left == 0 {
5765                    remove_borrow.push((span, String::new()));
5766                }
5767            }
5768        }
5769    }
5770
5771    if !to_borrow.is_empty() {
5772        err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow });
5773    }
5774
5775    if !remove_borrow.is_empty() {
5776        err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
5777    }
5778}
5779
5780/// Collect all the paths that reference `Self`.
5781/// Used to suggest replacing associated types with an explicit type in `where` clauses.
5782#[derive(#[automatically_derived]
impl<'v> ::core::fmt::Debug for SelfVisitor<'v> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "SelfVisitor",
            "paths", &self.paths, "name", &&self.name)
    }
}Debug)]
5783pub struct SelfVisitor<'v> {
5784    pub paths: Vec<&'v hir::Ty<'v>> = Vec::new(),
5785    pub name: Option<Symbol>,
5786}
5787
5788impl<'v> Visitor<'v> for SelfVisitor<'v> {
5789    fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
5790        if let hir::TyKind::Path(path) = ty.kind
5791            && let hir::QPath::TypeRelative(inner_ty, segment) = path
5792            && (Some(segment.ident.name) == self.name || self.name.is_none())
5793            && let hir::TyKind::Path(inner_path) = inner_ty.kind
5794            && let hir::QPath::Resolved(None, inner_path) = inner_path
5795            && let Res::SelfTyAlias { .. } = inner_path.res
5796        {
5797            self.paths.push(ty.as_unambig_ty());
5798        }
5799        hir::intravisit::walk_ty(self, ty);
5800    }
5801}
5802
5803/// Collect all the returned expressions within the input expression.
5804/// Used to point at the return spans when we want to suggest some change to them.
5805#[derive(#[automatically_derived]
impl<'v> ::core::default::Default for ReturnsVisitor<'v> {
    #[inline]
    fn default() -> ReturnsVisitor<'v> {
        ReturnsVisitor {
            returns: ::core::default::Default::default(),
            in_block_tail: ::core::default::Default::default(),
        }
    }
}Default)]
5806pub struct ReturnsVisitor<'v> {
5807    pub returns: Vec<&'v hir::Expr<'v>>,
5808    in_block_tail: bool,
5809}
5810
5811impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
5812    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
5813        // Visit every expression to detect `return` paths, either through the function's tail
5814        // expression or `return` statements. We walk all nodes to find `return` statements, but
5815        // we only care about tail expressions when `in_block_tail` is `true`, which means that
5816        // they're in the return path of the function body.
5817        match ex.kind {
5818            hir::ExprKind::Ret(Some(ex)) => {
5819                self.returns.push(ex);
5820            }
5821            hir::ExprKind::Block(block, _) if self.in_block_tail => {
5822                self.in_block_tail = false;
5823                for stmt in block.stmts {
5824                    hir::intravisit::walk_stmt(self, stmt);
5825                }
5826                self.in_block_tail = true;
5827                if let Some(expr) = block.expr {
5828                    self.visit_expr(expr);
5829                }
5830            }
5831            hir::ExprKind::If(_, then, else_opt) if self.in_block_tail => {
5832                self.visit_expr(then);
5833                if let Some(el) = else_opt {
5834                    self.visit_expr(el);
5835                }
5836            }
5837            hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
5838                for arm in arms {
5839                    self.visit_expr(arm.body);
5840                }
5841            }
5842            // We need to walk to find `return`s in the entire body.
5843            _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
5844            _ => self.returns.push(ex),
5845        }
5846    }
5847
5848    fn visit_body(&mut self, body: &hir::Body<'v>) {
5849        if !!self.in_block_tail {
    ::core::panicking::panic("assertion failed: !self.in_block_tail")
};assert!(!self.in_block_tail);
5850        self.in_block_tail = true;
5851        hir::intravisit::walk_body(self, body);
5852    }
5853}
5854
5855/// Collect all the awaited expressions within the input expression.
5856#[derive(#[automatically_derived]
impl ::core::default::Default for AwaitsVisitor {
    #[inline]
    fn default() -> AwaitsVisitor {
        AwaitsVisitor { awaits: ::core::default::Default::default() }
    }
}Default)]
5857struct AwaitsVisitor {
5858    awaits: Vec<HirId>,
5859}
5860
5861impl<'v> Visitor<'v> for AwaitsVisitor {
5862    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
5863        if let hir::ExprKind::Yield(_, hir::YieldSource::Await { expr: Some(id) }) = ex.kind {
5864            self.awaits.push(id)
5865        }
5866        hir::intravisit::walk_expr(self, ex)
5867    }
5868}
5869
5870/// Suggest a new type parameter name for diagnostic purposes.
5871///
5872/// `name` is the preferred name you'd like to suggest if it's not in use already.
5873pub trait NextTypeParamName {
5874    fn next_type_param_name(&self, name: Option<&str>) -> String;
5875}
5876
5877impl NextTypeParamName for &[hir::GenericParam<'_>] {
5878    fn next_type_param_name(&self, name: Option<&str>) -> String {
5879        // Type names are usually single letters in uppercase. So convert the first letter of input string to uppercase.
5880        let name = name.and_then(|n| n.chars().next()).map(|c| c.to_uppercase().to_string());
5881        let name = name.as_deref();
5882
5883        // This is the list of possible parameter names that we might suggest.
5884        let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
5885
5886        // Filter out used names based on `filter_fn`.
5887        let used_names: Vec<Symbol> = self
5888            .iter()
5889            .filter_map(|param| match param.name {
5890                hir::ParamName::Plain(ident) => Some(ident.name),
5891                _ => None,
5892            })
5893            .collect();
5894
5895        // Find a name from `possible_names` that is not in `used_names`.
5896        possible_names
5897            .iter()
5898            .find(|n| !used_names.contains(&Symbol::intern(n)))
5899            .unwrap_or(&"ParamName")
5900            .to_string()
5901    }
5902}
5903
5904/// Collect the spans that we see the generic param `param_did`
5905struct ReplaceImplTraitVisitor<'a> {
5906    ty_spans: &'a mut Vec<Span>,
5907    param_did: DefId,
5908}
5909
5910impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
5911    fn visit_ty(&mut self, t: &'hir hir::Ty<'hir, AmbigArg>) {
5912        if let hir::TyKind::Path(hir::QPath::Resolved(
5913            None,
5914            hir::Path { res: Res::Def(_, segment_did), .. },
5915        )) = t.kind
5916        {
5917            if self.param_did == *segment_did {
5918                // `fn foo(t: impl Trait)`
5919                //            ^^^^^^^^^^ get this to suggest `T` instead
5920
5921                // There might be more than one `impl Trait`.
5922                self.ty_spans.push(t.span);
5923                return;
5924            }
5925        }
5926
5927        hir::intravisit::walk_ty(self, t);
5928    }
5929}
5930
5931pub(super) fn get_explanation_based_on_obligation<'tcx>(
5932    tcx: TyCtxt<'tcx>,
5933    obligation: &PredicateObligation<'tcx>,
5934    trait_predicate: ty::PolyTraitPredicate<'tcx>,
5935    pre_message: String,
5936    long_ty_path: &mut Option<PathBuf>,
5937) -> String {
5938    if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
5939        "consider using `()`, or a `Result`".to_owned()
5940    } else {
5941        let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
5942            ty::FnDef(_, _) => Some("fn item"),
5943            ty::Closure(_, _) => Some("closure"),
5944            _ => None,
5945        };
5946
5947        let desc = match ty_desc {
5948            Some(desc) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" {0}", desc))
    })format!(" {desc}"),
5949            None => String::new(),
5950        };
5951        if let ty::PredicatePolarity::Positive = trait_predicate.polarity() {
5952            // If the trait in question is unstable, mention that fact in the diagnostic.
5953            // But if we're building with `-Zforce-unstable-if-unmarked` then _any_ trait
5954            // not explicitly marked stable is considered unstable, so the extra text is
5955            // unhelpful noise. See <https://github.com/rust-lang/rust/issues/152692>.
5956            let mention_unstable = !tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
5957                && try { tcx.lookup_stability(trait_predicate.def_id())?.level.is_stable() }
5958                    == Some(false);
5959            let unstable = if mention_unstable { "nightly-only, unstable " } else { "" };
5960
5961            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{2}the {3}trait `{0}` is not implemented for{4} `{1}`",
                trait_predicate.print_modifiers_and_trait_path(),
                tcx.short_string(trait_predicate.self_ty().skip_binder(),
                    long_ty_path), pre_message, unstable, desc))
    })format!(
5962                "{pre_message}the {unstable}trait `{}` is not implemented for{desc} `{}`",
5963                trait_predicate.print_modifiers_and_trait_path(),
5964                tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path),
5965            )
5966        } else {
5967            // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
5968            // not implemented for `T`".
5969            // FIXME: add note explaining explicit negative trait bounds.
5970            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}the trait bound `{1}` is not satisfied",
                pre_message, trait_predicate))
    })format!("{pre_message}the trait bound `{trait_predicate}` is not satisfied")
5971        }
5972    }
5973}
5974
5975// Replace `param` with `replace_ty`
5976struct ReplaceImplTraitFolder<'tcx> {
5977    tcx: TyCtxt<'tcx>,
5978    param: &'tcx ty::GenericParamDef,
5979    replace_ty: Ty<'tcx>,
5980}
5981
5982impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
5983    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
5984        if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
5985            if self.param.index == *index {
5986                return self.replace_ty;
5987            }
5988        }
5989        t.super_fold_with(self)
5990    }
5991
5992    fn cx(&self) -> TyCtxt<'tcx> {
5993        self.tcx
5994    }
5995}
5996
5997pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
5998    tcx: TyCtxt<'tcx>,
5999    sig: hir::FnSig<'tcx>,
6000    body: hir::TraitFn<'tcx>,
6001    opaque_def_id: LocalDefId,
6002    add_bounds: &str,
6003) -> Option<Vec<(Span, String)>> {
6004    let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
6005        return None;
6006    };
6007    let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span);
6008
6009    let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
6010    let [hir::GenericBound::Trait(trait_ref)] = future.bounds else {
6011        // `async fn` should always lower to a single bound... but don't ICE.
6012        return None;
6013    };
6014    let Some(hir::PathSegment { args: Some(args), .. }) = trait_ref.trait_ref.path.segments.last()
6015    else {
6016        // desugaring to a single path segment for `Future<...>`.
6017        return None;
6018    };
6019    let Some(future_output_ty) = args.constraints.first().and_then(|constraint| constraint.ty())
6020    else {
6021        // Also should never happen.
6022        return None;
6023    };
6024
6025    let mut sugg = if future_output_ty.span.is_empty() {
6026        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(async_span, String::new()),
                (future_output_ty.span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(" -> impl std::future::Future<Output = ()>{0}",
                                    add_bounds))
                        }))]))vec![
6027            (async_span, String::new()),
6028            (
6029                future_output_ty.span,
6030                format!(" -> impl std::future::Future<Output = ()>{add_bounds}"),
6031            ),
6032        ]
6033    } else {
6034        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(future_output_ty.span.shrink_to_lo(),
                    "impl std::future::Future<Output = ".to_owned()),
                (future_output_ty.span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(">{0}", add_bounds))
                        })), (async_span, String::new())]))vec![
6035            (future_output_ty.span.shrink_to_lo(), "impl std::future::Future<Output = ".to_owned()),
6036            (future_output_ty.span.shrink_to_hi(), format!(">{add_bounds}")),
6037            (async_span, String::new()),
6038        ]
6039    };
6040
6041    // If there's a body, we also need to wrap it in `async {}`
6042    if let hir::TraitFn::Provided(body) = body {
6043        let body = tcx.hir_body(body);
6044        let body_span = body.value.span;
6045        let body_span_without_braces =
6046            body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
6047        if body_span_without_braces.is_empty() {
6048            sugg.push((body_span_without_braces, " async {} ".to_owned()));
6049        } else {
6050            sugg.extend([
6051                (body_span_without_braces.shrink_to_lo(), "async {".to_owned()),
6052                (body_span_without_braces.shrink_to_hi(), "} ".to_owned()),
6053            ]);
6054        }
6055    }
6056
6057    Some(sugg)
6058}
6059
6060/// On `impl` evaluation cycles, look for `Self::AssocTy` restrictions in `where` clauses, explain
6061/// they are not allowed and if possible suggest alternatives.
6062fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
6063    tcx: TyCtxt<'_>,
6064    err: &mut Diag<'_, G>,
6065    self_ty_str: &str,
6066    trait_name: &str,
6067    predicate: ty::Predicate<'_>,
6068    generics: &hir::Generics<'_>,
6069    data: &ImplDerivedCause<'_>,
6070) {
6071    let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() else {
6072        return;
6073    };
6074    let ty::ClauseKind::Projection(proj) = clause else {
6075        return;
6076    };
6077    let name = tcx.item_name(proj.projection_term.def_id);
6078    let mut predicates = generics.predicates.iter().peekable();
6079    let mut prev: Option<(&hir::WhereBoundPredicate<'_>, Span)> = None;
6080    while let Some(pred) = predicates.next() {
6081        let curr_span = pred.span;
6082        let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
6083            continue;
6084        };
6085        let mut bounds = pred.bounds.iter();
6086        while let Some(bound) = bounds.next() {
6087            let Some(trait_ref) = bound.trait_ref() else {
6088                continue;
6089            };
6090            if bound.span() != data.span {
6091                continue;
6092            }
6093            if let hir::TyKind::Path(path) = pred.bounded_ty.kind
6094                && let hir::QPath::TypeRelative(ty, segment) = path
6095                && segment.ident.name == name
6096                && let hir::TyKind::Path(inner_path) = ty.kind
6097                && let hir::QPath::Resolved(None, inner_path) = inner_path
6098                && let Res::SelfTyAlias { .. } = inner_path.res
6099            {
6100                // The following block is to determine the right span to delete for this bound
6101                // that will leave valid code after the suggestion is applied.
6102                let span = if pred.origin == hir::PredicateOrigin::WhereClause
6103                    && generics
6104                        .predicates
6105                        .iter()
6106                        .filter(|p| {
6107                            #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    hir::WherePredicateKind::BoundPredicate(p) if
        hir::PredicateOrigin::WhereClause == p.origin => true,
    _ => false,
}matches!(
6108                                p.kind,
6109                                hir::WherePredicateKind::BoundPredicate(p)
6110                                if hir::PredicateOrigin::WhereClause == p.origin
6111                            )
6112                        })
6113                        .count()
6114                        == 1
6115                {
6116                    // There's only one `where` bound, that needs to be removed. Remove the whole
6117                    // `where` clause.
6118                    generics.where_clause_span
6119                } else if let Some(next_pred) = predicates.peek()
6120                    && let hir::WherePredicateKind::BoundPredicate(next) = next_pred.kind
6121                    && pred.origin == next.origin
6122                {
6123                    // There's another bound, include the comma for the current one.
6124                    curr_span.until(next_pred.span)
6125                } else if let Some((prev, prev_span)) = prev
6126                    && pred.origin == prev.origin
6127                {
6128                    // Last bound, try to remove the previous comma.
6129                    prev_span.shrink_to_hi().to(curr_span)
6130                } else if pred.origin == hir::PredicateOrigin::WhereClause {
6131                    curr_span.with_hi(generics.where_clause_span.hi())
6132                } else {
6133                    curr_span
6134                };
6135
6136                err.span_suggestion_verbose(
6137                    span,
6138                    "associated type for the current `impl` cannot be restricted in `where` \
6139                     clauses, remove this bound",
6140                    "",
6141                    Applicability::MaybeIncorrect,
6142                );
6143            }
6144            if let Some(new) =
6145                tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind(
6146                    tcx,
6147                    Ident::with_dummy_span(name),
6148                    ty::AssocTag::Type,
6149                    data.impl_or_alias_def_id,
6150                )
6151            {
6152                // The associated type is specified in the `impl` we're
6153                // looking at. Point at it.
6154                let span = tcx.def_span(new.def_id);
6155                err.span_label(
6156                    span,
6157                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("associated type `<{0} as {1}>::{2}` is specified here",
                self_ty_str, trait_name, name))
    })format!(
6158                        "associated type `<{self_ty_str} as {trait_name}>::{name}` is specified \
6159                         here",
6160                    ),
6161                );
6162                // Search for the associated type `Self::{name}`, get
6163                // its type and suggest replacing the bound with it.
6164                let mut visitor = SelfVisitor { name: Some(name), .. };
6165                visitor.visit_trait_ref(trait_ref);
6166                for path in visitor.paths {
6167                    err.span_suggestion_verbose(
6168                        path.span,
6169                        "replace the associated type with the type specified in this `impl`",
6170                        tcx.type_of(new.def_id).skip_binder(),
6171                        Applicability::MachineApplicable,
6172                    );
6173                }
6174            } else {
6175                let mut visitor = SelfVisitor { name: None, .. };
6176                visitor.visit_trait_ref(trait_ref);
6177                let span: MultiSpan =
6178                    visitor.paths.iter().map(|p| p.span).collect::<Vec<Span>>().into();
6179                err.span_note(
6180                    span,
6181                    "associated types for the current `impl` cannot be restricted in `where` \
6182                     clauses",
6183                );
6184            }
6185        }
6186        prev = Some((pred, curr_span));
6187    }
6188}
6189
6190fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, Vec<hir::Mutability>) {
6191    let mut refs = ::alloc::vec::Vec::new()vec![];
6192
6193    while let ty::Ref(_, new_ty, mutbl) = ty.kind() {
6194        ty = *new_ty;
6195        refs.push(*mutbl);
6196    }
6197
6198    (ty, refs)
6199}
6200
6201/// Look for type `param` in an ADT being used only through a reference to confirm that suggesting
6202/// `param: ?Sized` would be a valid constraint.
6203struct FindTypeParam {
6204    param: rustc_span::Symbol,
6205    invalid_spans: Vec<Span> = Vec::new(),
6206    nested: bool = false,
6207}
6208
6209impl<'v> Visitor<'v> for FindTypeParam {
6210    fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
6211        // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
6212    }
6213
6214    fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
6215        // We collect the spans of all uses of the "bare" type param, like in `field: T` or
6216        // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
6217        // valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized`
6218        // obligations like `Box<T>` and `Vec<T>`, but we perform no extra analysis for those cases
6219        // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors
6220        // in that case should make what happened clear enough.
6221        match ty.kind {
6222            hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {}
6223            hir::TyKind::Path(hir::QPath::Resolved(None, path))
6224                if let [segment] = path.segments
6225                    && segment.ident.name == self.param =>
6226            {
6227                if !self.nested {
6228                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:6228",
                        "rustc_trait_selection::error_reporting::traits::suggestions",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                        ::tracing_core::__macro_support::Option::Some(6228u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                        ::tracing_core::field::FieldSet::new(&["message", "ty"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("FindTypeParam::visit_ty")
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&ty) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(?ty, "FindTypeParam::visit_ty");
6229                    self.invalid_spans.push(ty.span);
6230                }
6231            }
6232            hir::TyKind::Path(_) => {
6233                let prev = self.nested;
6234                self.nested = true;
6235                hir::intravisit::walk_ty(self, ty);
6236                self.nested = prev;
6237            }
6238            _ => {
6239                hir::intravisit::walk_ty(self, ty);
6240            }
6241        }
6242    }
6243}
6244
6245/// Look for type parameters in predicates. We use this to identify whether a bound is suitable in
6246/// on a given item.
6247struct ParamFinder {
6248    params: Vec<Symbol> = Vec::new(),
6249}
6250
6251impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamFinder {
6252    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
6253        match t.kind() {
6254            ty::Param(p) => self.params.push(p.name),
6255            _ => {}
6256        }
6257        t.super_visit_with(self)
6258    }
6259}
6260
6261impl ParamFinder {
6262    /// Whether the `hir::Generics` of the current item can suggest the evaluated bound because its
6263    /// references to type parameters are present in the generics.
6264    fn can_suggest_bound(&self, generics: &hir::Generics<'_>) -> bool {
6265        if self.params.is_empty() {
6266            // There are no references to type parameters at all, so suggesting the bound
6267            // would be reasonable.
6268            return true;
6269        }
6270        generics.params.iter().any(|p| match p.name {
6271            hir::ParamName::Plain(p_name) => {
6272                // All of the parameters in the bound can be referenced in the current item.
6273                self.params.iter().any(|p| *p == p_name.name || *p == kw::SelfUpper)
6274            }
6275            _ => true,
6276        })
6277    }
6278}