Skip to main content

rustc_trait_selection/error_reporting/traits/
suggestions.rs

1// ignore-tidy-file-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_attr_ir::lang_items::{self, LangItem};
10use rustc_data_structures::fx::FxHashSet;
11use rustc_errors::codes::*;
12use rustc_errors::{
13    Applicability, Diag, MultiSpan, Style, SuggestionStyle, pluralize, struct_span_code_err,
14};
15use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
16use rustc_hir::def_id::DefId;
17use rustc_hir::intravisit::Visitor;
18use rustc_hir::{
19    self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
20    expr_needs_parens,
21};
22use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
23use rustc_infer::traits::ImplSource;
24use rustc_middle::middle::privacy::Level;
25use rustc_middle::traits::IsConstable;
26use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
27use rustc_middle::ty::consts::ConstExt;
28use rustc_middle::ty::error::TypeError;
29use rustc_middle::ty::print::{
30    PrintPolyTraitClauseExt as _, PrintPolyTraitRefExt, PrintTraitClauseExt as _,
31    PrintTraitRefExt as _, with_forced_trimmed_paths, with_no_trimmed_paths,
32    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,
37    Unnormalized, Upcast, suggest_arbitrary_trait_bound, suggest_constraining_type_param,
38};
39use rustc_span::def_id::LocalDefId;
40use rustc_span::{
41    BytePos, DUMMY_SP, DesugaringKind, ExpnKind, Ident, MacroKind, Span, Symbol, bug, kw, span_bug,
42    sym,
43};
44use tracing::{debug, instrument};
45
46use super::{
47    DefIdOrName, FindExprBySpan, ImplCandidate, Obligation, ObligationCause, ObligationCauseCode,
48    PredicateObligation,
49};
50use crate::diagnostics;
51use crate::error_reporting::TypeErrCtxt;
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 {
            Self::Interior(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "Interior", __self_0, &__self_1),
            Self::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.deeply_resolve_ignoring_regions(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>(
124    tcx: TyCtxt<'tcx>,
125    item_id: LocalDefId,
126    hir_generics: &hir::Generics<'tcx>,
127    msg: &str,
128    err: &mut Diag<'_>,
129    fn_sig: Option<&hir::FnSig<'_>>,
130    projection: Option<ty::ProjectionAliasTy<'_>>,
131    trait_pred: ty::PolyTraitClause<'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) && !tcx.features().return_type_notation())
143                || tcx.lookup_stability(projection.kind).is_some_and(|stab| stab.is_unstable())
144        })
145    {
146        return;
147    }
148    let generics = tcx.generics_of(item_id);
149    // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
150    if let Some((param, bound_str, fn_sig)) =
151        fn_sig.zip(projection).and_then(|(sig, p)| match *p.projection_self_ty().kind() {
152            // Shenanigans to get the `Trait` from the `impl Trait`.
153            ty::Param(param) => {
154                let param_def = generics.type_param(param, tcx);
155                if param_def.kind.is_synthetic() {
156                    let bound_str =
157                        param_def.name.as_str().strip_prefix("impl ")?.trim_start().to_string();
158                    return Some((param_def, bound_str, sig));
159                }
160                None
161            }
162            _ => None,
163        })
164    {
165        let type_param_name = hir_generics.params.next_type_param_name(Some(&bound_str));
166        let trait_pred = trait_pred.fold_with(&mut ReplaceImplTraitFolder {
167            tcx,
168            param,
169            replace_ty: ty::ParamTy::new(generics.count() as u32, Symbol::intern(&type_param_name))
170                .to_ty(tcx),
171        });
172        if !trait_pred.is_suggestable(tcx, false) {
173            return;
174        }
175        // We know we have an `impl Trait` that doesn't satisfy a required projection.
176
177        // Find all of the occurrences of `impl Trait` for `Trait` in the function arguments'
178        // types. There should be at least one, but there might be *more* than one. In that
179        // case we could just ignore it and try to identify which one needs the restriction,
180        // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
181        // where `T: Trait`.
182        let mut ty_spans = ::alloc::vec::Vec::new()vec![];
183        for input in fn_sig.decl.inputs {
184            ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id }
185                .visit_ty_unambig(input);
186        }
187        // The type param `T: Trait` we will suggest to introduce.
188        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}");
189
190        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![
191            if let Some(span) = hir_generics.span_for_param_suggestion() {
192                (span, format!(", {type_param}"))
193            } else {
194                (hir_generics.span, format!("<{type_param}>"))
195            },
196            // `fn foo(t: impl Trait)`
197            //                       ^ suggest `where <T as Trait>::A: Bound`
198            predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
199        ];
200        sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
201
202        // Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
203        // FIXME: we should suggest `fn foo(t: impl Trait<A: Bound>)` instead.
204        err.multipart_suggestion(
205            "introduce a type parameter with a trait bound instead of using `impl Trait`",
206            sugg,
207            Applicability::MaybeIncorrect,
208        );
209    } else {
210        if !trait_pred.is_suggestable(tcx, false) {
211            return;
212        }
213        // Trivial case: `T` needs an extra bound: `T: Bound`.
214        let (sp, suggestion) = match (
215            hir_generics
216                .params
217                .iter()
218                .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, .. })),
219            super_traits,
220        ) {
221            (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
222            (None, Some((ident, []))) => (
223                ident.span.shrink_to_hi(),
224                ::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()),
225            ),
226            (_, Some((_, [.., bounds]))) => (
227                bounds.span().shrink_to_hi(),
228                ::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()),
229            ),
230            (Some(_), Some((_, []))) => (
231                hir_generics.span.shrink_to_hi(),
232                ::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()),
233            ),
234        };
235
236        err.span_suggestion_verbose(
237            sp,
238            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider further restricting {0}",
                msg))
    })format!("consider further restricting {msg}"),
239            suggestion,
240            Applicability::MachineApplicable,
241        );
242    }
243}
244
245/// A single layer of `&` peeled from an expression, used by
246/// [`TypeErrCtxt::peel_expr_refs`].
247struct PeeledRef<'tcx> {
248    /// The span covering the `&` (and any whitespace/mutability keyword) to remove.
249    span: Span,
250    /// The type after peeling this layer (and all prior layers).
251    peeled_ty: Ty<'tcx>,
252}
253
254impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
255    pub fn note_field_shadowed_by_private_candidate_in_cause(
256        &self,
257        err: &mut Diag<'_>,
258        cause: &ObligationCause<'tcx>,
259        param_env: ty::ParamEnv<'tcx>,
260    ) {
261        let mut hir_ids = FxHashSet::default();
262        // Walk the parent chain so we can recover
263        // the source expression from whichever layer carries them.
264        let mut next_code = Some(cause.code());
265        while let Some(cause_code) = next_code {
266            match cause_code {
267                ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
268                    hir_ids.insert(*lhs_hir_id);
269                    hir_ids.insert(*rhs_hir_id);
270                }
271                ObligationCauseCode::FunctionArg { arg_hir_id, .. }
272                | ObligationCauseCode::ReturnValue(arg_hir_id)
273                | ObligationCauseCode::AwaitableExpr(arg_hir_id)
274                | ObligationCauseCode::BlockTailExpression(arg_hir_id, _)
275                | ObligationCauseCode::UnOp { hir_id: arg_hir_id } => {
276                    hir_ids.insert(*arg_hir_id);
277                }
278                ObligationCauseCode::OpaqueReturnType(Some((_, hir_id))) => {
279                    hir_ids.insert(*hir_id);
280                }
281                _ => {}
282            }
283            next_code = cause_code.parent();
284        }
285
286        if !cause.span.is_dummy()
287            && let Some(body) = self.tcx.hir_maybe_body_owned_by(cause.body_def_id)
288        {
289            let mut expr_finder = FindExprBySpan::new(cause.span, self.tcx);
290            expr_finder.visit_body(body);
291            if let Some(expr) = expr_finder.result {
292                hir_ids.insert(expr.hir_id);
293            }
294        }
295
296        // we will sort immediately by source order before emitting any diagnostics
297        #[allow(rustc::potential_query_instability)]
298        let mut hir_ids: Vec<_> = hir_ids.into_iter().collect();
299        let source_map = self.tcx.sess.source_map();
300        hir_ids.sort_by_cached_key(|hir_id| {
301            let span = self.tcx.hir_span(*hir_id);
302            let lo = source_map.lookup_byte_offset(span.lo());
303            let hi = source_map.lookup_byte_offset(span.hi());
304            (lo.sf.name.prefer_remapped_unconditionally().to_string(), lo.pos.0, hi.pos.0)
305        });
306
307        for hir_id in hir_ids {
308            self.note_field_shadowed_by_private_candidate(err, hir_id, param_env);
309        }
310    }
311
312    pub fn note_field_shadowed_by_private_candidate(
313        &self,
314        err: &mut Diag<'_>,
315        hir_id: hir::HirId,
316        param_env: ty::ParamEnv<'tcx>,
317    ) {
318        let Some(typeck_results) = &self.typeck_results else {
319            return;
320        };
321        let Node::Expr(expr) = self.tcx.hir_node(hir_id) else {
322            return;
323        };
324        let hir::ExprKind::Field(base_expr, field_ident) = expr.kind else {
325            return;
326        };
327
328        let Some(base_ty) = typeck_results.expr_ty_opt(base_expr) else {
329            return;
330        };
331        let base_ty = self.deeply_resolve_ignoring_regions(base_ty);
332        if base_ty.references_error() {
333            return;
334        }
335
336        let mut private_candidate: Option<(Ty<'tcx>, Ty<'tcx>, Span)> = None;
337
338        for (deref_base_ty, _) in (self.autoderef_steps)(base_ty) {
339            let ty::Adt(base_def, args) = deref_base_ty.kind() else {
340                continue;
341            };
342
343            if base_def.is_enum() {
344                continue;
345            }
346
347            let (adjusted_ident, def_scope) = self.tcx.adjust_ident_and_get_scope(
348                field_ident,
349                base_def.did(),
350                self.tcx.parent_module_from_def_id(typeck_results.hir_owner.def_id),
351            );
352
353            let Some((_, field_def)) =
354                base_def.non_enum_variant().fields.iter_enumerated().find(|(_, field)| {
355                    field.ident(self.tcx).normalize_to_macros_2_0() == adjusted_ident
356                })
357            else {
358                continue;
359            };
360            let field_span = self
361                .tcx
362                .def_ident_span(field_def.did)
363                .unwrap_or_else(|| self.tcx.def_span(field_def.did));
364
365            if field_def.vis.is_accessible_from(def_scope, self.tcx) {
366                let accessible_field_ty = field_def.ty(self.tcx, args).skip_norm_wip();
367                if let Some((private_base_ty, private_field_ty, private_field_span)) =
368                    private_candidate
369                    && !self.can_eq(param_env, private_field_ty, accessible_field_ty)
370                {
371                    let private_struct_span = match private_base_ty.kind() {
372                        ty::Adt(private_base_def, _) => self
373                            .tcx
374                            .def_ident_span(private_base_def.did())
375                            .unwrap_or_else(|| self.tcx.def_span(private_base_def.did())),
376                        _ => DUMMY_SP,
377                    };
378                    let accessible_struct_span = self
379                        .tcx
380                        .def_ident_span(base_def.did())
381                        .unwrap_or_else(|| self.tcx.def_span(base_def.did()));
382                    let deref_impl_span = (typeck_results
383                        .expr_adjustments(base_expr)
384                        .iter()
385                        .filter(|adj| {
386                            #[allow(non_exhaustive_omitted_patterns)] match adj.kind {
    Adjust::Deref(DerefAdjustKind::Overloaded(_)) => true,
    _ => false,
}matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))
387                        })
388                        .count()
389                        == 1)
390                        .then(|| {
391                            self.probe(|_| {
392                                let deref_trait_did =
393                                    self.tcx.require_lang_item(LangItem::Deref, DUMMY_SP);
394                                let trait_ref =
395                                    ty::TraitRef::new(self.tcx, deref_trait_did, [private_base_ty]);
396                                let obligation: Obligation<'tcx, ty::Predicate<'tcx>> =
397                                    Obligation::new(
398                                        self.tcx,
399                                        ObligationCause::dummy(),
400                                        param_env,
401                                        trait_ref,
402                                    );
403                                let Ok(Some(ImplSource::UserDefined(impl_data))) =
404                                    SelectionContext::new(self)
405                                        .select(&obligation.with(self.tcx, trait_ref))
406                                else {
407                                    return None;
408                                };
409                                Some(self.tcx.def_span(impl_data.impl_def_id))
410                            })
411                        })
412                        .flatten();
413
414                    let mut note_spans: MultiSpan = private_struct_span.into();
415                    if private_struct_span != DUMMY_SP {
416                        note_spans.push_span_label(private_struct_span, "in this struct");
417                    }
418                    if private_field_span != DUMMY_SP {
419                        note_spans.push_span_label(
420                            private_field_span,
421                            "if this field wasn't private, it would be accessible",
422                        );
423                    }
424                    if accessible_struct_span != DUMMY_SP {
425                        note_spans.push_span_label(
426                            accessible_struct_span,
427                            "this struct is accessible through auto-deref",
428                        );
429                    }
430                    if field_span != DUMMY_SP {
431                        note_spans
432                            .push_span_label(field_span, "this is the field that was accessed");
433                    }
434                    if let Some(deref_impl_span) = deref_impl_span
435                        && deref_impl_span != DUMMY_SP
436                    {
437                        note_spans.push_span_label(
438                            deref_impl_span,
439                            "the field was accessed through this `Deref`",
440                        );
441                    }
442
443                    err.span_note(
444                        note_spans,
445                        ::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!(
446                            "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"
447                        ),
448                    );
449                }
450
451                // we finally get to the accessible field,
452                // so we can return early without checking the rest of the autoderef candidates
453                return;
454            }
455
456            private_candidate.get_or_insert((
457                deref_base_ty,
458                field_def.ty(self.tcx, args).skip_norm_wip(),
459                field_span,
460            ));
461        }
462    }
463
464    pub fn suggest_restricting_param_bound(
465        &self,
466        err: &mut Diag<'_>,
467        trait_pred: ty::PolyTraitClause<'tcx>,
468        associated_ty: Option<(&'static str, Ty<'tcx>)>,
469        mut body_def_id: LocalDefId,
470    ) {
471        if trait_pred.skip_binder().polarity != ty::ClausePolarity::Positive {
472            return;
473        }
474
475        let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
476
477        let self_ty = trait_pred.skip_binder().self_ty();
478        let (param_ty, projection) = match *self_ty.kind() {
479            ty::Param(_) => (true, None),
480            ty::Alias(_, alias) => {
481                if let Some(projection) = alias.try_to_projection() {
482                    (false, Some(projection))
483                } else {
484                    (false, None)
485                }
486            }
487            _ => (false, None),
488        };
489
490        let mut finder = ParamFinder { .. };
491        finder.visit_binder(&trait_pred);
492
493        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
494        //        don't suggest `T: Sized + ?Sized`.
495        loop {
496            let node = self.tcx.hir_node_by_def_id(body_def_id);
497            match node {
498                hir::Node::Item(hir::Item {
499                    kind: hir::ItemKind::Trait { ident, generics, bounds, .. },
500                    ..
501                }) if self_ty == self.tcx.types.self_param => {
502                    if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
503                    // Restricting `Self` for a single method.
504                    suggest_restriction(
505                        self.tcx,
506                        body_def_id,
507                        generics,
508                        "`Self`",
509                        err,
510                        None,
511                        projection,
512                        trait_pred,
513                        Some((&ident, bounds)),
514                    );
515                    return;
516                }
517
518                hir::Node::TraitItem(hir::TraitItem {
519                    generics,
520                    kind: hir::TraitItemKind::Fn(..),
521                    ..
522                }) if self_ty == self.tcx.types.self_param => {
523                    if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
524                    // Restricting `Self` for a single method.
525                    suggest_restriction(
526                        self.tcx,
527                        body_def_id,
528                        generics,
529                        "`Self`",
530                        err,
531                        None,
532                        projection,
533                        trait_pred,
534                        None,
535                    );
536                    return;
537                }
538
539                hir::Node::TraitItem(hir::TraitItem {
540                    generics,
541                    kind: hir::TraitItemKind::Fn(fn_sig, ..),
542                    ..
543                })
544                | hir::Node::ImplItem(hir::ImplItem {
545                    generics,
546                    kind: hir::ImplItemKind::Fn(fn_sig, ..),
547                    ..
548                })
549                | hir::Node::Item(hir::Item {
550                    kind: hir::ItemKind::Fn { sig: fn_sig, generics, .. },
551                    ..
552                }) if projection.is_some() => {
553                    // Missing restriction on associated type of type parameter (unmet projection).
554                    suggest_restriction(
555                        self.tcx,
556                        body_def_id,
557                        generics,
558                        "the associated type",
559                        err,
560                        Some(fn_sig),
561                        projection,
562                        trait_pred,
563                        None,
564                    );
565                    return;
566                }
567                hir::Node::Item(hir::Item {
568                    kind:
569                        hir::ItemKind::Trait { generics, .. }
570                        | hir::ItemKind::Impl(hir::Impl { generics, .. }),
571                    ..
572                }) if projection.is_some() => {
573                    // Missing restriction on associated type of type parameter (unmet projection).
574                    suggest_restriction(
575                        self.tcx,
576                        body_def_id,
577                        generics,
578                        "the associated type",
579                        err,
580                        None,
581                        projection,
582                        trait_pred,
583                        None,
584                    );
585                    return;
586                }
587
588                hir::Node::Item(hir::Item {
589                    kind:
590                        hir::ItemKind::Struct(_, generics, _)
591                        | hir::ItemKind::Enum(_, generics, _)
592                        | hir::ItemKind::Union(_, generics, _)
593                        | hir::ItemKind::Trait { generics, .. }
594                        | hir::ItemKind::Impl(hir::Impl { generics, .. })
595                        | hir::ItemKind::Fn { generics, .. }
596                        | hir::ItemKind::TyAlias(_, generics, _)
597                        | hir::ItemKind::Const(_, generics, _, _)
598                        | hir::ItemKind::TraitAlias(_, _, generics, _),
599                    ..
600                })
601                | hir::Node::TraitItem(hir::TraitItem { generics, .. })
602                | hir::Node::ImplItem(hir::ImplItem { generics, .. })
603                    if param_ty =>
604                {
605                    // We skip the 0'th arg (self) because we do not want
606                    // to consider the predicate as not suggestible if the
607                    // self type is an arg position `impl Trait` -- instead,
608                    // we handle that by adding ` + Bound` below.
609                    // FIXME(compiler-errors): It would be nice to do the same
610                    // this that we do in `suggest_restriction` and pull the
611                    // `impl Trait` into a new generic if it shows up somewhere
612                    // else in the predicate.
613                    if !trait_pred.skip_binder().trait_ref.args[1..]
614                        .iter()
615                        .all(|g| g.is_suggestable(self.tcx, false))
616                    {
617                        return;
618                    }
619                    // Missing generic type parameter bound.
620                    let param_name = self_ty.to_string();
621                    let mut constraint = {
    let _guard = NoTrimmedGuard::new();
    trait_pred.print_modifiers_and_trait_path().to_string()
}with_no_trimmed_paths!(
622                        trait_pred.print_modifiers_and_trait_path().to_string()
623                    );
624
625                    if let Some((name, term)) = associated_ty {
626                        // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
627                        // That should be extracted into a helper function.
628                        if let Some(stripped) = constraint.strip_suffix('>') {
629                            constraint = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, {1} = {2}>", stripped, name,
                term))
    })format!("{stripped}, {name} = {term}>");
630                        } else {
631                            constraint.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} = {1}>", name, term))
    })format!("<{name} = {term}>"));
632                        }
633                    }
634
635                    if suggest_constraining_type_param(
636                        self.tcx,
637                        generics,
638                        err,
639                        &param_name,
640                        &constraint,
641                        Some(trait_pred.def_id()),
642                        None,
643                    ) {
644                        return;
645                    }
646                }
647
648                hir::Node::TraitItem(hir::TraitItem {
649                    generics,
650                    kind: hir::TraitItemKind::Fn(..),
651                    ..
652                })
653                | hir::Node::ImplItem(hir::ImplItem {
654                    generics,
655                    impl_kind: hir::ImplItemImplKind::Inherent { .. },
656                    kind: hir::ImplItemKind::Fn(..),
657                    ..
658                }) if finder.can_suggest_bound(generics) => {
659                    // Missing generic type parameter bound.
660                    suggest_arbitrary_trait_bound(
661                        self.tcx,
662                        generics,
663                        err,
664                        trait_pred,
665                        associated_ty,
666                    );
667                }
668                hir::Node::Item(hir::Item {
669                    kind:
670                        hir::ItemKind::Struct(_, generics, _)
671                        | hir::ItemKind::Enum(_, generics, _)
672                        | hir::ItemKind::Union(_, generics, _)
673                        | hir::ItemKind::Trait { generics, .. }
674                        | hir::ItemKind::Impl(hir::Impl { generics, .. })
675                        | hir::ItemKind::Fn { generics, .. }
676                        | hir::ItemKind::TyAlias(_, generics, _)
677                        | hir::ItemKind::Const(_, generics, _, _)
678                        | hir::ItemKind::TraitAlias(_, _, generics, _),
679                    ..
680                }) if finder.can_suggest_bound(generics) => {
681                    // Missing generic type parameter bound.
682                    if suggest_arbitrary_trait_bound(
683                        self.tcx,
684                        generics,
685                        err,
686                        trait_pred,
687                        associated_ty,
688                    ) {
689                        return;
690                    }
691                }
692                hir::Node::Crate(..) => return,
693
694                _ => {}
695            }
696            body_def_id = self.tcx.local_parent(body_def_id);
697        }
698    }
699
700    /// Provide a suggestion to dereference arguments to functions and binary operators, if that
701    /// would satisfy trait bounds.
702    pub(super) fn suggest_dereferences(
703        &self,
704        obligation: &PredicateObligation<'tcx>,
705        err: &mut Diag<'_>,
706        trait_pred: ty::PolyTraitClause<'tcx>,
707    ) -> bool {
708        let mut code = obligation.cause.code();
709        if let ObligationCauseCode::FunctionArg { arg_hir_id, call_hir_id, .. } = code
710            && let Some(typeck_results) = &self.typeck_results
711            && let hir::Node::Expr(expr) = self.tcx.hir_node(*arg_hir_id)
712            && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
713        {
714            // Suggest dereferencing the argument to a function/method call if possible
715
716            // Get the root obligation, since the leaf obligation we have may be unhelpful (#87437)
717            let mut real_trait_pred = trait_pred;
718            while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
719                code = parent_code;
720                if let Some(parent_trait_pred) = parent_trait_pred {
721                    real_trait_pred = parent_trait_pred;
722                }
723            }
724
725            // We `instantiate_bound_regions_with_erased` here because `make_subregion` does not handle
726            // `ReBound`, and we don't particularly care about the regions.
727            let real_ty = self.tcx.instantiate_bound_regions_with_erased(real_trait_pred.self_ty());
728            if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
729                return false;
730            }
731
732            // Potentially, we'll want to place our dereferences under a `&`. We don't try this for
733            // `&mut`, since we can't be sure users will get the side-effects they want from it.
734            // If this doesn't work, we'll try removing the `&` in `suggest_remove_reference`.
735            // FIXME(dianne): this misses the case where users need both to deref and remove `&`s.
736            // This method could be combined with `TypeErrCtxt::suggest_remove_reference` to handle
737            // that, similar to what `FnCtxt::suggest_deref_or_ref` does.
738            let (is_under_ref, base_ty, span) = match expr.kind {
739                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, subexpr)
740                    if let &ty::Ref(region, base_ty, hir::Mutability::Not) = real_ty.kind() =>
741                {
742                    (Some(region), base_ty, subexpr.span)
743                }
744                // Don't suggest `*&mut`, etc.
745                hir::ExprKind::AddrOf(..) => return false,
746                _ => (None, real_ty, obligation.cause.span),
747            };
748
749            let autoderef = (self.autoderef_steps)(base_ty);
750            let mut is_boxed = base_ty.is_box();
751            if let Some(steps) = autoderef.into_iter().position(|(mut ty, obligations)| {
752                // Ensure one of the following for dereferencing to be valid: we're passing by
753                // reference, `ty` is `Copy`, or we're moving out of a (potentially nested) `Box`.
754                let can_deref = is_under_ref.is_some()
755                    || self.type_is_copy_modulo_regions(obligation.param_env, ty)
756                    || ty.is_numeric() // for inference vars (presumably but not provably `Copy`)
757                    || is_boxed && self.type_is_sized_modulo_regions(obligation.param_env, ty);
758                is_boxed &= ty.is_box();
759
760                // Re-add the `&` if necessary
761                if let Some(region) = is_under_ref {
762                    ty = Ty::new_ref(self.tcx, region, ty, hir::Mutability::Not);
763                }
764
765                // Remapping bound vars here
766                let real_trait_pred_and_ty =
767                    real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
768                let obligation = self.mk_trait_obligation_with_new_self_ty(
769                    obligation.param_env,
770                    real_trait_pred_and_ty,
771                );
772
773                can_deref
774                    && obligations
775                        .iter()
776                        .chain([&obligation])
777                        .all(|obligation| self.predicate_may_hold(obligation))
778            }) && steps > 0
779            {
780                if span.in_external_macro(self.tcx.sess.source_map()) {
781                    return false;
782                }
783
784                // For a shared reference, prefer removing the outer `&` over suggesting
785                // `&*reference`. Keep the reborrow for `&mut T` and smart pointers.
786                if is_under_ref.is_some()
787                    && steps == 1
788                    && #[allow(non_exhaustive_omitted_patterns)] match base_ty.kind() {
    ty::Ref(_, _, hir::Mutability::Not) => true,
    _ => false,
}matches!(base_ty.kind(), ty::Ref(_, _, hir::Mutability::Not))
789                    && !expr.span.from_expansion()
790                    && self.suggest_remove_reference(obligation, err, real_trait_pred)
791                {
792                    return true;
793                }
794                let derefs = "*".repeat(steps);
795                let msg = "consider dereferencing here";
796
797                let call_node = self.tcx.hir_node(*call_hir_id);
798                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!(
799                    call_node,
800                    Node::Expr(hir::Expr {
801                        kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
802                        ..
803                    })
804                    if receiver_expr.hir_id == *arg_hir_id
805                );
806                if is_receiver {
807                    err.multipart_suggestion(
808                        msg,
809                        ::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![
810                            (span.shrink_to_lo(), format!("({derefs}")),
811                            (span.shrink_to_hi(), ")".to_string()),
812                        ],
813                        Applicability::MachineApplicable,
814                    )
815                } else {
816                    err.span_suggestion_verbose(
817                        span.shrink_to_lo(),
818                        msg,
819                        derefs,
820                        Applicability::MachineApplicable,
821                    )
822                };
823                return true;
824            }
825        } else if let (
826            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. },
827            predicate,
828        ) = code.peel_derives_with_predicate()
829            && let Some(typeck_results) = &self.typeck_results
830            && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id)
831            && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id)
832            && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs)
833            && let trait_pred = predicate.unwrap_or(trait_pred)
834            // Only run this code on binary operators
835            && lang_items::BINARY_OPERATORS
836                .iter()
837                .filter_map(|&op| self.tcx.lang_items().get(op))
838                .any(|op| {
839                    op == trait_pred.skip_binder().trait_ref.def_id
840                })
841        {
842            // Suggest dereferencing the LHS, RHS, or both terms of a binop if possible
843            let trait_pred = predicate.unwrap_or(trait_pred);
844            let lhs_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
845            let lhs_autoderef = (self.autoderef_steps)(lhs_ty);
846            let rhs_autoderef = (self.autoderef_steps)(rhs_ty);
847            let first_lhs = lhs_autoderef.first().unwrap().clone();
848            let first_rhs = rhs_autoderef.first().unwrap().clone();
849            let mut autoderefs = lhs_autoderef
850                .into_iter()
851                .enumerate()
852                .rev()
853                .zip_longest(rhs_autoderef.into_iter().enumerate().rev())
854                .map(|t| match t {
855                    EitherOrBoth::Both(a, b) => (a, b),
856                    EitherOrBoth::Left(a) => (a, (0, first_rhs.clone())),
857                    EitherOrBoth::Right(b) => ((0, first_lhs.clone()), b),
858                })
859                .rev();
860            if let Some((lsteps, rsteps)) =
861                autoderefs.find_map(|((lsteps, (l_ty, _)), (rsteps, (r_ty, _)))| {
862                    // Create a new predicate with the dereferenced LHS and RHS
863                    // We simultaneously dereference both sides rather than doing them
864                    // one at a time to account for cases such as &Box<T> == &&T
865                    let trait_pred_and_ty = trait_pred.map_bound(|inner| {
866                        (
867                            ty::TraitClause {
868                                trait_ref: ty::TraitRef::new_from_args(
869                                    self.tcx,
870                                    inner.trait_ref.def_id,
871                                    self.tcx.mk_args(
872                                        &[&[l_ty.into(), r_ty.into()], &inner.trait_ref.args[2..]]
873                                            .concat(),
874                                    ),
875                                ),
876                                ..inner
877                            },
878                            l_ty,
879                        )
880                    });
881                    let obligation = self.mk_trait_obligation_with_new_self_ty(
882                        obligation.param_env,
883                        trait_pred_and_ty,
884                    );
885                    self.predicate_may_hold(&obligation).then_some(match (lsteps, rsteps) {
886                        (_, 0) => (Some(lsteps), None),
887                        (0, _) => (None, Some(rsteps)),
888                        _ => (Some(lsteps), Some(rsteps)),
889                    })
890                })
891            {
892                let make_sugg = |mut expr: &Expr<'_>, mut steps| {
893                    if expr.span.in_external_macro(self.tcx.sess.source_map()) {
894                        return None;
895                    }
896                    let mut prefix_span = expr.span.shrink_to_lo();
897                    let mut msg = "consider dereferencing here";
898                    if let hir::ExprKind::AddrOf(_, _, inner) = expr.kind {
899                        msg = "consider removing the borrow and dereferencing instead";
900                        if let hir::ExprKind::AddrOf(..) = inner.kind {
901                            msg = "consider removing the borrows and dereferencing instead";
902                        }
903                    }
904                    while let hir::ExprKind::AddrOf(_, _, inner) = expr.kind
905                        && steps > 0
906                    {
907                        prefix_span = prefix_span.with_hi(inner.span.lo());
908                        expr = inner;
909                        steps -= 1;
910                    }
911                    // Empty suggestions with empty spans ICE with debug assertions
912                    if steps == 0 {
913                        return Some((
914                            msg.trim_end_matches(" and dereferencing instead"),
915                            ::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())],
916                        ));
917                    }
918                    let derefs = "*".repeat(steps);
919                    let needs_parens = steps > 0 && expr_needs_parens(expr);
920                    let mut suggestion = if needs_parens {
921                        ::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![
922                            (
923                                expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
924                                format!("{derefs}("),
925                            ),
926                            (expr.span.shrink_to_hi(), ")".to_string()),
927                        ]
928                    } else {
929                        ::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![(
930                            expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
931                            format!("{derefs}"),
932                        )]
933                    };
934                    // Empty suggestions with empty spans ICE with debug assertions
935                    if !prefix_span.is_empty() {
936                        suggestion.push((prefix_span, String::new()));
937                    }
938                    Some((msg, suggestion))
939                };
940
941                if let Some(lsteps) = lsteps
942                    && let Some(rsteps) = rsteps
943                    && lsteps > 0
944                    && rsteps > 0
945                {
946                    let Some((_, mut suggestion)) = make_sugg(lhs, lsteps) else {
947                        return false;
948                    };
949                    let Some((_, mut rhs_suggestion)) = make_sugg(rhs, rsteps) else {
950                        return false;
951                    };
952                    suggestion.append(&mut rhs_suggestion);
953                    err.multipart_suggestion(
954                        "consider dereferencing both sides of the expression",
955                        suggestion,
956                        Applicability::MachineApplicable,
957                    );
958                    return true;
959                } else if let Some(lsteps) = lsteps
960                    && lsteps > 0
961                {
962                    let Some((msg, suggestion)) = make_sugg(lhs, lsteps) else {
963                        return false;
964                    };
965                    err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
966                    return true;
967                } else if let Some(rsteps) = rsteps
968                    && rsteps > 0
969                {
970                    let Some((msg, suggestion)) = make_sugg(rhs, rsteps) else {
971                        return false;
972                    };
973                    err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
974                    return true;
975                }
976            }
977        }
978        false
979    }
980
981    /// Given a closure's `DefId`, return the given name of the closure.
982    ///
983    /// This doesn't account for reassignments, but it's only used for suggestions.
984    fn get_closure_name(
985        &self,
986        def_id: DefId,
987        err: &mut Diag<'_>,
988        msg: Cow<'static, str>,
989    ) -> Option<Symbol> {
990        let get_name = |err: &mut Diag<'_>, kind: &hir::PatKind<'_>| -> Option<Symbol> {
991            // Get the local name of this closure. This can be inaccurate because
992            // of the possibility of reassignment, but this should be good enough.
993            match &kind {
994                hir::PatKind::Binding(hir::BindingMode::NONE, _, ident, None) => Some(ident.name),
995                _ => {
996                    err.note(msg);
997                    None
998                }
999            }
1000        };
1001
1002        let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?);
1003        match self.tcx.parent_hir_node(hir_id) {
1004            hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => {
1005                get_name(err, &local.pat.kind)
1006            }
1007            // Different to previous arm because one is `&hir::Local` and the other
1008            // is `Box<hir::Local>`.
1009            hir::Node::LetStmt(local) => get_name(err, &local.pat.kind),
1010            _ => None,
1011        }
1012    }
1013
1014    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
1015    /// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling
1016    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
1017    pub(super) fn suggest_fn_call(
1018        &self,
1019        obligation: &PredicateObligation<'tcx>,
1020        err: &mut Diag<'_>,
1021        trait_pred: ty::PolyTraitClause<'tcx>,
1022    ) -> bool {
1023        // It doesn't make sense to make this suggestion outside of typeck...
1024        // (also autoderef will ICE...)
1025        if self.typeck_results.is_none() {
1026            return false;
1027        }
1028
1029        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
1030            obligation.predicate.kind().skip_binder()
1031            && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
1032        {
1033            // Don't suggest calling to turn an unsized type into a sized type
1034            return false;
1035        }
1036
1037        let self_ty = self.instantiate_binder_with_fresh_vars(
1038            DUMMY_SP,
1039            BoundRegionConversionTime::FnCall,
1040            trait_pred.self_ty(),
1041        );
1042
1043        let Some((def_id_or_name, output, inputs)) =
1044            self.extract_callable_info(obligation.cause.body_def_id, obligation.param_env, self_ty)
1045        else {
1046            return false;
1047        };
1048
1049        // Remapping bound vars here
1050        let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
1051
1052        let new_obligation =
1053            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
1054        if !self.predicate_must_hold_modulo_regions(&new_obligation) {
1055            return false;
1056        }
1057
1058        // If this is a zero-argument async closure directly passed as an argument
1059        // and the expected type is `Future`, suggest using `async {}` block instead
1060        // of `async || {}`
1061        if let ty::CoroutineClosure(def_id, args) = *self_ty.kind()
1062            && let sig = args.as_coroutine_closure().coroutine_closure_sig().skip_binder()
1063            && let ty::Tuple(inputs) = *sig.tupled_inputs_ty.kind()
1064            && inputs.is_empty()
1065            && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Future)
1066            && let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
1067            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) =
1068                self.tcx.hir_node(*arg_hir_id)
1069            && let Some(hir::Node::Expr(hir::Expr {
1070                kind: hir::ExprKind::Closure(closure), ..
1071            })) = self.tcx.hir_get_if_local(def_id)
1072            && let hir::ClosureKind::CoroutineClosure(CoroutineDesugaring::Async) = closure.kind
1073            && let Some(arg_span) = closure.fn_arg_span
1074            && obligation.cause.span.contains(arg_span)
1075        {
1076            let mut body = self.tcx.hir_body(closure.body).value;
1077            let peeled = body.peel_blocks().peel_drop_temps();
1078            if let hir::ExprKind::Closure(inner) = peeled.kind {
1079                body = self.tcx.hir_body(inner.body).value;
1080            }
1081            if !#[allow(non_exhaustive_omitted_patterns)] match body.peel_blocks().peel_drop_temps().kind
    {
    hir::ExprKind::Block(..) => true,
    _ => false,
}matches!(body.peel_blocks().peel_drop_temps().kind, hir::ExprKind::Block(..)) {
1082                return false;
1083            }
1084
1085            let sm = self.tcx.sess.source_map();
1086            let removal_span = if let Ok(snippet) =
1087                sm.span_to_snippet(arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1)))
1088                && snippet.ends_with(' ')
1089            {
1090                // There's a space after `||`, include it in the removal
1091                arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1))
1092            } else {
1093                arg_span
1094            };
1095            err.span_suggestion_verbose(
1096                removal_span,
1097                "use `async {}` instead of `async || {}` to introduce an async block",
1098                "",
1099                Applicability::MachineApplicable,
1100            );
1101            return true;
1102        }
1103
1104        // Get the name of the callable and the arguments to be used in the suggestion.
1105        let msg = match def_id_or_name {
1106            DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
1107                DefKind::Ctor(CtorOf::Struct, _) => {
1108                    Cow::from("use parentheses to construct this tuple struct")
1109                }
1110                DefKind::Ctor(CtorOf::Variant, _) => {
1111                    Cow::from("use parentheses to construct this tuple variant")
1112                }
1113                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!(
1114                    "use parentheses to call this {}",
1115                    self.tcx.def_kind_descr(kind, def_id)
1116                )),
1117            },
1118            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}")),
1119        };
1120
1121        let args = inputs
1122            .into_iter()
1123            .map(|ty| {
1124                if ty.is_suggestable(self.tcx, false) {
1125                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", ty))
    })format!("/* {ty} */")
1126                } else {
1127                    "/* value */".to_string()
1128                }
1129            })
1130            .collect::<Vec<_>>()
1131            .join(", ");
1132
1133        let callee_hir_id = match obligation.cause.code() {
1134            ObligationCauseCode::FunctionArg { arg_hir_id, .. }
1135                if obligation.cause.span.can_be_used_for_suggestions() =>
1136            {
1137                Some(*arg_hir_id)
1138            }
1139            // The iterator of a `for` loop is passed to `IntoIterator::into_iter`, so the failing
1140            // `Iterator` goal is a derived obligation and `cause.span` carries the loop's
1141            // desugaring context. The expression is still the user's, which its own span attests.
1142            code => match code.peel_derives() {
1143                ObligationCauseCode::ForLoopIterator(iter_hir_id)
1144                    if self.tcx.hir_span(*iter_hir_id).can_be_used_for_suggestions() =>
1145                {
1146                    Some(*iter_hir_id)
1147                }
1148                _ => None,
1149            },
1150        };
1151
1152        if let Some(callee_hir_id) = callee_hir_id {
1153            let span = obligation.cause.span;
1154
1155            let arg_expr = match self.tcx.hir_node(callee_hir_id) {
1156                hir::Node::Expr(expr) => Some(expr),
1157                _ => None,
1158            };
1159
1160            let is_closure_expr =
1161                arg_expr.is_some_and(|expr| #[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    hir::ExprKind::Closure(..) => true,
    _ => false,
}matches!(expr.kind, hir::ExprKind::Closure(..)));
1162
1163            // If the user wrote `|| {}()`, suggesting to call the closure would produce `(|| {}())()`,
1164            // which doesn't help and is often outright wrong.
1165            if args.is_empty()
1166                && let Some(expr) = arg_expr
1167                && let hir::ExprKind::Closure(closure) = expr.kind
1168            {
1169                let mut body = self.tcx.hir_body(closure.body).value;
1170
1171                // Async closures desugar to a closure returning a coroutine
1172                if let hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) =
1173                    closure.kind
1174                {
1175                    let peeled = body.peel_blocks().peel_drop_temps();
1176                    if let hir::ExprKind::Closure(inner) = peeled.kind {
1177                        body = self.tcx.hir_body(inner.body).value;
1178                    }
1179                }
1180
1181                let peeled_body = body.peel_blocks().peel_drop_temps();
1182                if let hir::ExprKind::Call(callee, call_args) = peeled_body.kind
1183                    && call_args.is_empty()
1184                    && let hir::ExprKind::Block(..) = callee.peel_blocks().peel_drop_temps().kind
1185                {
1186                    return false;
1187                }
1188            }
1189
1190            if is_closure_expr {
1191                err.multipart_suggestions(
1192                    msg,
1193                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                        [(span.shrink_to_lo(), "(".to_string()),
                                (span.shrink_to_hi(),
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!(")({0})", args))
                                        }))]))]))vec![vec![
1194                        (span.shrink_to_lo(), "(".to_string()),
1195                        (span.shrink_to_hi(), format!(")({args})")),
1196                    ]],
1197                    Applicability::HasPlaceholders,
1198                );
1199            } else {
1200                err.span_suggestion_verbose(
1201                    span.shrink_to_hi(),
1202                    msg,
1203                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0})", args))
    })format!("({args})"),
1204                    Applicability::HasPlaceholders,
1205                );
1206            }
1207        } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
1208            let name = match self.tcx.hir_get_if_local(def_id) {
1209                Some(hir::Node::Expr(hir::Expr {
1210                    kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
1211                    ..
1212                })) => {
1213                    err.span_label(*fn_decl_span, "consider calling this closure");
1214                    let Some(name) = self.get_closure_name(def_id, err, msg.clone()) else {
1215                        return false;
1216                    };
1217                    name.to_string()
1218                }
1219                Some(hir::Node::Item(hir::Item {
1220                    kind: hir::ItemKind::Fn { ident, .. }, ..
1221                })) => {
1222                    err.span_label(ident.span, "consider calling this function");
1223                    ident.to_string()
1224                }
1225                Some(hir::Node::Ctor(..)) => {
1226                    let name = self.tcx.def_path_str(def_id);
1227                    err.span_label(
1228                        self.tcx.def_span(def_id),
1229                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider calling the constructor for `{0}`",
                name))
    })format!("consider calling the constructor for `{name}`"),
1230                    );
1231                    name
1232                }
1233                _ => return false,
1234            };
1235            err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: `{1}({2})`", msg, name, args))
    })format!("{msg}: `{name}({args})`"));
1236        }
1237        true
1238    }
1239
1240    pub(super) fn suggest_cast_to_fn_pointer(
1241        &self,
1242        obligation: &PredicateObligation<'tcx>,
1243        err: &mut Diag<'_>,
1244        leaf_trait_predicate: ty::PolyTraitClause<'tcx>,
1245        main_trait_predicate: ty::PolyTraitClause<'tcx>,
1246        span: Span,
1247    ) -> bool {
1248        let &[candidate] = &self.find_similar_impl_candidates(leaf_trait_predicate)[..] else {
1249            return false;
1250        };
1251        let candidate = candidate.trait_ref;
1252
1253        if !#[allow(non_exhaustive_omitted_patterns)] match (candidate.self_ty().kind(),
        main_trait_predicate.self_ty().skip_binder().kind()) {
    (ty::FnPtr(..), ty::FnDef(..)) => true,
    _ => false,
}matches!(
1254            (candidate.self_ty().kind(), main_trait_predicate.self_ty().skip_binder().kind(),),
1255            (ty::FnPtr(..), ty::FnDef(..))
1256        ) {
1257            return false;
1258        }
1259
1260        let parenthesized_cast = |span: Span| {
1261            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), "(".to_string()),
                (span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(" as {0})",
                                    candidate.self_ty()))
                        }))]))vec![
1262                (span.shrink_to_lo(), "(".to_string()),
1263                (span.shrink_to_hi(), format!(" as {})", candidate.self_ty())),
1264            ]
1265        };
1266        // Wrap method receivers and `&`-references in parens.
1267        let suggestion = if self.tcx.sess.source_map().span_followed_by(span, ".").is_some() {
1268            parenthesized_cast(span)
1269        } else if let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) {
1270            let mut expr_finder = FindExprBySpan::new(span, self.tcx);
1271            expr_finder.visit_expr(body.value);
1272            if let Some(expr) = expr_finder.result
1273                && let hir::ExprKind::AddrOf(_, _, expr) = expr.kind
1274            {
1275                parenthesized_cast(expr.span)
1276            } else {
1277                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(" as {0}",
                                    candidate.self_ty()))
                        }))]))vec![(span.shrink_to_hi(), format!(" as {}", candidate.self_ty()))]
1278            }
1279        } else {
1280            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(" as {0}",
                                    candidate.self_ty()))
                        }))]))vec![(span.shrink_to_hi(), format!(" as {}", candidate.self_ty()))]
1281        };
1282
1283        let trait_ = self.tcx.short_string(candidate.print_trait_sugared(), err.long_ty_path());
1284        let self_ty = self.tcx.short_string(candidate.self_ty(), err.long_ty_path());
1285        err.multipart_suggestion(
1286            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the trait `{0}` is implemented for fn pointer `{1}`, try casting using `as`",
                trait_, self_ty))
    })format!(
1287                "the trait `{trait_}` is implemented for fn pointer \
1288                 `{self_ty}`, try casting using `as`",
1289            ),
1290            suggestion,
1291            Applicability::MaybeIncorrect,
1292        );
1293        true
1294    }
1295
1296    pub(super) fn check_for_binding_assigned_block_without_tail_expression(
1297        &self,
1298        obligation: &PredicateObligation<'tcx>,
1299        err: &mut Diag<'_>,
1300        trait_pred: ty::PolyTraitClause<'tcx>,
1301    ) {
1302        let mut span = obligation.cause.span;
1303        while span.from_expansion() {
1304            // Remove all the desugaring and macro contexts.
1305            span.remove_mark();
1306        }
1307        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
1308        let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) else {
1309            return;
1310        };
1311        expr_finder.visit_expr(body.value);
1312        let Some(expr) = expr_finder.result else {
1313            return;
1314        };
1315        let Some(typeck) = &self.typeck_results else {
1316            return;
1317        };
1318        let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
1319            return;
1320        };
1321        if !ty.is_unit() {
1322            return;
1323        };
1324        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
1325            return;
1326        };
1327        let Res::Local(hir_id) = path.res else {
1328            return;
1329        };
1330        let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else {
1331            return;
1332        };
1333        let hir::Node::LetStmt(hir::LetStmt { ty: None, init: Some(init), .. }) =
1334            self.tcx.parent_hir_node(pat.hir_id)
1335        else {
1336            return;
1337        };
1338        let hir::ExprKind::Block(block, None) = init.kind else {
1339            return;
1340        };
1341        if block.expr.is_some() {
1342            return;
1343        }
1344        let [.., stmt] = block.stmts else {
1345            err.span_label(block.span, "this empty block is missing a tail expression");
1346            return;
1347        };
1348        // FIXME expr and stmt have the same span if expr comes from expansion
1349        // cc: https://github.com/rust-lang/rust/pull/147416#discussion_r2499407523
1350        if stmt.span.from_expansion() {
1351            return;
1352        }
1353        let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
1354            return;
1355        };
1356        let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
1357            err.span_label(block.span, "this block is missing a tail expression");
1358            return;
1359        };
1360        let ty =
1361            self.resolve_numeric_literals_with_default(self.deeply_resolve_ignoring_regions(ty));
1362        let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty));
1363
1364        let new_obligation =
1365            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
1366        if !#[allow(non_exhaustive_omitted_patterns)] match tail_expr.kind {
    hir::ExprKind::Err(_) => true,
    _ => false,
}matches!(tail_expr.kind, hir::ExprKind::Err(_))
1367            && self.predicate_must_hold_modulo_regions(&new_obligation)
1368        {
1369            err.span_suggestion_short(
1370                stmt.span.with_lo(tail_expr.span.hi()),
1371                "remove this semicolon",
1372                "",
1373                Applicability::MachineApplicable,
1374            );
1375        } else {
1376            err.span_label(block.span, "this block is missing a tail expression");
1377        }
1378    }
1379
1380    pub(super) fn suggest_add_clone_to_arg(
1381        &self,
1382        obligation: &PredicateObligation<'tcx>,
1383        err: &mut Diag<'_>,
1384        trait_pred: ty::PolyTraitClause<'tcx>,
1385    ) -> bool {
1386        let self_ty = self.deeply_resolve_ignoring_regions(trait_pred.self_ty());
1387        self.enter_forall(self_ty, |ty: Ty<'_>| {
1388            let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_def_id) else {
1389                return false;
1390            };
1391            let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
1392            let ty::Param(param) = inner_ty.kind() else { return false };
1393            let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
1394            else {
1395                return false;
1396            };
1397
1398            let clone_trait = self.tcx.require_lang_item(LangItem::Clone, obligation.cause.span);
1399            let has_clone = |ty| {
1400                self.type_implements_trait(clone_trait, [ty], obligation.param_env)
1401                    .must_apply_modulo_regions()
1402            };
1403
1404            let existing_clone_call = match self.tcx.hir_node(*arg_hir_id) {
1405                // It's just a variable. Propose cloning it.
1406                Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) => None,
1407                // It's already a call to `clone()`. We might be able to suggest
1408                // adding a `+ Clone` bound, though.
1409                Node::Expr(Expr {
1410                    kind:
1411                        hir::ExprKind::MethodCall(
1412                            hir::PathSegment { ident, .. },
1413                            _receiver,
1414                            [],
1415                            call_span,
1416                        ),
1417                    hir_id,
1418                    ..
1419                }) if ident.name == sym::clone
1420                    && !call_span.from_expansion()
1421                    && !has_clone(*inner_ty) =>
1422                {
1423                    // We only care about method calls corresponding to the real `Clone` trait.
1424                    let Some(typeck_results) = self.typeck_results.as_ref() else { return false };
1425                    let Some((DefKind::AssocFn, did)) = typeck_results.type_dependent_def(*hir_id)
1426                    else {
1427                        return false;
1428                    };
1429                    if self.tcx.trait_of_assoc(did) != Some(clone_trait) {
1430                        return false;
1431                    }
1432                    Some(ident.span)
1433                }
1434                _ => return false,
1435            };
1436
1437            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1438                obligation.param_env,
1439                trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
1440            );
1441
1442            if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
1443                if !has_clone(param.to_ty(self.tcx)) {
1444                    suggest_constraining_type_param(
1445                        self.tcx,
1446                        generics,
1447                        err,
1448                        param.name.as_str(),
1449                        "Clone",
1450                        Some(clone_trait),
1451                        None,
1452                    );
1453                }
1454                if let Some(existing_clone_call) = existing_clone_call {
1455                    err.span_note(
1456                        existing_clone_call,
1457                        ::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!(
1458                            "this `clone()` copies the reference, \
1459                            which does not do anything, \
1460                            because `{inner_ty}` does not implement `Clone`"
1461                        ),
1462                    );
1463                } else {
1464                    err.span_suggestion_verbose(
1465                        obligation.cause.span.shrink_to_hi(),
1466                        "consider using clone here",
1467                        ".clone()".to_string(),
1468                        Applicability::MaybeIncorrect,
1469                    );
1470                }
1471                return true;
1472            }
1473            false
1474        })
1475    }
1476
1477    /// Extracts information about a callable type for diagnostics. This is a
1478    /// heuristic -- it doesn't necessarily mean that a type is always callable,
1479    /// because the callable type must also be well-formed to be called.
1480    pub fn extract_callable_info(
1481        &self,
1482        body_def_id: LocalDefId,
1483        param_env: ty::ParamEnv<'tcx>,
1484        found: Ty<'tcx>,
1485    ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
1486        // Autoderef is useful here because sometimes we box callables, etc.
1487        let Some((def_id_or_name, output, inputs)) =
1488            (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| match *found.kind() {
1489                ty::FnPtr(sig_tys, _) => Some((
1490                    DefIdOrName::Name("function pointer"),
1491                    sig_tys.output(),
1492                    sig_tys.inputs(),
1493                )),
1494                ty::FnDef(def_id, _) => {
1495                    let fn_sig = found.fn_sig(self.tcx);
1496                    Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
1497                }
1498                ty::Closure(def_id, args) => {
1499                    let fn_sig = args.as_closure().sig();
1500                    Some((
1501                        DefIdOrName::DefId(def_id),
1502                        fn_sig.output(),
1503                        fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()),
1504                    ))
1505                }
1506                ty::CoroutineClosure(def_id, args) => {
1507                    let sig_parts = args.as_coroutine_closure().coroutine_closure_sig();
1508                    Some((
1509                        DefIdOrName::DefId(def_id),
1510                        sig_parts.map_bound(|sig| {
1511                            sig.to_coroutine(
1512                                self.tcx,
1513                                args.as_coroutine_closure().parent_args(),
1514                                // Just use infer vars here, since we  don't really care
1515                                // what these types are, just that we're returning a coroutine.
1516                                self.next_ty_var(DUMMY_SP),
1517                                self.tcx.coroutine_for_closure(def_id),
1518                                self.next_ty_var(DUMMY_SP),
1519                            )
1520                        }),
1521                        sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()),
1522                    ))
1523                }
1524                ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
1525                    self.tcx
1526                        .item_self_bounds(def_id)
1527                        .instantiate(self.tcx, args)
1528                        .skip_norm_wip()
1529                        .iter()
1530                        .find_map(|pred| {
1531                            if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
1532                            && self
1533                                .tcx
1534                                .is_lang_item(proj.def_id(), LangItem::FnOnceOutput)
1535                            // args tuple will always be args[1]
1536                            && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1537                            {
1538                                Some((
1539                                    DefIdOrName::DefId(def_id),
1540                                    pred.kind().rebind(proj.term.expect_type()),
1541                                    pred.kind().rebind(args.as_slice()),
1542                                ))
1543                            } else {
1544                                None
1545                            }
1546                        })
1547                }
1548                ty::Dynamic(data, _) => data.iter().find_map(|pred| {
1549                    if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
1550                        && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput)
1551                        // for existential projection, args are shifted over by 1
1552                        && let ty::Tuple(args) = proj.args.type_at(0).kind()
1553                    {
1554                        Some((
1555                            DefIdOrName::Name("trait object"),
1556                            pred.rebind(proj.term.expect_type()),
1557                            pred.rebind(args.as_slice()),
1558                        ))
1559                    } else {
1560                        None
1561                    }
1562                }),
1563                ty::Param(param) => {
1564                    let generics = self.tcx.generics_of(body_def_id);
1565                    let name = if generics.count() > param.index as usize
1566                        && let def = generics.param_at(param.index as usize, self.tcx)
1567                        && #[allow(non_exhaustive_omitted_patterns)] match def.kind {
    ty::GenericParamDefKind::Type { .. } => true,
    _ => false,
}matches!(def.kind, ty::GenericParamDefKind::Type { .. })
1568                        && def.name == param.name
1569                    {
1570                        DefIdOrName::DefId(def.def_id)
1571                    } else {
1572                        DefIdOrName::Name("type parameter")
1573                    };
1574                    param_env.caller_bounds().find_map(|clause| {
1575                        if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder()
1576                            && self
1577                                .tcx
1578                                .is_lang_item(proj.def_id(), LangItem::FnOnceOutput)
1579                            && proj.projection_term.self_ty() == found
1580                            // args tuple will always be args[1]
1581                            && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1582                        {
1583                            Some((
1584                                name,
1585                                clause.kind().rebind(proj.term.expect_type()),
1586                                clause.kind().rebind(args.as_slice()),
1587                            ))
1588                        } else {
1589                            None
1590                        }
1591                    })
1592                }
1593                _ => None,
1594            })
1595        else {
1596            return None;
1597        };
1598
1599        let output = self.instantiate_binder_with_fresh_vars(
1600            DUMMY_SP,
1601            BoundRegionConversionTime::FnCall,
1602            output,
1603        );
1604        let inputs = inputs
1605            .skip_binder()
1606            .iter()
1607            .map(|ty| {
1608                self.instantiate_binder_with_fresh_vars(
1609                    DUMMY_SP,
1610                    BoundRegionConversionTime::FnCall,
1611                    inputs.rebind(*ty),
1612                )
1613            })
1614            .collect();
1615
1616        // We don't want to register any extra obligations, which should be
1617        // implied by wf, but also because that would possibly result in
1618        // erroneous errors later on.
1619        let InferOk { value: output, obligations: _ } =
1620            self.at(&ObligationCause::dummy(), param_env).normalize(Unnormalized::new_wip(output));
1621
1622        if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
1623    }
1624
1625    pub(super) fn where_clause_expr_matches_failed_self_ty(
1626        &self,
1627        obligation: &PredicateObligation<'tcx>,
1628        old_self_ty: Ty<'tcx>,
1629    ) -> bool {
1630        let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code() else {
1631            return true;
1632        };
1633        let (Some(typeck_results), Some(body)) = (
1634            self.typeck_results.as_ref(),
1635            self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id),
1636        ) else {
1637            return true;
1638        };
1639
1640        let mut expr_finder = FindExprBySpan::new(obligation.cause.span, self.tcx);
1641        expr_finder.visit_expr(body.value);
1642        let Some(expr) = expr_finder.result else {
1643            return true;
1644        };
1645
1646        let inner_old_self_ty = match old_self_ty.kind() {
1647            ty::Ref(_, inner_ty, _) => Some(*inner_ty),
1648            _ => None,
1649        };
1650
1651        typeck_results.expr_ty_adjusted_opt(expr).is_some_and(|expr_ty| {
1652            self.can_eq(obligation.param_env, expr_ty, old_self_ty)
1653                || inner_old_self_ty
1654                    .is_some_and(|inner_ty| self.can_eq(obligation.param_env, expr_ty, inner_ty))
1655        })
1656    }
1657
1658    pub(super) fn suggest_add_reference_to_arg(
1659        &self,
1660        obligation: &PredicateObligation<'tcx>,
1661        err: &mut Diag<'_>,
1662        poly_trait_pred: ty::PolyTraitClause<'tcx>,
1663        has_custom_message: bool,
1664    ) -> bool {
1665        let span = obligation.cause.span;
1666        let param_env = obligation.param_env;
1667
1668        let mk_result = |trait_pred_and_new_ty| {
1669            let obligation =
1670                self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
1671            self.predicate_must_hold_modulo_regions(&obligation)
1672        };
1673
1674        let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| {
1675            (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1676        });
1677        let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| {
1678            (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1679        });
1680
1681        let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1682        let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1683
1684        let mut point_at_relevant_args =
1685            |pred_ty: Ty<'tcx>, args_and_inputs: Vec<(hir::Expr<'_>, Ty<'tcx>)>| {
1686                let Some(typeck_results) = &self.typeck_results else { return false };
1687
1688                let erased_self_ty =
1689                    self.tcx.instantiate_bound_regions_with_erased(poly_trait_pred.self_ty());
1690                let mut spans = ::alloc::vec::Vec::new()vec![];
1691                for (arg, input) in args_and_inputs {
1692                    let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(&arg) else { continue };
1693                    let pred_has_arg_type = self.infcx.can_eq(param_env, arg_ty, erased_self_ty);
1694                    let arg_is_type_param = self.infcx.can_eq(param_env, pred_ty, input);
1695                    if pred_has_arg_type && arg_is_type_param {
1696                        err.span_label(
1697                            arg.span,
1698                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` doesn\'t satisfy the trait bound",
                arg_ty))
    })format!("`{arg_ty}` doesn't satisfy the trait bound"),
1699                        );
1700                        spans.push(arg.span);
1701                    }
1702                }
1703                let this = if spans.len() == 1 { "this" } else { "these" }pluralize!("this", spans.len());
1704                if !spans.is_empty() {
1705                    if imm_ref_self_ty_satisfies_pred {
1706                        err.multipart_suggestion(
1707                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider borrowing {0} argument",
                this))
    })format!("consider borrowing {this} argument"),
1708                            spans.iter().map(|sp| (sp.shrink_to_lo(), "&".into())).collect(),
1709                            Applicability::MaybeIncorrect,
1710                        );
1711                    }
1712                    if mut_ref_self_ty_satisfies_pred {
1713                        err.multipart_suggestion(
1714                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider mutably borrowing {0} argument",
                this))
    })format!("consider mutably borrowing {this} argument"),
1715                            spans.iter().map(|sp| (sp.shrink_to_lo(), "&mut ".into())).collect(),
1716                            Applicability::MaybeIncorrect,
1717                        );
1718                    }
1719                }
1720                !spans.is_empty()
1721            };
1722        let code = match obligation.cause.code() {
1723            ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code,
1724            // FIXME(compiler-errors): This is kind of a mess, but required for obligations
1725            // that come from a path expr to affect the *call* expr.
1726            c @ ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx)
1727                if self.tcx.hir_span(*hir_id).lo() == span.lo() =>
1728            {
1729                // `hir_id` corresponds to the HIR node that introduced a `where`-clause obligation.
1730                if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id) {
1731                    // If that obligation comes from a type in an associated method call, we need
1732                    // special handling here.
1733                    if let hir::ExprKind::Call(base, _) = expr.kind
1734                        && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) =
1735                            base.kind
1736                        && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id)
1737                        && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind
1738                        && ty.span == span
1739                    {
1740                        // We've encountered something like `&str::from("")`, where the intended code
1741                        // was likely `<&str>::from("")`. The former is interpreted as "call method
1742                        // `from` on `str` and borrow the result", while the latter means "call method
1743                        // `from` on `&str`".
1744
1745                        let sugg_msg = |pre: &str| {
1746                            ::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!(
1747                                "you likely meant to call the associated function `{FN}` for type \
1748                                 `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \
1749                                 type `{TY}`",
1750                                FN = segment.ident,
1751                                TY = poly_trait_pred.self_ty(),
1752                            )
1753                        };
1754                        match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl)
1755                        {
1756                            (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => {
1757                                err.multipart_suggestion(
1758                                    sugg_msg(mtbl.prefix_str()),
1759                                    ::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![
1760                                        (outer.span.shrink_to_lo(), "<".to_string()),
1761                                        (span.shrink_to_hi(), ">".to_string()),
1762                                    ],
1763                                    Applicability::MachineApplicable,
1764                                );
1765                            }
1766                            (true, _, hir::Mutability::Mut) => {
1767                                // There's an associated function found on the immutable borrow of the
1768                                err.multipart_suggestion(
1769                                    sugg_msg("mut "),
1770                                    ::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![
1771                                        (outer.span.shrink_to_lo().until(span), "<&".to_string()),
1772                                        (span.shrink_to_hi(), ">".to_string()),
1773                                    ],
1774                                    Applicability::MachineApplicable,
1775                                );
1776                            }
1777                            (_, true, hir::Mutability::Not) => {
1778                                err.multipart_suggestion(
1779                                    sugg_msg(""),
1780                                    ::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![
1781                                        (
1782                                            outer.span.shrink_to_lo().until(span),
1783                                            "<&mut ".to_string(),
1784                                        ),
1785                                        (span.shrink_to_hi(), ">".to_string()),
1786                                    ],
1787                                    Applicability::MachineApplicable,
1788                                );
1789                            }
1790                            _ => {}
1791                        }
1792                        // If we didn't return early here, we would instead suggest `&&str::from("")`.
1793                        return false;
1794                    } else if let hir::ExprKind::Call(_, args) = expr.kind {
1795                        // The `def_id` can point at a struct, which has no fn sig.
1796                        if #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(*def_id) {
    DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => true,
    _ => false,
}matches!(
1797                            self.tcx.def_kind(*def_id),
1798                            DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn)
1799                        ) && let Some(pred) = self
1800                                .tcx
1801                                .clauses_of(*def_id)
1802                                .instantiate_identity(self.tcx)
1803                                .clauses
1804                                .into_iter()
1805                                .nth(*idx)
1806                            && let Some(pred) = pred.as_trait_clause()
1807                            // This feature allows for `for<T> T: Trait`, which fails
1808                            // `instantiate_bound_regions_with_erased`. Avoid suggesting for now.
1809                            && !self.tcx.features().non_lifetime_binders()
1810                        {
1811                            let pred_ty = self.tcx.instantiate_bound_regions_with_erased(
1812                                pred.self_ty().skip_norm_wip(),
1813                            );
1814                            let fn_sig = self.tcx.instantiate_bound_regions_with_erased(
1815                                self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(),
1816                            );
1817                            if point_at_relevant_args(
1818                                pred_ty,
1819                                args.into_iter()
1820                                    .zip(fn_sig.inputs())
1821                                    .map(|(e, t)| (*e, *t))
1822                                    .collect(),
1823                            ) {
1824                                return false;
1825                            }
1826                        }
1827                    }
1828                }
1829                c
1830            }
1831            c @ ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx)
1832                if let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
1833                    && let hir::ExprKind::MethodCall(_segment, rcvr, args, ..) = expr.kind
1834                    // The `def_id` can also point at the impl, which has no fn sig.
1835                    && #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(*def_id) {
    DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => true,
    _ => false,
}matches!(
1836                        self.tcx.def_kind(*def_id),
1837                        DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn)
1838                    )
1839                    && let Some(pred) = self
1840                        .tcx
1841                        .clauses_of(*def_id)
1842                        .instantiate_identity(self.tcx)
1843                        .clauses
1844                        .into_iter()
1845                        .nth(*idx)
1846                    && let Some(pred) = pred.as_trait_clause()
1847                    // This feature allows for `for<T> T: Trait`, which fails
1848                    // `instantiate_bound_regions_with_erased`. Avoid suggesting for now.
1849                    && !self.tcx.features().non_lifetime_binders() =>
1850            {
1851                let fn_sig = self.tcx.instantiate_bound_regions_with_erased(
1852                    self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(),
1853                );
1854                // We've got a method call where likely one of the arguments didn't meet a bound.
1855                let pred_ty =
1856                    self.tcx.instantiate_bound_regions_with_erased(pred.self_ty().skip_norm_wip());
1857                if point_at_relevant_args(
1858                    pred_ty,
1859                    [rcvr]
1860                        .into_iter()
1861                        .chain(args.into_iter())
1862                        .zip(fn_sig.inputs())
1863                        .map(|(e, t)| (*e, *t))
1864                        .collect(),
1865                ) {
1866                    return false;
1867                }
1868                c
1869            }
1870            c if #[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
    _ => false,
}matches!(
1871                span.ctxt().outer_expn_data().kind,
1872                ExpnKind::Desugaring(DesugaringKind::ForLoop)
1873            ) =>
1874            {
1875                c
1876            }
1877            _ => return false,
1878        };
1879
1880        // List of traits for which it would be nonsensical to suggest borrowing.
1881        // For instance, immutable references are always Copy, so suggesting to
1882        // borrow would always succeed, but it's probably not what the user wanted.
1883        let mut never_suggest_borrow: Vec<_> =
1884            [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
1885                .iter()
1886                .filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
1887                .collect();
1888
1889        if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
1890            never_suggest_borrow.push(def_id);
1891        }
1892
1893        // Try to apply the original trait bound by borrowing.
1894        let mut try_borrowing = |old_pred: ty::PolyTraitClause<'tcx>,
1895                                 blacklist: &[DefId]|
1896         -> bool {
1897            if blacklist.contains(&old_pred.def_id()) {
1898                return false;
1899            }
1900            // We map bounds to `&T` and `&mut T`
1901            let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
1902                (
1903                    trait_pred,
1904                    Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1905                )
1906            });
1907            let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
1908                (
1909                    trait_pred,
1910                    Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1911                )
1912            });
1913
1914            let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1915            let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1916
1917            let (ref_inner_ty_satisfies_pred, ref_inner_ty_is_mut) =
1918                if let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
1919                    && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
1920                {
1921                    (
1922                        mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
1923                        mutability.is_mut(),
1924                    )
1925                } else {
1926                    (false, false)
1927                };
1928
1929            let is_immut = imm_ref_self_ty_satisfies_pred
1930                || (ref_inner_ty_satisfies_pred && !ref_inner_ty_is_mut);
1931            let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_is_mut;
1932            if !is_immut && !is_mut {
1933                return false;
1934            }
1935            let Ok(_snippet) = self.tcx.sess.source_map().span_to_snippet(span) else {
1936                return false;
1937            };
1938            // We don't want a borrowing suggestion on the fields in structs
1939            // ```
1940            // #[derive(Clone)]
1941            // struct Foo {
1942            //     the_foos: Vec<Foo>
1943            // }
1944            // ```
1945            if !#[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
    _ => false,
}matches!(
1946                span.ctxt().outer_expn_data().kind,
1947                ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
1948            ) {
1949                return false;
1950            }
1951            // We have a very specific type of error, where just borrowing this argument
1952            // might solve the problem. In cases like this, the important part is the
1953            // original type obligation, not the last one that failed, which is arbitrary.
1954            // Because of this, we modify the error to refer to the original obligation and
1955            // return early in the caller.
1956
1957            let mut label = || {
1958                // Special case `Sized` as `old_pred` will be the trait itself instead of
1959                // `Sized` when the trait bound is the source of the error.
1960                let is_sized = match obligation.predicate.kind().skip_binder() {
1961                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
1962                        self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
1963                    }
1964                    _ => false,
1965                };
1966
1967                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!(
1968                    "the trait bound `{}` is not satisfied",
1969                    self.tcx.short_string(old_pred, err.long_ty_path()),
1970                );
1971                let self_ty_str = self.tcx.short_string(old_pred.self_ty(), err.long_ty_path());
1972                let trait_path = self
1973                    .tcx
1974                    .short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
1975
1976                if has_custom_message {
1977                    let msg = if is_sized {
1978                        "the trait bound `Sized` is not satisfied".into()
1979                    } else {
1980                        msg
1981                    };
1982                    err.note(msg);
1983                } else {
1984                    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)];
1985                }
1986                if is_sized {
1987                    err.span_label(
1988                        span,
1989                        ::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}`"),
1990                    );
1991                } else {
1992                    err.span_label(
1993                        span,
1994                        ::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}`"),
1995                    );
1996                }
1997            };
1998
1999            let mut sugg_prefixes = ::alloc::vec::Vec::new()vec![];
2000            if is_immut {
2001                sugg_prefixes.push("&");
2002            }
2003            if is_mut {
2004                sugg_prefixes.push("&mut ");
2005            }
2006            let sugg_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider{0} borrowing here",
                if is_mut && !is_immut { " mutably" } else { "" }))
    })format!(
2007                "consider{} borrowing here",
2008                if is_mut && !is_immut { " mutably" } else { "" },
2009            );
2010
2011            // Issue #104961, we need to add parentheses properly for compound expressions
2012            // for example, `x.starts_with("hi".to_string() + "you")`
2013            // should be `x.starts_with(&("hi".to_string() + "you"))`
2014            let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) else {
2015                return false;
2016            };
2017            let mut expr_finder = FindExprBySpan::new(span, self.tcx);
2018            expr_finder.visit_expr(body.value);
2019
2020            if let Some(ty) = expr_finder.ty_result {
2021                if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(ty.hir_id)
2022                    && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, _)) = expr.kind
2023                    && ty.span == span
2024                {
2025                    // We've encountered something like `str::from("")`, where the intended code
2026                    // was likely `<&str>::from("")`. #143393.
2027                    label();
2028                    err.multipart_suggestions(
2029                        sugg_msg,
2030                        sugg_prefixes.into_iter().map(|sugg_prefix| {
2031                            ::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![
2032                                (span.shrink_to_lo(), format!("<{sugg_prefix}")),
2033                                (span.shrink_to_hi(), ">".to_string()),
2034                            ]
2035                        }),
2036                        Applicability::MaybeIncorrect,
2037                    );
2038                    return true;
2039                }
2040                return false;
2041            }
2042            let Some(expr) = expr_finder.result else {
2043                return false;
2044            };
2045            if let hir::ExprKind::AddrOf(_, _, _) = expr.kind {
2046                return false;
2047            }
2048            let old_self_ty = old_pred.skip_binder().self_ty();
2049            if !old_self_ty.has_escaping_bound_vars()
2050                && !self.where_clause_expr_matches_failed_self_ty(
2051                    obligation,
2052                    self.tcx.instantiate_bound_regions_with_erased(old_pred.self_ty()),
2053                )
2054            {
2055                return false;
2056            }
2057            let needs_parens_post = expr_needs_parens(expr);
2058            let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) {
2059                Node::Expr(e)
2060                    if let hir::ExprKind::MethodCall(_, base, _, _) = e.kind
2061                        && base.hir_id == expr.hir_id =>
2062                {
2063                    true
2064                }
2065                _ => false,
2066            };
2067
2068            label();
2069            let suggestions = sugg_prefixes.into_iter().map(|sugg_prefix| {
2070                match (needs_parens_pre, needs_parens_post) {
2071                    (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())],
2072                    // We have something like `foo.bar()`, where we want to bororw foo, so we need
2073                    // to suggest `(&mut foo).bar()`.
2074                    (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![
2075                        (span.shrink_to_lo(), format!("{sugg_prefix}(")),
2076                        (span.shrink_to_hi(), ")".to_string()),
2077                    ],
2078                    // Issue #109436, we need to add parentheses properly for method calls
2079                    // for example, `foo.into()` should be `(&foo).into()`
2080                    (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![
2081                        (span.shrink_to_lo(), format!("({sugg_prefix}")),
2082                        (span.shrink_to_hi(), ")".to_string()),
2083                    ],
2084                    (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![
2085                        (span.shrink_to_lo(), format!("({sugg_prefix}(")),
2086                        (span.shrink_to_hi(), "))".to_string()),
2087                    ],
2088                }
2089            });
2090            err.multipart_suggestions(sugg_msg, suggestions, Applicability::MaybeIncorrect);
2091            return true;
2092        };
2093
2094        if let ObligationCauseCode::ImplDerived(cause) = &*code {
2095            try_borrowing(cause.derived.parent_trait_pred, &[])
2096        } else if let ObligationCauseCode::WhereClause(..)
2097        | ObligationCauseCode::WhereClauseInExpr(..) = code
2098        {
2099            try_borrowing(poly_trait_pred, &never_suggest_borrow)
2100        } else {
2101            false
2102        }
2103    }
2104
2105    // Suggest borrowing the type
2106    pub(super) fn suggest_borrowing_for_object_cast(
2107        &self,
2108        err: &mut Diag<'_>,
2109        obligation: &PredicateObligation<'tcx>,
2110        self_ty: Ty<'tcx>,
2111        target_ty: Ty<'tcx>,
2112    ) {
2113        let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
2114            return;
2115        };
2116        let ty::Dynamic(predicates, _) = object_ty.kind() else {
2117            return;
2118        };
2119        let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
2120
2121        for predicate in predicates.iter() {
2122            if !self.predicate_must_hold_modulo_regions(
2123                &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
2124            ) {
2125                return;
2126            }
2127        }
2128
2129        err.span_suggestion_verbose(
2130            obligation.cause.span.shrink_to_lo(),
2131            ::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!(
2132                "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
2133            ),
2134            "&",
2135            Applicability::MaybeIncorrect,
2136        );
2137    }
2138
2139    /// Peel `&`-borrows from an expression, following through untyped let-bindings.
2140    /// Returns a list of removable `&` layers (each with the span to remove and the
2141    /// resulting type), plus an optional terminal [`hir::Param`] when the chain ends
2142    /// at a function parameter (including async-fn desugared parameters).
2143    fn peel_expr_refs(
2144        &self,
2145        mut expr: &'tcx hir::Expr<'tcx>,
2146        mut ty: Ty<'tcx>,
2147    ) -> (Vec<PeeledRef<'tcx>>, Option<&'tcx hir::Param<'tcx>>) {
2148        let mut refs = Vec::new();
2149        'outer: loop {
2150            while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
2151                let span =
2152                    if let Some(borrowed_span) = borrowed.span.find_ancestor_inside(expr.span) {
2153                        expr.span.until(borrowed_span)
2154                    } else {
2155                        break 'outer;
2156                    };
2157
2158                // Double check that the span actually corresponds to a borrow,
2159                // rather than some macro garbage.
2160                // The span may include leading parens from parenthesized expressions
2161                // (e.g., `(&expr)` where HIR removes the Paren but keeps the span).
2162                // In that case, trim the span to start at the `&`.
2163                let span = match self.tcx.sess.source_map().span_to_snippet(span) {
2164                    Ok(ref snippet) if snippet.starts_with("&") => span,
2165                    Ok(ref snippet) if let Some(amp) = snippet.find('&') => {
2166                        span.with_lo(span.lo() + BytePos(amp as u32))
2167                    }
2168                    _ => break 'outer,
2169                };
2170
2171                let ty::Ref(_, inner_ty, _) = ty.kind() else {
2172                    break 'outer;
2173                };
2174                ty = *inner_ty;
2175                refs.push(PeeledRef { span, peeled_ty: ty });
2176                expr = borrowed;
2177            }
2178            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
2179                && let Res::Local(hir_id) = path.res
2180                && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id)
2181            {
2182                match self.tcx.parent_hir_node(binding.hir_id) {
2183                    // Untyped let-binding: follow to its initializer.
2184                    hir::Node::LetStmt(local)
2185                        if local.ty.is_none()
2186                            && let Some(init) = local.init =>
2187                    {
2188                        expr = init;
2189                        continue;
2190                    }
2191                    // Async fn desugared parameter: `let x = __arg0;` with AsyncFn source.
2192                    // Follow to the original parameter.
2193                    hir::Node::LetStmt(local)
2194                        if #[allow(non_exhaustive_omitted_patterns)] match local.source {
    hir::LocalSource::AsyncFn => true,
    _ => false,
}matches!(local.source, hir::LocalSource::AsyncFn)
2195                            && let Some(init) = local.init
2196                            && let hir::ExprKind::Path(hir::QPath::Resolved(None, arg_path)) =
2197                                init.kind
2198                            && let Res::Local(arg_hir_id) = arg_path.res
2199                            && let hir::Node::Pat(arg_binding) = self.tcx.hir_node(arg_hir_id)
2200                            && let hir::Node::Param(param) =
2201                                self.tcx.parent_hir_node(arg_binding.hir_id) =>
2202                    {
2203                        return (refs, Some(param));
2204                    }
2205                    // Direct parameter reference.
2206                    hir::Node::Param(param) => {
2207                        return (refs, Some(param));
2208                    }
2209                    _ => break 'outer,
2210                }
2211            } else {
2212                break 'outer;
2213            }
2214        }
2215        (refs, None)
2216    }
2217
2218    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
2219    /// suggest removing these references until we reach a type that implements the trait.
2220    pub(super) fn suggest_remove_reference(
2221        &self,
2222        obligation: &PredicateObligation<'tcx>,
2223        err: &mut Diag<'_>,
2224        trait_pred: ty::PolyTraitClause<'tcx>,
2225    ) -> bool {
2226        let mut span = obligation.cause.span;
2227        let mut trait_pred = trait_pred;
2228        let mut code = obligation.cause.code();
2229        while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
2230            // We want the root obligation, in order to detect properly handle
2231            // `for _ in &mut &mut vec![] {}`.
2232            code = c;
2233            trait_pred = parent_trait_pred;
2234        }
2235        while span.desugaring_kind().is_some() {
2236            // Remove all the hir desugaring contexts while maintaining the macro contexts.
2237            span.remove_mark();
2238        }
2239        let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
2240        let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) else {
2241            return false;
2242        };
2243        expr_finder.visit_expr(body.value);
2244        let mut maybe_suggest = |suggested_ty, count, suggestions| {
2245            // Remapping bound vars here
2246            let trait_pred_and_suggested_ty =
2247                trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
2248
2249            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
2250                obligation.param_env,
2251                trait_pred_and_suggested_ty,
2252            );
2253
2254            if self.predicate_may_hold(&new_obligation) {
2255                let msg = if count == 1 {
2256                    "consider removing the leading `&`-reference".to_string()
2257                } else {
2258                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider removing {0} leading `&`-references",
                count))
    })format!("consider removing {count} leading `&`-references")
2259                };
2260
2261                err.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable);
2262                true
2263            } else {
2264                false
2265            }
2266        };
2267
2268        // Maybe suggest removal of borrows from types in type parameters, like in
2269        // `src/test/ui/not-panic/not-panic-safe.rs`.
2270        let mut count = 0;
2271        let mut suggestions = ::alloc::vec::Vec::new()vec![];
2272        // Skipping binder here, remapping below
2273        let mut suggested_ty = trait_pred.self_ty().skip_binder();
2274        if let Some(mut hir_ty) = expr_finder.ty_result {
2275            while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
2276                count += 1;
2277                let span = hir_ty.span.until(mut_ty.ty.span);
2278                suggestions.push((span, String::new()));
2279
2280                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
2281                    break;
2282                };
2283                suggested_ty = *inner_ty;
2284
2285                hir_ty = mut_ty.ty;
2286
2287                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
2288                    return true;
2289                }
2290            }
2291        }
2292
2293        // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
2294        let Some(expr) = expr_finder.result else {
2295            return false;
2296        };
2297        // Skipping binder here, remapping below
2298        let suggested_ty = trait_pred.self_ty().skip_binder();
2299        let (peeled_refs, _) = self.peel_expr_refs(expr, suggested_ty);
2300        for (i, peeled) in peeled_refs.iter().enumerate() {
2301            let suggestions: Vec<_> =
2302                peeled_refs[..=i].iter().map(|r| (r.span, String::new())).collect();
2303            if maybe_suggest(peeled.peeled_ty, i + 1, suggestions) {
2304                return true;
2305            }
2306        }
2307        false
2308    }
2309
2310    /// Suggest removing `&` from a function parameter type like `&impl Future`.
2311    fn suggest_remove_ref_from_param(&self, param: &hir::Param<'_>, err: &mut Diag<'_>) -> bool {
2312        if let Some(decl) = self.tcx.parent_hir_node(param.hir_id).fn_decl()
2313            && let Some(input_ty) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
2314            && let hir::TyKind::Ref(_, mut_ty) = input_ty.kind
2315        {
2316            let ref_span = input_ty.span.until(mut_ty.ty.span);
2317            match self.tcx.sess.source_map().span_to_snippet(ref_span) {
2318                Ok(snippet) if snippet.starts_with("&") => {
2319                    err.span_suggestion_verbose(
2320                        ref_span,
2321                        "consider removing the `&` from the parameter type",
2322                        "",
2323                        Applicability::MaybeIncorrect,
2324                    );
2325                    return true;
2326                }
2327                _ => {}
2328            }
2329        }
2330        false
2331    }
2332
2333    pub(super) fn suggest_remove_await(
2334        &self,
2335        obligation: &PredicateObligation<'tcx>,
2336        err: &mut Diag<'_>,
2337    ) {
2338        if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives()
2339            && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
2340        {
2341            // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
2342            // and if not maybe suggest doing something else? If we kept the expression around we
2343            // could also check if it is an fn call (very likely) and suggest changing *that*, if
2344            // it is from the local crate.
2345
2346            // If the type is `&..&T` where `T: Future`, suggest removing `&`
2347            // instead of removing `.await`.
2348            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
2349                obligation.predicate.kind().skip_binder()
2350            {
2351                let self_ty = pred.self_ty();
2352                let future_trait =
2353                    self.tcx.require_lang_item(LangItem::Future, obligation.cause.span);
2354
2355                // Peel through references to check if there's a Future underneath.
2356                let has_future = {
2357                    let mut ty = self_ty;
2358                    loop {
2359                        match *ty.kind() {
2360                            ty::Ref(_, inner_ty, _)
2361                                if !#[allow(non_exhaustive_omitted_patterns)] match inner_ty.kind() {
    ty::Dynamic(..) => true,
    _ => false,
}matches!(inner_ty.kind(), ty::Dynamic(..)) =>
2362                            {
2363                                if self
2364                                    .type_implements_trait(
2365                                        future_trait,
2366                                        [inner_ty],
2367                                        obligation.param_env,
2368                                    )
2369                                    .must_apply_modulo_regions()
2370                                {
2371                                    break true;
2372                                }
2373                                ty = inner_ty;
2374                            }
2375                            _ => break false,
2376                        }
2377                    }
2378                };
2379
2380                if has_future {
2381                    let (peeled_refs, terminal_param) = self.peel_expr_refs(expr, self_ty);
2382
2383                    // Try removing `&`s from the expression.
2384                    for (i, peeled) in peeled_refs.iter().enumerate() {
2385                        if self
2386                            .type_implements_trait(
2387                                future_trait,
2388                                [peeled.peeled_ty],
2389                                obligation.param_env,
2390                            )
2391                            .must_apply_modulo_regions()
2392                        {
2393                            let count = i + 1;
2394                            let msg = if count == 1 {
2395                                "consider removing the leading `&`-reference".to_string()
2396                            } else {
2397                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider removing {0} leading `&`-references",
                count))
    })format!("consider removing {count} leading `&`-references")
2398                            };
2399                            let suggestions: Vec<_> =
2400                                peeled_refs[..=i].iter().map(|r| (r.span, String::new())).collect();
2401                            err.multipart_suggestion(
2402                                msg,
2403                                suggestions,
2404                                Applicability::MachineApplicable,
2405                            );
2406                            return;
2407                        }
2408                    }
2409
2410                    // Try removing `&` from the parameter type, but only when there's
2411                    // no `&` in the expression itself (otherwise removing from the param
2412                    // alone wouldn't fix the error).
2413                    if peeled_refs.is_empty()
2414                        && let Some(param) = terminal_param
2415                        && self.suggest_remove_ref_from_param(param, err)
2416                    {
2417                        return;
2418                    }
2419
2420                    // Fallback: emit a help message when we can't provide a specific span.
2421                    err.help(
2422                        "a reference to a future is not a future; \
2423                     consider removing the leading `&`-reference",
2424                    );
2425                    return;
2426                }
2427            }
2428
2429            // use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
2430            if let Some((_, hir::Node::Expr(await_expr))) = self.tcx.hir_parent_iter(*hir_id).nth(1)
2431                && let Some(expr_span) = expr.span.find_ancestor_inside_same_ctxt(await_expr.span)
2432            {
2433                let removal_span = self
2434                    .tcx
2435                    .sess
2436                    .source_map()
2437                    .span_extend_while_whitespace(expr_span)
2438                    .shrink_to_hi()
2439                    .to(await_expr.span.shrink_to_hi());
2440                err.span_suggestion_verbose(
2441                    removal_span,
2442                    "remove the `.await`",
2443                    "",
2444                    Applicability::MachineApplicable,
2445                );
2446            } else {
2447                err.span_label(obligation.cause.span, "remove the `.await`");
2448            }
2449            // FIXME: account for associated `async fn`s.
2450            if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
2451                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
2452                    obligation.predicate.kind().skip_binder()
2453                {
2454                    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()));
2455                }
2456                if let Some(typeck_results) = &self.typeck_results
2457                    && let ty = typeck_results.expr_ty_adjusted(base)
2458                    && let ty::FnDef(def_id, _args) = ty.kind()
2459                    && let Some(hir::Node::Item(item)) = self.tcx.hir_get_if_local(*def_id)
2460                {
2461                    let (ident, _, _, _) = item.expect_fn();
2462                    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");
2463                    if item.vis_span.is_empty() {
2464                        err.span_suggestion_verbose(
2465                            item.span.shrink_to_lo(),
2466                            msg,
2467                            "async ",
2468                            Applicability::MaybeIncorrect,
2469                        );
2470                    } else {
2471                        err.span_suggestion_verbose(
2472                            item.vis_span.shrink_to_hi(),
2473                            msg,
2474                            " async",
2475                            Applicability::MaybeIncorrect,
2476                        );
2477                    }
2478                }
2479            }
2480        }
2481    }
2482
2483    /// Check if the trait bound is implemented for a different mutability and note it in the
2484    /// final error.
2485    pub(super) fn suggest_change_mut(
2486        &self,
2487        obligation: &PredicateObligation<'tcx>,
2488        err: &mut Diag<'_>,
2489        trait_pred: ty::PolyTraitClause<'tcx>,
2490    ) {
2491        let points_at_arg =
2492            #[allow(non_exhaustive_omitted_patterns)] match obligation.cause.code() {
    ObligationCauseCode::FunctionArg { .. } => true,
    _ => false,
}matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. },);
2493
2494        let span = obligation.cause.span;
2495        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
2496            let refs_number =
2497                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
2498            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
2499                // Do not suggest removal of borrow from type arguments.
2500                return;
2501            }
2502            let trait_pred = self.deeply_resolve_ignoring_regions(trait_pred);
2503            if trait_pred.has_non_region_infer() {
2504                // Do not ICE while trying to find if a reborrow would succeed on a trait with
2505                // unresolved bindings.
2506                return;
2507            }
2508
2509            // Skipping binder here, remapping below
2510            if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind()
2511            {
2512                let suggested_ty = match mutability {
2513                    hir::Mutability::Mut => Ty::new_imm_ref(self.tcx, region, t_type),
2514                    hir::Mutability::Not => Ty::new_mut_ref(self.tcx, region, t_type),
2515                };
2516
2517                // Remapping bound vars here
2518                let trait_pred_and_suggested_ty =
2519                    trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
2520
2521                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
2522                    obligation.param_env,
2523                    trait_pred_and_suggested_ty,
2524                );
2525                let suggested_ty_would_satisfy_obligation = self
2526                    .evaluate_obligation_no_overflow(&new_obligation)
2527                    .must_apply_modulo_regions();
2528                if suggested_ty_would_satisfy_obligation {
2529                    let sp = self
2530                        .tcx
2531                        .sess
2532                        .source_map()
2533                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
2534                    if points_at_arg
2535                        && mutability.is_not()
2536                        && refs_number > 0
2537                        // The borrow can sit in a macro body, where rewriting it would edit the
2538                        // macro definition and so every one of its call sites, or a crate the user
2539                        // does not own. Fall through to the note in that case.
2540                        && span.can_be_used_for_suggestions()
2541                    {
2542                        // If we have a call like foo(&mut buf), then don't suggest foo(&mut mut buf)
2543                        if snippet
2544                            .trim_start_matches(|c: char| c.is_whitespace() || c == '&')
2545                            .starts_with("mut")
2546                        {
2547                            return;
2548                        }
2549                        err.span_suggestion_verbose(
2550                            sp,
2551                            "consider changing this borrow's mutability",
2552                            "&mut ",
2553                            Applicability::MachineApplicable,
2554                        );
2555                    } else {
2556                        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!(
2557                            "`{}` is implemented for `{}`, but not for `{}`",
2558                            trait_pred.print_modifiers_and_trait_path(),
2559                            suggested_ty,
2560                            trait_pred.skip_binder().self_ty(),
2561                        ));
2562                    }
2563                }
2564            }
2565        }
2566    }
2567
2568    pub(super) fn suggest_semicolon_removal(
2569        &self,
2570        obligation: &PredicateObligation<'tcx>,
2571        err: &mut Diag<'_>,
2572        span: Span,
2573        trait_pred: ty::PolyTraitClause<'tcx>,
2574    ) -> bool {
2575        if !trait_pred.self_ty().skip_binder().is_unit() {
2576            return false;
2577        }
2578        let node = self.tcx.hir_node_by_def_id(obligation.cause.body_def_id);
2579        if let hir::Node::Item(hir::Item {
2580            kind: hir::ItemKind::Fn { sig, body: body_id, .. }, ..
2581        }) = node
2582            && let hir::ExprKind::Block(blk, _) = &self.tcx.hir_body(*body_id).value.kind
2583            && sig.decl.output.span().overlaps(span)
2584            && let Some(candidate) = self.removable_trailing_semicolon(blk, obligation, trait_pred)
2585        {
2586            // A function body has a single return type, so keeping the value can't break any
2587            // other use of it.
2588            self.emit_semicolon_removal_suggestion(
2589                err,
2590                trait_pred,
2591                candidate,
2592                Applicability::MachineApplicable,
2593            );
2594            return true;
2595        }
2596        self.suggest_semicolon_removal_in_closure_arg(obligation, err, trait_pred)
2597    }
2598
2599    /// If the value of `block` is discarded by a trailing semicolon and keeping it would satisfy
2600    /// `trait_pred`, return that statement, its expression and the type of that expression.
2601    fn removable_trailing_semicolon(
2602        &self,
2603        block: &hir::Block<'tcx>,
2604        obligation: &PredicateObligation<'tcx>,
2605        trait_pred: ty::PolyTraitClause<'tcx>,
2606    ) -> Option<(&'tcx hir::Stmt<'tcx>, &'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
2607        if block.expr.is_none()
2608            && let Some(stmt) = block.stmts.last()
2609            && let hir::StmtKind::Semi(expr) = stmt.kind
2610            && !stmt.span.from_expansion()
2611            && !#[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    hir::ExprKind::Err(_) => true,
    _ => false,
}matches!(expr.kind, hir::ExprKind::Err(_))
2612            // Only suggest this if the expression behind the semicolon implements the predicate
2613            && let Some(typeck_results) = &self.typeck_results
2614            && let Some(ty) =
2615                typeck_results.expr_ty_opt(expr).map(|ty| self.deeply_resolve_ignoring_regions(ty))
2616            && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(
2617                obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty))
2618            ))
2619        {
2620            Some((stmt, expr, ty))
2621        } else {
2622            None
2623        }
2624    }
2625
2626    fn emit_semicolon_removal_suggestion(
2627        &self,
2628        err: &mut Diag<'_>,
2629        trait_pred: ty::PolyTraitClause<'tcx>,
2630        (stmt, expr, ty): (&hir::Stmt<'_>, &hir::Expr<'_>, Ty<'tcx>),
2631        applicability: Applicability,
2632    ) {
2633        err.span_label(
2634            expr.span,
2635            ::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!(
2636                "this expression has type `{}`, which implements `{}`",
2637                ty,
2638                trait_pred.print_modifiers_and_trait_path()
2639            ),
2640        );
2641        err.span_suggestion(
2642            self.tcx.sess.source_map().end_point(stmt.span),
2643            "remove this semicolon",
2644            "",
2645            applicability,
2646        );
2647    }
2648
2649    /// Detect when a closure argument returns `()` because of a trailing semicolon and that makes
2650    /// a trait bound on the function's generic param fail, and suggest removing the semicolon:
2651    ///
2652    /// ```text
2653    /// fn bar<R: Bar>(_: impl Fn() -> R) {}
2654    /// bar(|| { 5u8; })
2655    /// //          - help: remove this semicolon
2656    /// ```
2657    fn suggest_semicolon_removal_in_closure_arg(
2658        &self,
2659        obligation: &PredicateObligation<'tcx>,
2660        err: &mut Diag<'_>,
2661        trait_pred: ty::PolyTraitClause<'tcx>,
2662    ) -> bool {
2663        let &ObligationCauseCode::WhereClauseInExpr(callee_def_id, _, hir_id, idx) =
2664            obligation.cause.code().peel_derives()
2665        else {
2666            return false;
2667        };
2668        // This cause code is used for the clauses of any item named in an expression, like an
2669        // associated const or a type alias, and `fn_sig` is only defined for functions.
2670        if !#[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(callee_def_id)
    {
    DefKind::Fn | DefKind::AssocFn => true,
    _ => false,
}matches!(self.tcx.def_kind(callee_def_id), DefKind::Fn | DefKind::AssocFn) {
2671            return false;
2672        }
2673        let hir::Node::Expr(expr) = self.tcx.hir_node(hir_id) else {
2674            return false;
2675        };
2676        let Some(typeck_results) = &self.typeck_results else {
2677            return false;
2678        };
2679        let args: Vec<&hir::Expr<'_>> =
2680            match expr.kind {
2681                hir::ExprKind::MethodCall(_, receiver, args, _) => {
2682                    iter::once(receiver).chain(args).collect()
2683                }
2684                // For a call like `bar(..)` the obligation is attached to the callee path expression,
2685                // so the arguments live in its parent.
2686                _ => match self.tcx.parent_hir_node(expr.hir_id) {
2687                    hir::Node::Expr(hir::Expr {
2688                        kind: hir::ExprKind::Call(callee, args), ..
2689                    }) if callee.hir_id == expr.hir_id => args.iter().collect(),
2690                    _ => return false,
2691                },
2692            };
2693        // Work with the callee's own clauses and signature, where the failing bound is still
2694        // written in terms of the generic param it was declared on.
2695        let clauses = self.tcx.clauses_of(callee_def_id).instantiate_identity(self.tcx);
2696        let Some(ty::ClauseKind::Trait(failed)) = clauses
2697            .clauses
2698            .get(idx)
2699            .map(|clause| clause.as_ref().skip_norm_wip().kind().skip_binder())
2700        else {
2701            return false;
2702        };
2703        let sig =
2704            self.tcx.fn_sig(callee_def_id).instantiate_identity().skip_norm_wip().skip_binder();
2705        let mut candidates = args.into_iter().enumerate().filter_map(|(i, arg)| {
2706            // The bound has to be on what the closure returns. A bound on an unrelated param that
2707            // also happened to be inferred as `()` would not be satisfied by removing a semicolon.
2708            let declared = sig.inputs().get(i)?.peel_refs();
2709            if !clauses.clauses.iter().any(|clause| {
2710                #[allow(non_exhaustive_omitted_patterns)] match clause.as_ref().skip_norm_wip().kind().skip_binder()
    {
    ty::ClauseKind::Projection(proj) if
        self.tcx.is_lang_item(proj.def_id(), LangItem::FnOnceOutput) &&
                proj.projection_term.self_ty() == declared &&
            proj.term.as_type() == Some(failed.self_ty()) => true,
    _ => false,
}matches!(
2711                    clause.as_ref().skip_norm_wip().kind().skip_binder(),
2712                    ty::ClauseKind::Projection(proj)
2713                        if self.tcx.is_lang_item(proj.def_id(), LangItem::FnOnceOutput)
2714                            && proj.projection_term.self_ty() == declared
2715                            && proj.term.as_type() == Some(failed.self_ty())
2716                )
2717            }) {
2718                return None;
2719            }
2720            // The error can be reported while the closure argument is still being checked, before
2721            // its own type is recorded, so identify closures syntactically and only fall back to
2722            // the argument's type (e.g. for a closure bound to a variable and passed by path).
2723            let closure_def_id = match arg.kind {
2724                hir::ExprKind::Closure(closure) => closure.def_id,
2725                _ => match typeck_results
2726                    .expr_ty_adjusted_opt(arg)
2727                    .map(|ty| *self.deeply_resolve_ignoring_regions(ty).peel_refs().kind())
2728                {
2729                    Some(ty::Closure(def_id, _)) => def_id.as_local()?,
2730                    _ => return None,
2731                },
2732            };
2733            let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
2734                self.tcx.hir_node_by_def_id(closure_def_id)
2735            else {
2736                return None;
2737            };
2738            let hir::ExprKind::Block(block, None) = self.tcx.hir_body(closure.body).value.kind
2739            else {
2740                return None;
2741            };
2742            self.removable_trailing_semicolon(block, obligation, trait_pred)
2743        });
2744        // Only emit the suggestion when a single closure argument matches, to avoid pointing at
2745        // an unrelated closure.
2746        if let Some(candidate) = candidates.next()
2747            && candidates.next().is_none()
2748        {
2749            // The same closure can be passed to somewhere else that expects it to return `()`,
2750            // where keeping the value would introduce a new error.
2751            self.emit_semicolon_removal_suggestion(
2752                err,
2753                trait_pred,
2754                candidate,
2755                Applicability::MaybeIncorrect,
2756            );
2757            return true;
2758        }
2759        false
2760    }
2761
2762    pub(super) fn suggest_borrow_for_unsized_closure_return(
2763        &self,
2764        body_def_id: LocalDefId,
2765        err: &mut Diag<'_>,
2766        predicate: ty::Predicate<'tcx>,
2767    ) {
2768        let Some(pred) = predicate.as_trait_clause() else {
2769            return;
2770        };
2771        if !self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
2772            return;
2773        }
2774
2775        let Some(span) = err.span.primary_span() else {
2776            return;
2777        };
2778        let Some(body_id) = self.tcx.hir_node_by_def_id(body_def_id).body_id() else {
2779            return;
2780        };
2781        let body = self.tcx.hir_body(body_id);
2782        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
2783        expr_finder.visit_expr(body.value);
2784        let Some(expr) = expr_finder.result else {
2785            return;
2786        };
2787
2788        let closure = match expr.kind {
2789            hir::ExprKind::Call(_, args) => args.iter().find_map(|arg| match arg.kind {
2790                hir::ExprKind::Closure(closure) => Some(closure),
2791                _ => None,
2792            }),
2793            hir::ExprKind::MethodCall(_, _, args, _) => {
2794                args.iter().find_map(|arg| match arg.kind {
2795                    hir::ExprKind::Closure(closure) => Some(closure),
2796                    _ => None,
2797                })
2798            }
2799            _ => None,
2800        };
2801        let Some(closure) = closure else {
2802            return;
2803        };
2804        if !#[allow(non_exhaustive_omitted_patterns)] match closure.fn_decl.output {
    hir::FnRetTy::DefaultReturn(_) => true,
    _ => false,
}matches!(closure.fn_decl.output, hir::FnRetTy::DefaultReturn(_)) {
2805            return;
2806        }
2807
2808        err.span_suggestion_verbose(
2809            self.tcx.hir_body(closure.body).value.span.shrink_to_lo(),
2810            "consider borrowing the value",
2811            "&",
2812            Applicability::MaybeIncorrect,
2813        );
2814    }
2815
2816    pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
2817        let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig, .. }, .. }) =
2818            self.tcx.hir_node_by_def_id(obligation.cause.body_def_id)
2819        else {
2820            return None;
2821        };
2822
2823        if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
2824    }
2825
2826    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
2827    /// applicable and signal that the error has been expanded appropriately and needs to be
2828    /// emitted.
2829    pub(super) fn suggest_impl_trait(
2830        &self,
2831        err: &mut Diag<'_>,
2832        obligation: &PredicateObligation<'tcx>,
2833        trait_pred: ty::PolyTraitClause<'tcx>,
2834    ) -> bool {
2835        let ObligationCauseCode::SizedReturnType = obligation.cause.code() else {
2836            return false;
2837        };
2838        let ty::Dynamic(_, _) = trait_pred.self_ty().skip_binder().kind() else {
2839            return false;
2840        };
2841        if let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
2842        | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
2843        | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(fn_sig, _), .. }) =
2844            self.tcx.hir_node_by_def_id(obligation.cause.body_def_id)
2845            && let hir::FnRetTy::Return(ty) = fn_sig.decl.output
2846            && let hir::TyKind::Path(qpath) = ty.kind
2847            && let hir::QPath::Resolved(None, path) = qpath
2848            && let Res::Def(DefKind::TyAlias, def_id) = path.res
2849        {
2850            // Do not suggest
2851            // type T = dyn Trait;
2852            // fn foo() -> impl T { .. }
2853            err.span_note(self.tcx.def_span(def_id), "this type alias is unsized");
2854            err.multipart_suggestion(
2855                ::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!(
2856                    "consider boxing the return type, and wrapping all of the returned values in \
2857                    `Box::new`",
2858                ),
2859                ::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![
2860                    (ty.span.shrink_to_lo(), "Box<".to_string()),
2861                    (ty.span.shrink_to_hi(), ">".to_string()),
2862                ],
2863                Applicability::MaybeIncorrect,
2864            );
2865            return false;
2866        }
2867
2868        err.code(E0746);
2869        err.primary_message("return type cannot be a trait object without pointer indirection");
2870        err.children.clear();
2871
2872        let mut span = obligation.cause.span;
2873        let mut is_async_fn_return = false;
2874        if let DefKind::Closure = self.tcx.def_kind(obligation.cause.body_def_id)
2875            && let parent = self.tcx.local_parent(obligation.cause.body_def_id)
2876            && let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(parent)
2877            && self.tcx.asyncness(parent).is_async()
2878            && let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
2879            | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
2880            | Node::TraitItem(hir::TraitItem {
2881                kind: hir::TraitItemKind::Fn(fn_sig, _), ..
2882            }) = self.tcx.hir_node_by_def_id(parent)
2883        {
2884            // Do not suggest (#147894)
2885            // async fn foo() -> dyn Display impl { .. }
2886            // and
2887            // async fn foo() -> dyn Display Box<dyn { .. }>
2888            span = fn_sig.decl.output.span();
2889            is_async_fn_return = true;
2890            err.span(span);
2891        }
2892        let body = self.tcx.hir_body_owned_by(obligation.cause.body_def_id);
2893
2894        if !is_async_fn_return
2895            && let Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
2896                self.tcx.hir_node_by_def_id(obligation.cause.body_def_id)
2897            && #[allow(non_exhaustive_omitted_patterns)] match closure.fn_decl.output {
    hir::FnRetTy::DefaultReturn(_) => true,
    _ => false,
}matches!(closure.fn_decl.output, hir::FnRetTy::DefaultReturn(_))
2898        {
2899            return true;
2900        }
2901
2902        let mut visitor = ReturnsVisitor::default();
2903        visitor.visit_body(&body);
2904
2905        let (pre, impl_span) = if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
2906            && snip.starts_with("dyn ")
2907        {
2908            ("", span.with_hi(span.lo() + BytePos(4)))
2909        } else {
2910            ("dyn ", span.shrink_to_lo())
2911        };
2912
2913        err.span_suggestion_verbose(
2914            impl_span,
2915            "consider returning an `impl Trait` instead of a `dyn Trait`",
2916            "impl ",
2917            Applicability::MaybeIncorrect,
2918        );
2919
2920        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![
2921            (span.shrink_to_lo(), format!("Box<{pre}")),
2922            (span.shrink_to_hi(), ">".to_string()),
2923        ];
2924        sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
2925            let span =
2926                expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
2927            if !span.can_be_used_for_suggestions() {
2928                ::alloc::vec::Vec::new()vec![]
2929            } else if let hir::ExprKind::Call(path, ..) = expr.kind
2930                && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, method)) = path.kind
2931                && method.ident.name == sym::new
2932                && let hir::TyKind::Path(hir::QPath::Resolved(.., box_path)) = ty.kind
2933                && box_path
2934                    .res
2935                    .opt_def_id()
2936                    .is_some_and(|def_id| self.tcx.is_lang_item(def_id, LangItem::OwnedBox))
2937            {
2938                // Don't box `Box::new`
2939                ::alloc::vec::Vec::new()vec![]
2940            } else {
2941                ::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![
2942                    (span.shrink_to_lo(), "Box::new(".to_string()),
2943                    (span.shrink_to_hi(), ")".to_string()),
2944                ]
2945            }
2946        }));
2947
2948        err.multipart_suggestion(
2949            ::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!(
2950                "alternatively, box the return type, and wrap all of the returned values in \
2951                 `Box::new`",
2952            ),
2953            sugg,
2954            Applicability::MaybeIncorrect,
2955        );
2956
2957        true
2958    }
2959
2960    pub(super) fn report_closure_arg_mismatch(
2961        &self,
2962        span: Span,
2963        found_span: Option<Span>,
2964        found: ty::TraitRef<'tcx>,
2965        expected: ty::TraitRef<'tcx>,
2966        cause: &ObligationCauseCode<'tcx>,
2967        found_node: Option<Node<'_>>,
2968        param_env: ty::ParamEnv<'tcx>,
2969    ) -> Diag<'a> {
2970        pub(crate) fn build_fn_sig_ty<'tcx>(
2971            infcx: &InferCtxt<'tcx>,
2972            trait_ref: ty::TraitRef<'tcx>,
2973        ) -> Ty<'tcx> {
2974            let inputs = trait_ref.args.type_at(1);
2975            let sig = match inputs.kind() {
2976                ty::Tuple(inputs) if infcx.tcx.is_callable_trait(trait_ref.def_id) => {
2977                    infcx.tcx.mk_fn_sig_safe_rust_abi(*inputs, infcx.next_ty_var(DUMMY_SP))
2978                }
2979                _ => infcx.tcx.mk_fn_sig_safe_rust_abi([inputs], infcx.next_ty_var(DUMMY_SP)),
2980            };
2981
2982            Ty::new_fn_ptr(infcx.tcx, ty::Binder::dummy(sig))
2983        }
2984
2985        let argument_kind = match expected.self_ty().kind() {
2986            ty::Closure(..) => "closure",
2987            ty::Coroutine(..) => "coroutine",
2988            _ => "function",
2989        };
2990        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!(
2991            self.dcx(),
2992            span,
2993            E0631,
2994            "type mismatch in {argument_kind} arguments",
2995        );
2996
2997        err.span_label(span, "expected due to this");
2998
2999        let found_span = found_span.unwrap_or(span);
3000        err.span_label(found_span, "found signature defined here");
3001
3002        let expected = build_fn_sig_ty(self, expected);
3003        let found = build_fn_sig_ty(self, found);
3004
3005        let (expected_str, found_str) = self.cmp(expected, found);
3006
3007        let signature_kind = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} signature", argument_kind))
    })format!("{argument_kind} signature");
3008        err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
3009
3010        self.note_conflicting_fn_args(&mut err, cause, expected, found, param_env);
3011        self.note_conflicting_closure_bounds(cause, &mut err);
3012
3013        if let Some(found_node) = found_node {
3014            hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
3015        }
3016
3017        err
3018    }
3019
3020    fn note_conflicting_fn_args(
3021        &self,
3022        err: &mut Diag<'_>,
3023        cause: &ObligationCauseCode<'tcx>,
3024        expected: Ty<'tcx>,
3025        found: Ty<'tcx>,
3026        param_env: ty::ParamEnv<'tcx>,
3027    ) {
3028        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else {
3029            return;
3030        };
3031        let ty::FnPtr(sig_tys, hdr) = expected.kind() else {
3032            return;
3033        };
3034        let expected = sig_tys.with(*hdr);
3035        let ty::FnPtr(sig_tys, hdr) = found.kind() else {
3036            return;
3037        };
3038        let found = sig_tys.with(*hdr);
3039        let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else {
3040            return;
3041        };
3042        let hir::ExprKind::Path(path) = arg.kind else {
3043            return;
3044        };
3045        let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(expected).inputs();
3046        let found_inputs = self.tcx.instantiate_bound_regions_with_erased(found).inputs();
3047        let both_tys = expected_inputs.iter().copied().zip(found_inputs.iter().copied());
3048
3049        let arg_expr = |infcx: &InferCtxt<'tcx>, name, expected: Ty<'tcx>, found: Ty<'tcx>| {
3050            let (expected_ty, expected_refs) = get_deref_type_and_refs(expected);
3051            let (found_ty, found_refs) = get_deref_type_and_refs(found);
3052
3053            if infcx.can_eq(param_env, found_ty, expected_ty) {
3054                if found_refs.len() == expected_refs.len()
3055                    && found_refs.iter().eq(expected_refs.iter())
3056                {
3057                    name
3058                } else if found_refs.len() > expected_refs.len() {
3059                    let refs = &found_refs[..found_refs.len() - expected_refs.len()];
3060                    if found_refs[..expected_refs.len()].iter().eq(expected_refs.iter()) {
3061                        ::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!(
3062                            "{}{name}",
3063                            refs.iter()
3064                                .map(|mutbl| format!("&{}", mutbl.prefix_str()))
3065                                .collect::<Vec<_>>()
3066                                .join(""),
3067                        )
3068                    } else {
3069                        // The refs have different mutability.
3070                        ::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!(
3071                            "{}*{name}",
3072                            refs.iter()
3073                                .map(|mutbl| format!("&{}", mutbl.prefix_str()))
3074                                .collect::<Vec<_>>()
3075                                .join(""),
3076                        )
3077                    }
3078                } else if expected_refs.len() > found_refs.len() {
3079                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                (0..(expected_refs.len() -
                                            found_refs.len())).map(|_|
                                "*").collect::<Vec<_>>().join(""), name))
    })format!(
3080                        "{}{name}",
3081                        (0..(expected_refs.len() - found_refs.len()))
3082                            .map(|_| "*")
3083                            .collect::<Vec<_>>()
3084                            .join(""),
3085                    )
3086                } else {
3087                    ::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!(
3088                        "{}{name}",
3089                        found_refs
3090                            .iter()
3091                            .map(|mutbl| format!("&{}", mutbl.prefix_str()))
3092                            .chain(found_refs.iter().map(|_| "*".to_string()))
3093                            .collect::<Vec<_>>()
3094                            .join(""),
3095                    )
3096                }
3097            } else {
3098                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", found))
    })format!("/* {found} */")
3099            }
3100        };
3101        let args_have_same_underlying_type = both_tys.clone().all(|(expected, found)| {
3102            let (expected_ty, _) = get_deref_type_and_refs(expected);
3103            let (found_ty, _) = get_deref_type_and_refs(found);
3104            self.can_eq(param_env, found_ty, expected_ty)
3105        });
3106        let (closure_names, call_names): (Vec<_>, Vec<_>) = if args_have_same_underlying_type
3107            && !expected_inputs.is_empty()
3108            && expected_inputs.len() == found_inputs.len()
3109            && let Some(typeck) = &self.typeck_results
3110            && let Res::Def(res_kind, fn_def_id) = typeck.qpath_res(&path, *arg_hir_id)
3111            && res_kind.is_fn_like()
3112        {
3113            let closure: Vec<_> = self
3114                .tcx
3115                .fn_arg_idents(fn_def_id)
3116                .iter()
3117                .enumerate()
3118                .map(|(i, ident)| {
3119                    if let Some(ident) = ident
3120                        && !#[allow(non_exhaustive_omitted_patterns)] match ident {
    Ident { name: kw::Underscore | kw::SelfLower, .. } => true,
    _ => false,
}matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
3121                    {
3122                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", ident))
    })format!("{ident}")
3123                    } else {
3124                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}")
3125                    }
3126                })
3127                .collect();
3128            let args = closure
3129                .iter()
3130                .zip(both_tys)
3131                .map(|(name, (expected, found))| {
3132                    arg_expr(self.infcx, name.to_owned(), expected, found)
3133                })
3134                .collect();
3135            (closure, args)
3136        } else {
3137            let closure_args = expected_inputs
3138                .iter()
3139                .enumerate()
3140                .map(|(i, _)| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}"))
3141                .collect::<Vec<_>>();
3142            let call_args = both_tys
3143                .enumerate()
3144                .map(|(i, (expected, found))| {
3145                    arg_expr(self.infcx, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arg{0}", i))
    })format!("arg{i}"), expected, found)
3146                })
3147                .collect::<Vec<_>>();
3148            (closure_args, call_args)
3149        };
3150        let closure_names: Vec<_> = closure_names
3151            .into_iter()
3152            .zip(expected_inputs.iter())
3153            .map(|(name, ty)| {
3154                ::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!(
3155                    "{name}{}",
3156                    if ty.has_infer_types() {
3157                        String::new()
3158                    } else if ty.references_error() {
3159                        ": /* type */".to_string()
3160                    } else {
3161                        format!(": {ty}")
3162                    }
3163                )
3164            })
3165            .collect();
3166        err.multipart_suggestion(
3167            "consider wrapping the function in a closure",
3168            ::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![
3169                (arg.span.shrink_to_lo(), format!("|{}| ", closure_names.join(", "))),
3170                (arg.span.shrink_to_hi(), format!("({})", call_names.join(", "))),
3171            ],
3172            Applicability::MaybeIncorrect,
3173        );
3174    }
3175
3176    // Add a note if there are two `Fn`-family bounds that have conflicting argument
3177    // requirements, which will always cause a closure to have a type error.
3178    fn note_conflicting_closure_bounds(
3179        &self,
3180        cause: &ObligationCauseCode<'tcx>,
3181        err: &mut Diag<'_>,
3182    ) {
3183        // First, look for a `WhereClauseInExpr`, which means we can get
3184        // the uninstantiated predicate list of the called function. And check
3185        // that the predicate that we failed to satisfy is a `Fn`-like trait.
3186        if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = *cause
3187            && let gen_clauses = self.tcx.clauses_of(def_id).instantiate_identity(self.tcx)
3188            && let Some(clause) = gen_clauses.clauses.get(idx).map(|c| c.as_ref().skip_norm_wip())
3189            && let ty::ClauseKind::Trait(trait_pred) = clause.kind().skip_binder()
3190            && self.tcx.is_fn_trait(trait_pred.def_id())
3191        {
3192            let expected_self =
3193                self.tcx.anonymize_bound_vars(clause.kind().rebind(trait_pred.self_ty()));
3194            let expected_args =
3195                self.tcx.anonymize_bound_vars(clause.kind().rebind(trait_pred.trait_ref.args));
3196
3197            // Find another clause whose self-type is equal to the expected self type,
3198            // but whose args don't match.
3199            let other_clause =
3200                gen_clauses.into_iter().enumerate().find(|&(other_idx, (clause, _))| {
3201                    let clause = clause.skip_norm_wip();
3202                    match clause.kind().skip_binder() {
3203                        ty::ClauseKind::Trait(trait_pred)
3204                            if self.tcx.is_fn_trait(trait_pred.def_id())
3205                            && other_idx != idx
3206                            // Make sure that the self type matches
3207                            // (i.e. constraining this closure)
3208                            && expected_self
3209                                == self.tcx.anonymize_bound_vars(
3210                                    clause.kind().rebind(trait_pred.self_ty()),
3211                                )
3212                            // But the args don't match (i.e. incompatible args)
3213                            && expected_args
3214                                != self.tcx.anonymize_bound_vars(
3215                                    clause.kind().rebind(trait_pred.trait_ref.args),
3216                                ) =>
3217                        {
3218                            true
3219                        }
3220                        _ => false,
3221                    }
3222                });
3223            // If we found one, then it's very likely the cause of the error.
3224            if let Some((_, (_, other_clause_span))) = other_clause {
3225                err.span_note(
3226                    other_clause_span,
3227                    "closure inferred to have a different signature due to this bound",
3228                );
3229            }
3230        }
3231    }
3232
3233    pub(super) fn suggest_fully_qualified_path(
3234        &self,
3235        err: &mut Diag<'_>,
3236        item_def_id: DefId,
3237        span: Span,
3238        trait_ref: DefId,
3239    ) {
3240        if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id)
3241            && let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind
3242        {
3243            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!(
3244                "{}s cannot be accessed directly on a `trait`, they can only be \
3245                        accessed through a specific `impl`",
3246                self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
3247            ));
3248
3249            if !assoc_item.is_impl_trait_in_trait() {
3250                err.span_suggestion_verbose(
3251                    span,
3252                    "use the fully qualified path to an implementation",
3253                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<Type as {0}>::{1}",
                self.tcx.def_path_str(trait_ref), assoc_item.name()))
    })format!(
3254                        "<Type as {}>::{}",
3255                        self.tcx.def_path_str(trait_ref),
3256                        assoc_item.name()
3257                    ),
3258                    Applicability::HasPlaceholders,
3259                );
3260            }
3261        }
3262    }
3263
3264    /// Adds an async-await specific note to the diagnostic when the future does not implement
3265    /// an auto trait because of a captured type.
3266    ///
3267    /// ```text
3268    /// note: future does not implement `Qux` as this value is used across an await
3269    ///   --> $DIR/issue-64130-3-other.rs:17:5
3270    ///    |
3271    /// LL |     let x = Foo;
3272    ///    |         - has type `Foo`
3273    /// LL |     baz().await;
3274    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
3275    /// LL | }
3276    ///    | - `x` is later dropped here
3277    /// ```
3278    ///
3279    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
3280    /// is "replaced" with a different message and a more specific error.
3281    ///
3282    /// ```text
3283    /// error: future cannot be sent between threads safely
3284    ///   --> $DIR/issue-64130-2-send.rs:21:5
3285    ///    |
3286    /// LL | fn is_send<T: Send>(t: T) { }
3287    ///    |               ---- required by this bound in `is_send`
3288    /// ...
3289    /// LL |     is_send(bar());
3290    ///    |     ^^^^^^^ future returned by `bar` is not send
3291    ///    |
3292    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
3293    ///            implemented for `Foo`
3294    /// note: future is not send as this value is used across an await
3295    ///   --> $DIR/issue-64130-2-send.rs:15:5
3296    ///    |
3297    /// LL |     let x = Foo;
3298    ///    |         - has type `Foo`
3299    /// LL |     baz().await;
3300    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
3301    /// LL | }
3302    ///    | - `x` is later dropped here
3303    /// ```
3304    ///
3305    /// Returns `true` if an async-await specific note was added to the diagnostic.
3306    {}
#[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("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3306u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("obligation.predicate")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("obligation.predicate");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("obligation.cause.span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("obligation.cause.span");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation.predicate)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation.cause.span)
                                                            as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3345",
                                        "rustc_trait_selection::error_reporting::traits::suggestions",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                        ::tracing_core::__macro_support::Option::Some(3345u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                        ::tracing_core::field::FieldSet::new(&[{
                                                            const NAME:
                                                                ::tracing::__macro_support::FieldName<{
                                                                    ::tracing::__macro_support::FieldName::len("code")
                                                                }> =
                                                                ::tracing::__macro_support::FieldName::new("code");
                                                            NAME.as_str()
                                                        }], ::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};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&code)
                                                            as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3352",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(3352u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&["message",
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("parent_trait_ref")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("parent_trait_ref");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("self_ty.kind")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("self_ty.kind");
                                                                    NAME.as_str()
                                                                }], ::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};
                                        __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("ImplDerived")
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause.derived.parent_trait_pred)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty.kind())
                                                                    as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3382",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(3382u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("parent_trait_ref")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("parent_trait_ref");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("self_ty.kind")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("self_ty.kind");
                                                                    NAME.as_str()
                                                                }], ::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};
                                        __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&derived_obligation.parent_trait_pred)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty.kind())
                                                                    as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3413",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3413u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("coroutine")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("coroutine");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_ref")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_ref");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_ty");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&coroutine)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_ref)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_ty)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3423",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3423u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("coroutine_did")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("coroutine_did");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("coroutine_did_root")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("coroutine_did_root");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("typeck_results.hir_owner")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("typeck_results.hir_owner");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("span");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&coroutine_did)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&coroutine_did_root)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.typeck_results.as_ref().map(|t|
                                                                            t.hir_owner)) as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3436",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3436u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("awaits")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("awaits");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&visitor.awaits)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3457",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(3457u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("ty_erased")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("ty_erased");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("target_ty_erased")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("target_ty_erased");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("eq")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("eq");
                                                                    NAME.as_str()
                                                                }], ::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};
                                        __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty_erased)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_ty_erased)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&eq)
                                                                    as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3481",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3481u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("from_awaited_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("from_awaited_ty");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&from_awaited_ty)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3489",
                                        "rustc_trait_selection::error_reporting::traits::suggestions",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                        ::tracing_core::__macro_support::Option::Some(3489u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                        ::tracing_core::field::FieldSet::new(&[{
                                                            const NAME:
                                                                ::tracing::__macro_support::FieldName<{
                                                                    ::tracing::__macro_support::FieldName::len("coroutine_info")
                                                                }> =
                                                                ::tracing::__macro_support::FieldName::new("coroutine_info");
                                                            NAME.as_str()
                                                        }], ::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};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&coroutine_info)
                                                            as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3493",
                                            "rustc_trait_selection::error_reporting::traits::suggestions",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                            ::tracing_core::__macro_support::Option::Some(3493u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                            ::tracing_core::field::FieldSet::new(&[{
                                                                const NAME:
                                                                    ::tracing::__macro_support::FieldName<{
                                                                        ::tracing::__macro_support::FieldName::len("variant")
                                                                    }> =
                                                                    ::tracing::__macro_support::FieldName::new("variant");
                                                                NAME.as_str()
                                                            }], ::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};
                                    __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&variant)
                                                                as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3496",
                                                "rustc_trait_selection::error_reporting::traits::suggestions",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                                ::tracing_core::__macro_support::Option::Some(3496u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("decl")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("decl");
                                                                    NAME.as_str()
                                                                }], ::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};
                                        __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&decl)
                                                                    as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3517",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3517u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("interior_or_upvar_span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("interior_or_upvar_span");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&interior_or_upvar_span)
                                                        as &dyn ::tracing::field::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))]
3307    pub fn maybe_note_obligation_cause_for_async_await(
3308        &self,
3309        err: &mut Diag<'_>,
3310        obligation: &PredicateObligation<'tcx>,
3311    ) -> bool {
3312        // Attempt to detect an async-await error by looking at the obligation causes, looking
3313        // for a coroutine to be present.
3314        //
3315        // When a future does not implement a trait because of a captured type in one of the
3316        // coroutines somewhere in the call stack, then the result is a chain of obligations.
3317        //
3318        // Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
3319        // future is passed as an argument to a function C which requires a `Send` type, then the
3320        // chain looks something like this:
3321        //
3322        // - `BuiltinDerivedObligation` with a coroutine witness (B)
3323        // - `BuiltinDerivedObligation` with a coroutine (B)
3324        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
3325        // - `BuiltinDerivedObligation` with a coroutine witness (A)
3326        // - `BuiltinDerivedObligation` with a coroutine (A)
3327        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
3328        // - `BindingObligation` with `impl_send` (Send requirement)
3329        //
3330        // The first obligation in the chain is the most useful and has the coroutine that captured
3331        // the type. The last coroutine (`outer_coroutine` below) has information about where the
3332        // bound was introduced. At least one coroutine should be present for this diagnostic to be
3333        // modified.
3334        let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
3335            ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) => (Some(p), Some(p.self_ty())),
3336            _ => (None, None),
3337        };
3338        let mut coroutine = None;
3339        let mut outer_coroutine = None;
3340        let mut next_code = Some(obligation.cause.code());
3341
3342        let mut seen_upvar_tys_infer_tuple = false;
3343
3344        while let Some(code) = next_code {
3345            debug!(?code);
3346            match code {
3347                ObligationCauseCode::FunctionArg { parent_code, .. } => {
3348                    next_code = Some(parent_code);
3349                }
3350                ObligationCauseCode::ImplDerived(cause) => {
3351                    let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
3352                    debug!(
3353                        parent_trait_ref = ?cause.derived.parent_trait_pred,
3354                        self_ty.kind = ?ty.kind(),
3355                        "ImplDerived",
3356                    );
3357
3358                    match *ty.kind() {
3359                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
3360                            coroutine = coroutine.or(Some(did));
3361                            outer_coroutine = Some(did);
3362                        }
3363                        ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
3364                            // By introducing a tuple of upvar types into the chain of obligations
3365                            // of a coroutine, the first non-coroutine item is now the tuple itself,
3366                            // we shall ignore this.
3367
3368                            seen_upvar_tys_infer_tuple = true;
3369                        }
3370                        _ if coroutine.is_none() => {
3371                            trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
3372                            target_ty = Some(ty);
3373                        }
3374                        _ => {}
3375                    }
3376
3377                    next_code = Some(&cause.derived.parent_code);
3378                }
3379                ObligationCauseCode::WellFormedDerived(derived_obligation)
3380                | ObligationCauseCode::BuiltinDerived(derived_obligation) => {
3381                    let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
3382                    debug!(
3383                        parent_trait_ref = ?derived_obligation.parent_trait_pred,
3384                        self_ty.kind = ?ty.kind(),
3385                    );
3386
3387                    match *ty.kind() {
3388                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
3389                            coroutine = coroutine.or(Some(did));
3390                            outer_coroutine = Some(did);
3391                        }
3392                        ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
3393                            // By introducing a tuple of upvar types into the chain of obligations
3394                            // of a coroutine, the first non-coroutine item is now the tuple itself,
3395                            // we shall ignore this.
3396
3397                            seen_upvar_tys_infer_tuple = true;
3398                        }
3399                        _ if coroutine.is_none() => {
3400                            trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
3401                            target_ty = Some(ty);
3402                        }
3403                        _ => {}
3404                    }
3405
3406                    next_code = Some(&derived_obligation.parent_code);
3407                }
3408                _ => break,
3409            }
3410        }
3411
3412        // Only continue if a coroutine was found.
3413        debug!(?coroutine, ?trait_ref, ?target_ty);
3414        let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
3415            (coroutine, trait_ref, target_ty)
3416        else {
3417            return false;
3418        };
3419
3420        let span = self.tcx.def_span(coroutine_did);
3421
3422        let coroutine_did_root = self.tcx.typeck_root_def_id(coroutine_did);
3423        debug!(
3424            ?coroutine_did,
3425            ?coroutine_did_root,
3426            typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
3427            ?span,
3428        );
3429
3430        let coroutine_body =
3431            coroutine_did.as_local().and_then(|def_id| self.tcx.hir_maybe_body_owned_by(def_id));
3432        let mut visitor = AwaitsVisitor::default();
3433        if let Some(body) = coroutine_body {
3434            visitor.visit_body(&body);
3435        }
3436        debug!(awaits = ?visitor.awaits);
3437
3438        // Look for a type inside the coroutine interior that matches the target type to get
3439        // a span.
3440        let target_ty_erased = self.tcx.erase_and_anonymize_regions(target_ty);
3441        let ty_matches = |ty| -> bool {
3442            // Careful: the regions for types that appear in the
3443            // coroutine interior are not generally known, so we
3444            // want to erase them when comparing (and anyway,
3445            // `Send` and other bounds are generally unaffected by
3446            // the choice of region). When erasing regions, we
3447            // also have to erase late-bound regions. This is
3448            // because the types that appear in the coroutine
3449            // interior generally contain "bound regions" to
3450            // represent regions that are part of the suspended
3451            // coroutine frame. Bound regions are preserved by
3452            // `erase_and_anonymize_regions` and so we must also call
3453            // `instantiate_bound_regions_with_erased`.
3454            let ty_erased = self.tcx.instantiate_bound_regions_with_erased(ty);
3455            let ty_erased = self.tcx.erase_and_anonymize_regions(ty_erased);
3456            let eq = ty_erased == target_ty_erased;
3457            debug!(?ty_erased, ?target_ty_erased, ?eq);
3458            eq
3459        };
3460
3461        // Get the typeck results from the infcx if the coroutine is the function we are currently
3462        // type-checking; otherwise, get them by performing a query. This is needed to avoid
3463        // cycles. If we can't use resolved types because the coroutine comes from another crate,
3464        // we still provide a targeted error but without all the relevant spans.
3465        let coroutine_data = match &self.typeck_results {
3466            Some(t) if t.hir_owner.to_def_id() == coroutine_did_root => CoroutineData(t),
3467            _ if coroutine_did.is_local() => {
3468                CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
3469            }
3470            _ => return false,
3471        };
3472
3473        let coroutine_within_in_progress_typeck = match &self.typeck_results {
3474            Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
3475            _ => false,
3476        };
3477
3478        let mut interior_or_upvar_span = None;
3479
3480        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, self.tcx, ty_matches);
3481        debug!(?from_awaited_ty);
3482
3483        // Avoid disclosing internal information to downstream crates.
3484        if coroutine_did.is_local()
3485            // Try to avoid cycles.
3486            && !coroutine_within_in_progress_typeck
3487            && let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
3488        {
3489            debug!(?coroutine_info);
3490            'find_source: for (variant, source_info) in
3491                coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
3492            {
3493                debug!(?variant);
3494                for &local in variant {
3495                    let decl = &coroutine_info.field_tys[local];
3496                    debug!(?decl);
3497                    if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
3498                        interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
3499                            decl.source_info.span,
3500                            Some((source_info.span, from_awaited_ty)),
3501                        ));
3502                        break 'find_source;
3503                    }
3504                }
3505            }
3506        }
3507
3508        if interior_or_upvar_span.is_none() {
3509            interior_or_upvar_span =
3510                coroutine_data.try_get_upvar_span(self, coroutine_did, ty_matches);
3511        }
3512
3513        if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
3514            interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(span, None));
3515        }
3516
3517        debug!(?interior_or_upvar_span);
3518        if let Some(interior_or_upvar_span) = interior_or_upvar_span {
3519            let is_async = self.tcx.coroutine_is_async(coroutine_did);
3520            self.note_obligation_cause_for_async_await(
3521                err,
3522                interior_or_upvar_span,
3523                is_async,
3524                outer_coroutine,
3525                trait_ref,
3526                target_ty,
3527                obligation,
3528                next_code,
3529            );
3530            true
3531        } else {
3532            false
3533        }
3534    }
3535
3536    /// Unconditionally adds the diagnostic note described in
3537    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
3538    {}
#[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("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3538u32),
                                    ::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_all(&[]) })
                } 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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:3761",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3761u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("next_code")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("next_code");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&next_code)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            self.note_obligation_cause_code(obligation.cause.body_def_id, err,
                obligation.predicate, obligation.param_env,
                next_code.unwrap(), &mut Vec::new(), &mut Default::default());
        }
    }
}#[instrument(level = "debug", skip_all)]
3539    fn note_obligation_cause_for_async_await(
3540        &self,
3541        err: &mut Diag<'_>,
3542        interior_or_upvar_span: CoroutineInteriorOrUpvar,
3543        is_async: bool,
3544        outer_coroutine: Option<DefId>,
3545        trait_pred: ty::TraitClause<'tcx>,
3546        target_ty: Ty<'tcx>,
3547        obligation: &PredicateObligation<'tcx>,
3548        next_code: Option<&ObligationCauseCode<'tcx>>,
3549    ) {
3550        let source_map = self.tcx.sess.source_map();
3551
3552        let (await_or_yield, an_await_or_yield) =
3553            if is_async { ("await", "an await") } else { ("yield", "a yield") };
3554        let future_or_coroutine = if is_async { "future" } else { "coroutine" };
3555
3556        // Special case the primary error message when send or sync is the trait that was
3557        // not implemented.
3558        let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
3559            self.tcx.get_diagnostic_name(trait_pred.def_id())
3560        {
3561            let (trait_name, trait_verb) =
3562                if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
3563
3564            err.code = None;
3565            err.primary_message(format!(
3566                "{future_or_coroutine} cannot be {trait_verb} between threads safely"
3567            ));
3568
3569            let original_span = err.span.primary_span().unwrap();
3570            let mut span = MultiSpan::from_span(original_span);
3571
3572            let message = outer_coroutine
3573                .and_then(|coroutine_did| {
3574                    Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
3575                        CoroutineKind::Coroutine(_) => format!("coroutine is not {trait_name}"),
3576                        CoroutineKind::Desugared(
3577                            CoroutineDesugaring::Async,
3578                            CoroutineSource::Fn,
3579                        ) => self
3580                            .tcx
3581                            .parent(coroutine_did)
3582                            .as_local()
3583                            .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
3584                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
3585                            .map(|name| {
3586                                format!("future returned by `{name}` is not {trait_name}")
3587                            })?,
3588                        CoroutineKind::Desugared(
3589                            CoroutineDesugaring::Async,
3590                            CoroutineSource::Block,
3591                        ) => {
3592                            format!("future created by async block is not {trait_name}")
3593                        }
3594                        CoroutineKind::Desugared(
3595                            CoroutineDesugaring::Async,
3596                            CoroutineSource::Closure,
3597                        ) => {
3598                            format!("future created by async closure is not {trait_name}")
3599                        }
3600                        CoroutineKind::Desugared(
3601                            CoroutineDesugaring::AsyncGen,
3602                            CoroutineSource::Fn,
3603                        ) => self
3604                            .tcx
3605                            .parent(coroutine_did)
3606                            .as_local()
3607                            .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
3608                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
3609                            .map(|name| {
3610                                format!("async iterator returned by `{name}` is not {trait_name}")
3611                            })?,
3612                        CoroutineKind::Desugared(
3613                            CoroutineDesugaring::AsyncGen,
3614                            CoroutineSource::Block,
3615                        ) => {
3616                            format!("async iterator created by async gen block is not {trait_name}")
3617                        }
3618                        CoroutineKind::Desugared(
3619                            CoroutineDesugaring::AsyncGen,
3620                            CoroutineSource::Closure,
3621                        ) => {
3622                            format!(
3623                                "async iterator created by async gen closure is not {trait_name}"
3624                            )
3625                        }
3626                        CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn) => {
3627                            self.tcx
3628                                .parent(coroutine_did)
3629                                .as_local()
3630                                .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
3631                                .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
3632                                .map(|name| {
3633                                    format!("iterator returned by `{name}` is not {trait_name}")
3634                                })?
3635                        }
3636                        CoroutineKind::Desugared(
3637                            CoroutineDesugaring::Gen,
3638                            CoroutineSource::Block,
3639                        ) => {
3640                            format!("iterator created by gen block is not {trait_name}")
3641                        }
3642                        CoroutineKind::Desugared(
3643                            CoroutineDesugaring::Gen,
3644                            CoroutineSource::Closure,
3645                        ) => {
3646                            format!("iterator created by gen closure is not {trait_name}")
3647                        }
3648                    })
3649                })
3650                .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
3651
3652            span.push_span_label(original_span, message);
3653            err.span(span);
3654
3655            format!("is not {trait_name}")
3656        } else {
3657            format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
3658        };
3659
3660        let mut explain_yield = |interior_span: Span, yield_span: Span| {
3661            let mut span = MultiSpan::from_span(yield_span);
3662            let snippet = match source_map.span_to_snippet(interior_span) {
3663                // #70935: If snippet contains newlines, display "the value" instead
3664                // so that we do not emit complex diagnostics.
3665                Ok(snippet) if !snippet.contains('\n') => format!("`{snippet}`"),
3666                _ => "the value".to_string(),
3667            };
3668            // note: future is not `Send` as this value is used across an await
3669            //   --> $DIR/issue-70935-complex-spans.rs:13:9
3670            //    |
3671            // LL |            baz(|| async {
3672            //    |  ______________-
3673            //    | |
3674            //    | |
3675            // LL | |              foo(tx.clone());
3676            // LL | |          }).await;
3677            //    | |          - ^^^^^^ await occurs here, with value maybe used later
3678            //    | |__________|
3679            //    |            has type `closure` which is not `Send`
3680            // note: value is later dropped here
3681            // LL | |          }).await;
3682            //    | |                  ^
3683            //
3684            span.push_span_label(
3685                yield_span,
3686                format!("{await_or_yield} occurs here, with {snippet} maybe used later"),
3687            );
3688            span.push_span_label(
3689                interior_span,
3690                format!("has type `{target_ty}` which {trait_explanation}"),
3691            );
3692            err.span_note(
3693                span,
3694                format!("{future_or_coroutine} {trait_explanation} as this value is used across {an_await_or_yield}"),
3695            );
3696        };
3697        match interior_or_upvar_span {
3698            CoroutineInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
3699                if let Some((yield_span, from_awaited_ty)) = interior_extra_info {
3700                    if let Some(await_span) = from_awaited_ty {
3701                        // The type causing this obligation is one being awaited at await_span.
3702                        let mut span = MultiSpan::from_span(await_span);
3703                        span.push_span_label(
3704                            await_span,
3705                            format!(
3706                                "await occurs here on type `{target_ty}`, which {trait_explanation}"
3707                            ),
3708                        );
3709                        err.span_note(
3710                            span,
3711                            format!(
3712                                "future {trait_explanation} as it awaits another future which {trait_explanation}"
3713                            ),
3714                        );
3715                    } else {
3716                        // Look at the last interior type to get a span for the `.await`.
3717                        explain_yield(interior_span, yield_span);
3718                    }
3719                }
3720            }
3721            CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
3722                // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
3723                let non_send = match target_ty.kind() {
3724                    ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(obligation) {
3725                        Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
3726                        _ => None,
3727                    },
3728                    _ => None,
3729                };
3730
3731                let (span_label, span_note) = match non_send {
3732                    // if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
3733                    // include suggestions to make `T: Sync` so that `&T: Send`,
3734                    // or to make `T: Send` so that `&mut T: Send`
3735                    Some((ref_ty, is_mut)) => {
3736                        let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
3737                        let ref_kind = if is_mut { "&mut" } else { "&" };
3738                        (
3739                            format!(
3740                                "has type `{target_ty}` which {trait_explanation}, because `{ref_ty}` is not `{ref_ty_trait}`"
3741                            ),
3742                            format!(
3743                                "captured value {trait_explanation} because `{ref_kind}` references cannot be sent unless their referent is `{ref_ty_trait}`"
3744                            ),
3745                        )
3746                    }
3747                    None => (
3748                        format!("has type `{target_ty}` which {trait_explanation}"),
3749                        format!("captured value {trait_explanation}"),
3750                    ),
3751                };
3752
3753                let mut span = MultiSpan::from_span(upvar_span);
3754                span.push_span_label(upvar_span, span_label);
3755                err.span_note(span, span_note);
3756            }
3757        }
3758
3759        // Add a note for the item obligation that remains - normally a note pointing to the
3760        // bound that introduced the obligation (e.g. `T: Send`).
3761        debug!(?next_code);
3762        self.note_obligation_cause_code(
3763            obligation.cause.body_def_id,
3764            err,
3765            obligation.predicate,
3766            obligation.param_env,
3767            next_code.unwrap(),
3768            &mut Vec::new(),
3769            &mut Default::default(),
3770        );
3771    }
3772
3773    fn note_closure_capture(
3774        &self,
3775        err: &mut Diag<'_>,
3776        closure_def_id: DefId,
3777        upvar_args: ty::UpvarArgs<'tcx>,
3778        capture_ty: Option<Ty<'tcx>>,
3779    ) -> bool {
3780        let Some(closure_def_id) = closure_def_id.as_local() else {
3781            return false;
3782        };
3783        let Some(capture_ty) = capture_ty else {
3784            return false;
3785        };
3786
3787        // This can run while `typeck` for the closure's root is still on the query stack, for
3788        // example when reporting an overflow from inside trait selection, so only the in-progress
3789        // results are safe to look at. Asking for the captures through `tcx.closure_captures`
3790        // would call `typeck` again and replace the error being reported with a cycle error.
3791        let Some(typeck_results) = &self.typeck_results else {
3792            return false;
3793        };
3794        let typeck_root = self.tcx.typeck_root_def_id(closure_def_id.to_def_id());
3795        if typeck_results.hir_owner.to_def_id() != typeck_root {
3796            return false;
3797        }
3798
3799        // Error reporting can run before closure capture analysis has inferred the
3800        // tuple of upvar types. avoid accessing upvar types until they are available.
3801        let upvar_tys = match upvar_args.tupled_upvars_ty().kind() {
3802            ty::Tuple(args) => args,
3803            ty::Error(_) => ty::List::empty(),
3804            ty::Infer(_) => return false,
3805            ty => {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("unexpected upvar types tuple: {0:?}", ty)));
}unreachable!("unexpected upvar types tuple: {ty:?}"),
3806        };
3807
3808        let captures: Vec<_> =
3809            typeck_results.closure_min_captures_flattened(closure_def_id).collect();
3810        if captures.len() != upvar_tys.len() {
3811            return false;
3812        }
3813
3814        let capture_ty =
3815            self.tcx.erase_and_anonymize_regions(self.deeply_resolve_ignoring_regions(capture_ty));
3816        let Some(capture) = captures.iter().zip(upvar_tys).find_map(|(&capture, upvar_ty)| {
3817            let upvar_ty = self
3818                .tcx
3819                .erase_and_anonymize_regions(self.deeply_resolve_ignoring_regions(upvar_ty));
3820            (upvar_ty == capture_ty).then_some(capture)
3821        }) else {
3822            return false;
3823        };
3824
3825        err.span_note(
3826            capture.get_path_span(self.tcx),
3827            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required because `{0}` is used within this closure",
                capture.to_string(self.tcx)))
    })format!(
3828                "required because `{}` is used within this closure",
3829                capture.to_string(self.tcx)
3830            ),
3831        );
3832        true
3833    }
3834
3835    pub(super) fn note_obligation_cause_code<T>(
3836        &self,
3837        body_def_id: LocalDefId,
3838        err: &mut Diag<'_>,
3839        predicate: T,
3840        param_env: ty::ParamEnv<'tcx>,
3841        cause_code: &ObligationCauseCode<'tcx>,
3842        obligated_types: &mut Vec<Ty<'tcx>>,
3843        seen_requirements: &mut FxHashSet<DefId>,
3844    ) where
3845        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
3846    {
3847        let predicate = predicate.upcast(self.tcx);
3848        // Built-in closure obligations pass through a synthetic tuple of upvar types. Remember
3849        // the last constituent before that tuple so it can be matched to a captured place.
3850        let mut closure_capture_ty =
3851            predicate.as_trait_clause().map(|trait_pred| trait_pred.skip_binder().self_ty());
3852        self.note_obligation_cause_code_inner(
3853            body_def_id,
3854            err,
3855            predicate,
3856            param_env,
3857            cause_code,
3858            obligated_types,
3859            seen_requirements,
3860            &mut closure_capture_ty,
3861        );
3862    }
3863
3864    fn note_obligation_cause_code_inner<T>(
3865        &self,
3866        body_def_id: LocalDefId,
3867        err: &mut Diag<'_>,
3868        predicate: T,
3869        param_env: ty::ParamEnv<'tcx>,
3870        cause_code: &ObligationCauseCode<'tcx>,
3871        obligated_types: &mut Vec<Ty<'tcx>>,
3872        seen_requirements: &mut FxHashSet<DefId>,
3873        closure_capture_ty: &mut Option<Ty<'tcx>>,
3874    ) where
3875        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
3876    {
3877        let tcx = self.tcx;
3878        let predicate = predicate.upcast(tcx);
3879        let suggest_remove_deref = |err: &mut Diag<'_>, expr: &hir::Expr<'_>| {
3880            if let Some(pred) = predicate.as_trait_clause()
3881                && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3882                && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
3883            {
3884                err.span_suggestion_verbose(
3885                    expr.span.until(inner.span),
3886                    "references are always `Sized`, even if they point to unsized data; consider \
3887                     not dereferencing the expression",
3888                    String::new(),
3889                    Applicability::MaybeIncorrect,
3890                );
3891            }
3892        };
3893        match *cause_code {
3894            ObligationCauseCode::ExprAssignable
3895            | ObligationCauseCode::MatchExpressionArm { .. }
3896            | ObligationCauseCode::Pattern { .. }
3897            | ObligationCauseCode::IfExpression { .. }
3898            | ObligationCauseCode::IfExpressionWithNoElse
3899            | ObligationCauseCode::MainFunctionType
3900            | ObligationCauseCode::LangFunctionType(_)
3901            | ObligationCauseCode::IntrinsicType
3902            | ObligationCauseCode::MethodReceiver
3903            | ObligationCauseCode::ReturnNoExpression
3904            | ObligationCauseCode::Misc
3905            | ObligationCauseCode::WellFormed(..)
3906            | ObligationCauseCode::MatchImpl(..)
3907            | ObligationCauseCode::ReturnValue(_)
3908            | ObligationCauseCode::BlockTailExpression(..)
3909            | ObligationCauseCode::AwaitableExpr(_)
3910            | ObligationCauseCode::ForLoopIterator(_)
3911            | ObligationCauseCode::QuestionMark
3912            | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
3913            | ObligationCauseCode::LetElse
3914            | ObligationCauseCode::UnOp { .. }
3915            | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
3916            | ObligationCauseCode::AlwaysApplicableImpl
3917            | ObligationCauseCode::ConstParam(_)
3918            | ObligationCauseCode::ReferenceOutlivesReferent(..)
3919            | ObligationCauseCode::ObjectTypeBound(..) => {}
3920            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
3921                if let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id)
3922                    && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id)
3923                    && tcx.sess.source_map().lookup_char_pos(lhs.span.lo()).line
3924                        != tcx.sess.source_map().lookup_char_pos(rhs.span.hi()).line
3925                {
3926                    err.span_label(lhs.span, "");
3927                    err.span_label(rhs.span, "");
3928                }
3929            }
3930            ObligationCauseCode::RustCall => {
3931                if let Some(pred) = predicate.as_trait_clause()
3932                    && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3933                {
3934                    err.note("argument required to be sized due to `extern \"rust-call\"` ABI");
3935                }
3936            }
3937            ObligationCauseCode::SliceOrArrayElem => {
3938                err.note("slice and array elements must have `Sized` type");
3939            }
3940            ObligationCauseCode::ArrayLen(array_ty) => {
3941                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`"));
3942            }
3943            ObligationCauseCode::TupleElem => {
3944                err.note("only the last element of a tuple may have a dynamically sized type");
3945            }
3946            ObligationCauseCode::DynCompatible(span) => {
3947                err.multipart_suggestion(
3948                    "you might have meant to use `Self` to refer to the implementing type",
3949                    ::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())],
3950                    Applicability::MachineApplicable,
3951                );
3952            }
3953            ObligationCauseCode::WhereClause(item_def_id, span)
3954            | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
3955            | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..)
3956                if !span.is_dummy() =>
3957            {
3958                if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code {
3959                    if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id)
3960                        && let hir::ExprKind::Call(_, args) = expr.kind
3961                        && let Some(expr) = args.get(*pos)
3962                    {
3963                        suggest_remove_deref(err, &expr);
3964                    } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id)
3965                        && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind
3966                        && let Some(expr) = args.get(*pos)
3967                    {
3968                        suggest_remove_deref(err, &expr);
3969                    }
3970                }
3971                let item_name = tcx.def_path_str(item_def_id);
3972                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));
3973                let mut multispan = MultiSpan::from(span);
3974                let sm = tcx.sess.source_map();
3975                if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy =
3976                    tcx.def_kind(item_def_id)
3977                {
3978                    let span = tcx.def_span(tcx.parent(item_def_id)).shrink_to_lo();
3979                    multispan.push_span_context(span);
3980                }
3981                if let Some(ident) = tcx.opt_item_ident(item_def_id) {
3982                    multispan.push_span_context(ident.span);
3983                }
3984                let mut a = "a";
3985                let mut this = "this bound";
3986                let mut note = None;
3987                let mut help = None;
3988                if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
3989                    match clause {
3990                        ty::ClauseKind::Trait(trait_pred) => {
3991                            let def_id = trait_pred.def_id();
3992                            let visible_item = if let Some(local) = def_id.as_local() {
3993                                let ty = trait_pred.self_ty();
3994                                // when `TraitA: TraitB` and `S` only impl TraitA,
3995                                // we check if `TraitB` can be reachable from `S`
3996                                // to determine whether to note `TraitA` is sealed trait.
3997                                if let ty::Adt(adt, _) = ty.kind() {
3998                                    let visibilities = &tcx.resolutions(()).effective_visibilities;
3999                                    visibilities.effective_vis(local).is_none_or(|v| {
4000                                        v.at_level(Level::Reexported)
4001                                            .is_accessible_from(adt.did(), tcx)
4002                                    })
4003                                } else {
4004                                    // FIXME(xizheyin): if the type is not ADT, we should not suggest it
4005                                    true
4006                                }
4007                            } else {
4008                                // Check for foreign traits being reachable.
4009                                tcx.visible_parent_map(()).get(&def_id).is_some()
4010                            };
4011                            if tcx.is_lang_item(def_id, LangItem::Sized) {
4012                                // Check if this is an implicit bound, even in foreign crates.
4013                                if tcx
4014                                    .generics_of(item_def_id)
4015                                    .own_params
4016                                    .iter()
4017                                    .any(|param| tcx.def_span(param.def_id) == span)
4018                                {
4019                                    a = "an implicit `Sized`";
4020                                    this =
4021                                        "the implicit `Sized` requirement on this type parameter";
4022                                }
4023                                if let Some(hir::Node::TraitItem(hir::TraitItem {
4024                                    generics,
4025                                    kind: hir::TraitItemKind::Type(bounds, None),
4026                                    ..
4027                                })) = tcx.hir_get_if_local(item_def_id)
4028                                    // Do not suggest relaxing if there is an explicit `Sized` obligation.
4029                                    && !bounds.iter()
4030                                        .filter_map(|bound| bound.trait_ref())
4031                                        .any(|tr| tr.trait_def_id().is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)))
4032                                {
4033                                    let (span, separator) = if let [.., last] = bounds {
4034                                        (last.span().shrink_to_hi(), " +")
4035                                    } else {
4036                                        (generics.span.shrink_to_hi(), ":")
4037                                    };
4038                                    err.span_suggestion_verbose(
4039                                        span,
4040                                        "consider relaxing the implicit `Sized` restriction",
4041                                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} ?Sized", separator))
    })format!("{separator} ?Sized"),
4042                                        Applicability::MachineApplicable,
4043                                    );
4044                                }
4045                            }
4046                            if let DefKind::Trait = tcx.def_kind(item_def_id)
4047                                && !visible_item
4048                            {
4049                                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!(
4050                                    "`{short_item_name}` is a \"sealed trait\", because to implement it \
4051                                    you also need to implement `{}`, which is not accessible; this is \
4052                                    usually done to force you to use one of the provided types that \
4053                                    already implement it",
4054                                    with_no_trimmed_paths!(tcx.def_path_str(def_id)),
4055                                ));
4056                                let mut types = tcx
4057                                    .all_impls(def_id)
4058                                    .map(|t| {
4059                                        {
    let _guard = NoTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("  {0}",
                    tcx.type_of(t).instantiate_identity().skip_norm_wip()))
        })
}with_no_trimmed_paths!(format!(
4060                                            "  {}",
4061                                            tcx.type_of(t).instantiate_identity().skip_norm_wip(),
4062                                        ))
4063                                    })
4064                                    .collect::<Vec<_>>();
4065                                if !types.is_empty() {
4066                                    let len = types.len();
4067                                    let post = if len > 9 {
4068                                        types.truncate(8);
4069                                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\nand {0} others", len - 8))
    })format!("\nand {} others", len - 8)
4070                                    } else {
4071                                        String::new()
4072                                    };
4073                                    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!(
4074                                        "the following type{} implement{} the trait:\n{}{post}",
4075                                        pluralize!(len),
4076                                        if len == 1 { "s" } else { "" },
4077                                        types.join("\n"),
4078                                    ));
4079                                }
4080                            }
4081                        }
4082                        ty::ClauseKind::ConstArgHasType(..) => {
4083                            let descr =
4084                                ::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}`");
4085                            if span.is_visible(sm) {
4086                                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required by this const generic parameter in `{0}`",
                short_item_name))
    })format!(
4087                                    "required by this const generic parameter in `{short_item_name}`"
4088                                );
4089                                multispan.push_span_label(span, msg);
4090                                err.span_note(multispan, descr);
4091                            } else {
4092                                err.span_note(tcx.def_span(item_def_id), descr);
4093                            }
4094                            return;
4095                        }
4096                        _ => (),
4097                    }
4098                }
4099
4100                // If this is from a format string literal desugaring,
4101                // we've already said "required by this formatting parameter"
4102                let is_in_fmt_lit = if let Some(s) = err.span.primary_span() {
4103                    #[allow(non_exhaustive_omitted_patterns)] match s.desugaring_kind() {
    Some(DesugaringKind::FormatLiteral { .. }) => true,
    _ => false,
}matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. }))
4104                } else {
4105                    false
4106                };
4107                if !is_in_fmt_lit {
4108                    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}`");
4109                    if span.is_visible(sm) {
4110                        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}`");
4111                        multispan.push_span_label(span, msg);
4112                        err.span_note(multispan, descr);
4113                    } else {
4114                        err.span_note(tcx.def_span(item_def_id), descr);
4115                    }
4116                }
4117                if let Some(note) = note {
4118                    err.note(note);
4119                }
4120                if let Some(help) = help {
4121                    err.help(help);
4122                }
4123            }
4124            ObligationCauseCode::WhereClause(..)
4125            | ObligationCauseCode::WhereClauseInExpr(..)
4126            | ObligationCauseCode::HostEffectInExpr(..) => {
4127                // We hold the `DefId` of the item introducing the obligation, but displaying it
4128                // doesn't add user usable information. It always point at an associated item.
4129            }
4130            ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => {
4131                err.span_note(span, "required by a bound in an opaque type");
4132                if let Some(definition_def_id) = definition_def_id
4133                    // If there are any stalled coroutine obligations, then this
4134                    // error may be due to that, and not because the body has more
4135                    // where-clauses.
4136                    && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty()
4137                {
4138                    // FIXME(compiler-errors): We could probably point to something
4139                    // specific here if we tried hard enough...
4140                    err.span_note(
4141                        tcx.def_span(definition_def_id),
4142                        "this definition site has more where clauses than the opaque type",
4143                    );
4144                }
4145            }
4146            ObligationCauseCode::Coercion { source, target } => {
4147                let source = tcx
4148                    .short_string(self.deeply_resolve_ignoring_regions(source), err.long_ty_path());
4149                let target = tcx
4150                    .short_string(self.deeply_resolve_ignoring_regions(target), err.long_ty_path());
4151                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!(
4152                    "required for the cast from `{source}` to `{target}`",
4153                )));
4154            }
4155            ObligationCauseCode::RepeatElementCopy { is_constable, elt_span } => {
4156                err.note(
4157                    "the `Copy` trait is required because this value will be copied for each element of the array",
4158                );
4159                let sm = tcx.sess.source_map();
4160                if #[allow(non_exhaustive_omitted_patterns)] match is_constable {
    IsConstable::Fn | IsConstable::Ctor => true,
    _ => false,
}matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
4161                    && let Ok(_) = sm.span_to_snippet(elt_span)
4162                {
4163                    err.multipart_suggestion(
4164                        "create an inline `const` block",
4165                        ::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![
4166                            (elt_span.shrink_to_lo(), "const { ".to_string()),
4167                            (elt_span.shrink_to_hi(), " }".to_string()),
4168                        ],
4169                        Applicability::MachineApplicable,
4170                    );
4171                } else {
4172                    // FIXME: we may suggest array::repeat instead
4173                    err.help("consider using `core::array::from_fn` to initialize the array");
4174                    err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information");
4175                }
4176            }
4177            ObligationCauseCode::VariableType(hir_id) => {
4178                if let Some(typeck_results) = &self.typeck_results
4179                    && let Some(ty) = typeck_results.node_type_opt(hir_id)
4180                    && let ty::Error(_) = ty.kind()
4181                {
4182                    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!(
4183                        "`{predicate}` isn't satisfied, but the type of this pattern is \
4184                         `{{type error}}`",
4185                    ));
4186                    err.downgrade_to_delayed_bug();
4187                }
4188                let mut local = true;
4189                match tcx.parent_hir_node(hir_id) {
4190                    Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
4191                        err.span_suggestion_verbose(
4192                            ty.span.shrink_to_lo(),
4193                            "consider borrowing here",
4194                            "&",
4195                            Applicability::MachineApplicable,
4196                        );
4197                    }
4198                    Node::LetStmt(hir::LetStmt {
4199                        init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }),
4200                        ..
4201                    }) => {
4202                        // When encountering an assignment of an unsized trait, like
4203                        // `let x = ""[..];`, provide a suggestion to borrow the initializer in
4204                        // order to use have a slice instead.
4205                        err.span_suggestion_verbose(
4206                            span.shrink_to_lo(),
4207                            "consider borrowing here",
4208                            "&",
4209                            Applicability::MachineApplicable,
4210                        );
4211                    }
4212                    Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => {
4213                        // When encountering an assignment of an unsized trait, like `let x = *"";`,
4214                        // we check if the RHS is a deref operation, to suggest removing it.
4215                        suggest_remove_deref(err, &expr);
4216                    }
4217                    Node::Param(param) => {
4218                        err.span_suggestion_verbose(
4219                            param.ty_span.shrink_to_lo(),
4220                            "function arguments must have a statically known size, borrowed types \
4221                            always have a known size",
4222                            "&",
4223                            Applicability::MachineApplicable,
4224                        );
4225                        local = false;
4226                    }
4227                    _ => {}
4228                }
4229                if local {
4230                    err.note("all local variables must have a statically known size");
4231                }
4232            }
4233            ObligationCauseCode::SizedArgumentType(hir_id) => {
4234                let mut ty = None;
4235                let borrowed_msg = "function arguments must have a statically known size, borrowed \
4236                                    types always have a known size";
4237                if let Some(hir_id) = hir_id
4238                    && let hir::Node::Param(param) = self.tcx.hir_node(hir_id)
4239                    && let Some(decl) = self.tcx.parent_hir_node(hir_id).fn_decl()
4240                    && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
4241                {
4242                    // We use `contains` because the type might be surrounded by parentheses,
4243                    // which makes `ty_span` and `t.span` disagree with each other, but one
4244                    // fully contains the other: `foo: (dyn Foo + Bar)`
4245                    //                                 ^-------------^
4246                    //                                 ||
4247                    //                                 |t.span
4248                    //                                 param._ty_span
4249                    ty = Some(t);
4250                } else if let Some(hir_id) = hir_id
4251                    && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id)
4252                {
4253                    ty = Some(t);
4254                }
4255                if let Some(ty) = ty {
4256                    match ty.kind {
4257                        hir::TyKind::TraitObject(traits, _) => {
4258                            let (span, kw) = match traits {
4259                                [first, ..] if first.span.lo() == ty.span.lo() => {
4260                                    // Missing `dyn` in front of trait object.
4261                                    (ty.span.shrink_to_lo(), "dyn ")
4262                                }
4263                                [first, ..] => (ty.span.until(first.span), ""),
4264                                [] => ::rustc_span::macros::bug_impl(Some(ty.span),
    format_args!("trait object with no traits: {0:?}", ty),
    Location::caller())span_bug!(ty.span, "trait object with no traits: {ty:?}"),
4265                            };
4266                            let needs_parens = traits.len() != 1;
4267                            // Don't recommend impl Trait as a closure argument
4268                            if let Some(hir_id) = hir_id
4269                                && #[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!(
4270                                    self.tcx.parent_hir_node(hir_id),
4271                                    hir::Node::Item(hir::Item {
4272                                        kind: hir::ItemKind::Fn { .. },
4273                                        ..
4274                                    })
4275                                )
4276                            {
4277                                err.span_suggestion_verbose(
4278                                    span,
4279                                    "you can use `impl Trait` as the argument type",
4280                                    "impl ",
4281                                    Applicability::MaybeIncorrect,
4282                                );
4283                            }
4284                            let sugg = if !needs_parens {
4285                                ::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}"))]
4286                            } else {
4287                                ::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![
4288                                    (span.shrink_to_lo(), format!("&({kw}")),
4289                                    (ty.span.shrink_to_hi(), ")".to_string()),
4290                                ]
4291                            };
4292                            err.multipart_suggestion(
4293                                borrowed_msg,
4294                                sugg,
4295                                Applicability::MachineApplicable,
4296                            );
4297                        }
4298                        hir::TyKind::Slice(_ty) => {
4299                            err.span_suggestion_verbose(
4300                                ty.span.shrink_to_lo(),
4301                                "function arguments must have a statically known size, borrowed \
4302                                 slices always have a known size",
4303                                "&",
4304                                Applicability::MachineApplicable,
4305                            );
4306                        }
4307                        hir::TyKind::Path(_) => {
4308                            err.span_suggestion_verbose(
4309                                ty.span.shrink_to_lo(),
4310                                borrowed_msg,
4311                                "&",
4312                                Applicability::MachineApplicable,
4313                            );
4314                        }
4315                        _ => {}
4316                    }
4317                } else {
4318                    err.note("all function arguments must have a statically known size");
4319                }
4320                if tcx.sess.opts.unstable_features.is_nightly_build()
4321                    && !tcx.features().unsized_fn_params()
4322                {
4323                    err.help("unsized fn params are gated as an unstable feature");
4324                }
4325            }
4326            ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => {
4327                err.note("the return type of a function must have a statically known size");
4328            }
4329            ObligationCauseCode::SizedYieldType => {
4330                err.note("the yield type of a coroutine must have a statically known size");
4331            }
4332            ObligationCauseCode::AssignmentLhsSized => {
4333                err.note("the left-hand-side of an assignment must have a statically known size");
4334            }
4335            ObligationCauseCode::TupleInitializerSized => {
4336                err.note("tuples must have a statically known size to be initialized");
4337            }
4338            ObligationCauseCode::StructInitializerSized => {
4339                err.note("structs must have a statically known size to be initialized");
4340            }
4341            ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
4342                match *item {
4343                    AdtKind::Struct => {
4344                        if last {
4345                            err.note(
4346                                "the last field of a packed struct may only have a \
4347                                dynamically sized type if it does not need drop to be run",
4348                            );
4349                        } else {
4350                            err.note(
4351                                "only the last field of a struct may have a dynamically sized type",
4352                            );
4353                        }
4354                    }
4355                    AdtKind::Union => {
4356                        err.note("no field of a union may have a dynamically sized type");
4357                    }
4358                    AdtKind::Enum => {
4359                        err.note("no field of an enum variant may have a dynamically sized type");
4360                    }
4361                }
4362                err.help("change the field's type to have a statically known size");
4363                err.span_suggestion_verbose(
4364                    span.shrink_to_lo(),
4365                    "borrowed types always have a statically known size",
4366                    "&",
4367                    Applicability::MachineApplicable,
4368                );
4369                err.multipart_suggestion(
4370                    "the `Box` type always has a statically known size and allocates its contents \
4371                     in the heap",
4372                    ::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![
4373                        (span.shrink_to_lo(), "Box<".to_string()),
4374                        (span.shrink_to_hi(), ">".to_string()),
4375                    ],
4376                    Applicability::MachineApplicable,
4377                );
4378            }
4379            ObligationCauseCode::SizedConstOrStatic => {
4380                err.note("statics and constants must have a statically known size");
4381            }
4382            ObligationCauseCode::InlineAsmSized => {
4383                err.note("all inline asm arguments must have a statically known size");
4384            }
4385            ObligationCauseCode::SizedClosureCapture(closure_def_id) => {
4386                err.note(
4387                    "all values captured by value by a closure must have a statically known size",
4388                );
4389                let hir::ExprKind::Closure(closure) =
4390                    tcx.hir_node_by_def_id(closure_def_id).expect_expr().kind
4391                else {
4392                    ::rustc_span::macros::bug_impl(None,
    format_args!("expected closure in SizedClosureCapture obligation"),
    Location::caller());bug!("expected closure in SizedClosureCapture obligation");
4393                };
4394                if let hir::CaptureBy::Value { .. } = closure.capture_clause
4395                    && let Some(span) = closure.fn_arg_span
4396                {
4397                    err.span_label(span, "this closure captures all values by move");
4398                }
4399            }
4400            ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => {
4401                let what = match tcx.coroutine_kind(coroutine_def_id) {
4402                    None
4403                    | Some(hir::CoroutineKind::Coroutine(_))
4404                    | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => {
4405                        "yield"
4406                    }
4407                    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
4408                        "await"
4409                    }
4410                    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => {
4411                        "yield`/`await"
4412                    }
4413                };
4414                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("all values live across `{0}` must have a statically known size",
                what))
    })format!(
4415                    "all values live across `{what}` must have a statically known size"
4416                ));
4417            }
4418            ObligationCauseCode::SharedStatic => {
4419                err.note("shared static variables must have a type that implements `Sync`");
4420            }
4421            ObligationCauseCode::BuiltinDerived(ref data) => {
4422                let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred);
4423                let ty = parent_trait_ref.skip_binder().self_ty();
4424                if parent_trait_ref.references_error() {
4425                    // NOTE(eddyb) this was `.cancel()`, but `err`
4426                    // is borrowed, so we can't fully defuse it.
4427                    err.downgrade_to_delayed_bug();
4428                    return;
4429                }
4430
4431                // If the obligation for a tuple is set directly by a Coroutine or Closure,
4432                // then the tuple must be the one containing capture types.
4433                let is_upvar_tys_infer_tuple = if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Tuple(..) => true,
    _ => false,
}matches!(ty.kind(), ty::Tuple(..)) {
4434                    false
4435                } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
4436                    let parent_trait_ref =
4437                        self.deeply_resolve_ignoring_regions(data.parent_trait_pred);
4438                    let nested_ty = parent_trait_ref.skip_binder().self_ty();
4439                    #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
    ty::Coroutine(..) => true,
    _ => false,
}matches!(nested_ty.kind(), ty::Coroutine(..))
4440                        || #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
    ty::Closure(..) => true,
    _ => false,
}matches!(nested_ty.kind(), ty::Closure(..))
4441                        || #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
    ty::CoroutineClosure(..) => true,
    _ => false,
}matches!(nested_ty.kind(), ty::CoroutineClosure(..))
4442                } else {
4443                    false
4444                };
4445
4446                let is_builtin_async_fn_trait =
4447                    tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some();
4448
4449                if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait {
4450                    let mut msg = || {
4451                        let ty_str = tcx.short_string(ty, err.long_ty_path());
4452                        ::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}`")
4453                    };
4454                    match *ty.kind() {
4455                        ty::Adt(def, args) => {
4456                            let msg = msg();
4457                            match tcx.opt_item_ident(def.did()) {
4458                                Some(ident) => {
4459                                    let mut spans = MultiSpan::new();
4460                                    if def.did().is_local()
4461                                        && let Some(pred) = predicate.as_trait_clause()
4462                                    {
4463                                        let field_ty = self.deeply_resolve_ignoring_regions(
4464                                            pred.skip_binder().self_ty(),
4465                                        );
4466                                        for field in def.all_fields() {
4467                                            if field.ty(tcx, args).skip_norm_wip() == field_ty {
4468                                                let sp = tcx.def_span(field.did);
4469                                                spans.push_primary_span(sp);
4470                                                spans.push_span_label(sp, "required by this field");
4471                                            }
4472                                        }
4473                                    }
4474                                    if spans.has_primary_spans() {
4475                                        spans.push_span_context(ident.span);
4476                                    } else {
4477                                        spans.push_primary_span(ident.span);
4478                                        spans.push_span_label(ident.span, "");
4479                                    }
4480                                    err.span_note(spans, msg);
4481                                }
4482                                None => {
4483                                    err.note(msg);
4484                                }
4485                            }
4486                        }
4487                        ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => {
4488                            // If the previous type is async fn, this is the future generated by the body of an async function.
4489                            // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below).
4490                            let is_future = tcx.ty_is_opaque_future(ty);
4491                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:4491",
                        "rustc_trait_selection::error_reporting::traits::suggestions",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                        ::tracing_core::__macro_support::Option::Some(4491u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("obligated_types")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("obligated_types");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("is_future")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("is_future");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("note_obligation_cause_code: check for async fn")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligated_types)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&is_future)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(
4492                                ?obligated_types,
4493                                ?is_future,
4494                                "note_obligation_cause_code: check for async fn"
4495                            );
4496                            if is_future
4497                                && obligated_types.last().is_some_and(|ty| match ty.kind() {
4498                                    ty::Coroutine(last_def_id, ..) => {
4499                                        tcx.coroutine_is_async(*last_def_id)
4500                                    }
4501                                    _ => false,
4502                                })
4503                            {
4504                                // See comment above; skip printing twice.
4505                            } else {
4506                                let msg = msg();
4507                                err.span_note(tcx.def_span(def_id), msg);
4508                            }
4509                        }
4510                        ty::Coroutine(def_id, _) => {
4511                            let sp = tcx.def_span(def_id);
4512
4513                            // Special-case this to say "async block" instead of `[static coroutine]`.
4514                            let kind = tcx.coroutine_kind(def_id).unwrap();
4515                            err.span_note(
4516                                sp,
4517                                {
    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!(
4518                                    "required because it's used within this {kind:#}",
4519                                )),
4520                            );
4521                        }
4522                        ty::CoroutineWitness(..) => {
4523                            // Skip printing coroutine-witnesses, since we'll drill into
4524                            // the bad field in another derived obligation cause.
4525                        }
4526                        ty::Closure(def_id, args) => {
4527                            if !self.note_closure_capture(
4528                                err,
4529                                def_id,
4530                                ty::UpvarArgs::Closure(args),
4531                                *closure_capture_ty,
4532                            ) {
4533                                err.span_note(
4534                                    tcx.def_span(def_id),
4535                                    "required because it's used within this closure",
4536                                );
4537                            }
4538                        }
4539                        ty::CoroutineClosure(def_id, args) => {
4540                            if !self.note_closure_capture(
4541                                err,
4542                                def_id,
4543                                ty::UpvarArgs::CoroutineClosure(args),
4544                                *closure_capture_ty,
4545                            ) {
4546                                err.span_note(
4547                                    tcx.def_span(def_id),
4548                                    "required because it's used within this closure",
4549                                );
4550                            }
4551                        }
4552                        ty::Str => {
4553                            err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes");
4554                        }
4555                        _ => {
4556                            let msg = msg();
4557                            err.note(msg);
4558                        }
4559                    };
4560                }
4561
4562                if !is_upvar_tys_infer_tuple {
4563                    *closure_capture_ty = Some(ty);
4564                }
4565
4566                obligated_types.push(ty);
4567
4568                let parent_predicate = parent_trait_ref;
4569                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
4570                    self.note_obligation_cause_code_inner(
4571                        body_def_id,
4572                        err,
4573                        parent_predicate,
4574                        param_env,
4575                        &data.parent_code,
4576                        obligated_types,
4577                        seen_requirements,
4578                        closure_capture_ty,
4579                    );
4580                } else {
4581                    self.note_obligation_cause_code_inner(
4582                        body_def_id,
4583                        err,
4584                        parent_predicate,
4585                        param_env,
4586                        cause_code.peel_derives(),
4587                        obligated_types,
4588                        seen_requirements,
4589                        closure_capture_ty,
4590                    );
4591                }
4592            }
4593            ObligationCauseCode::ImplDerived(ref data) => {
4594                let mut parent_trait_pred =
4595                    self.deeply_resolve_ignoring_regions(data.derived.parent_trait_pred);
4596                let parent_def_id = parent_trait_pred.def_id();
4597                if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id)
4598                    && !tcx.features().enabled(sym::try_trait_v2)
4599                {
4600                    // If `#![feature(try_trait_v2)]` is not enabled, then there's no point on
4601                    // talking about `FromResidual<Result<A, B>>`, as the end user has nothing they
4602                    // can do about it. As far as they are concerned, `?` is compiler magic.
4603                    return;
4604                }
4605                if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) {
4606                    let parent_predicate =
4607                        self.deeply_resolve_ignoring_regions(data.derived.parent_trait_pred);
4608
4609                    // Skip PinDerefMutHelper in suggestions, but still show downstream suggestions.
4610
4611                    *closure_capture_ty = Some(parent_trait_pred.skip_binder().self_ty());
4612                    self.note_obligation_cause_code_inner(
4613                        body_def_id,
4614                        err,
4615                        parent_predicate,
4616                        param_env,
4617                        &data.derived.parent_code,
4618                        obligated_types,
4619                        seen_requirements,
4620                        closure_capture_ty,
4621                    );
4622                    return;
4623                }
4624                let self_ty_str =
4625                    tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
4626                let trait_name = tcx.short_string(
4627                    parent_trait_pred.print_modifiers_and_trait_path(),
4628                    err.long_ty_path(),
4629                );
4630                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}`");
4631                let mut is_auto_trait = false;
4632                match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
4633                    Some(Node::Item(hir::Item {
4634                        kind: hir::ItemKind::Trait { is_auto, ident, .. },
4635                        ..
4636                    })) => {
4637                        // FIXME: we should do something else so that it works even on crate foreign
4638                        // auto traits.
4639                        is_auto_trait = #[allow(non_exhaustive_omitted_patterns)] match is_auto {
    hir::IsAuto::Yes => true,
    _ => false,
}matches!(is_auto, hir::IsAuto::Yes);
4640                        err.span_note(ident.span, msg);
4641                    }
4642                    Some(Node::Item(hir::Item {
4643                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
4644                        ..
4645                    })) => {
4646                        let mut spans = Vec::with_capacity(2);
4647                        if let Some(of_trait) = of_trait
4648                            && !of_trait.trait_ref.path.span.in_derive_expansion()
4649                        {
4650                            spans.push(of_trait.trait_ref.path.span);
4651                        }
4652                        spans.push(self_ty.span);
4653                        let mut spans: MultiSpan = spans.into();
4654                        let mut derived = false;
4655                        if #[allow(non_exhaustive_omitted_patterns)] match self_ty.span.ctxt().outer_expn_data().kind
    {
    ExpnKind::Macro(MacroKind::Derive, _) => true,
    _ => false,
}matches!(
4656                            self_ty.span.ctxt().outer_expn_data().kind,
4657                            ExpnKind::Macro(MacroKind::Derive, _)
4658                        ) || #[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!(
4659                            of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
4660                            Some(ExpnKind::Macro(MacroKind::Derive, _))
4661                        ) {
4662                            derived = true;
4663                            spans.push_span_label(
4664                                data.span,
4665                                if data.span.in_derive_expansion() {
4666                                    ::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}`")
4667                                } else {
4668                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unsatisfied trait bound"))
    })format!("unsatisfied trait bound")
4669                                },
4670                            );
4671                        } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) {
4672                            // `Sized` may be an explicit or implicit trait bound. If it is
4673                            // implicit, mention it as such.
4674                            if let Some(pred) = predicate.as_trait_clause()
4675                                && self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
4676                                && self
4677                                    .tcx
4678                                    .generics_of(data.impl_or_alias_def_id)
4679                                    .own_params
4680                                    .iter()
4681                                    .any(|param| self.tcx.def_span(param.def_id) == data.span)
4682                            {
4683                                spans.push_span_label(
4684                                    data.span,
4685                                    "unsatisfied trait bound implicitly introduced here",
4686                                );
4687                            } else {
4688                                spans.push_span_label(
4689                                    data.span,
4690                                    "unsatisfied trait bound introduced here",
4691                                );
4692                            }
4693                        }
4694                        err.span_note(spans, msg);
4695                        if derived
4696                            && self.is_truly_imperfect_derive(
4697                                parent_trait_pred,
4698                                predicate,
4699                                param_env,
4700                            )
4701                        {
4702                            err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider manually implementing `{0}` to avoid undesired bounds caused by \"imperfect derives\"",
                trait_name))
    })format!(
4703                                "consider manually implementing `{trait_name}` to avoid undesired bounds caused by \"imperfect derives\"",
4704                            ));
4705                            err.note(
4706                                "to learn more, visit <https://github.com/rust-lang/rust/issues/26925>",
4707                            );
4708                        }
4709                        point_at_assoc_type_restriction(
4710                            tcx,
4711                            err,
4712                            &self_ty_str,
4713                            &trait_name,
4714                            predicate,
4715                            &generics,
4716                            &data,
4717                        );
4718                    }
4719                    _ => {
4720                        err.note(msg);
4721                    }
4722                };
4723
4724                let mut parent_predicate = parent_trait_pred;
4725                let mut data = &data.derived;
4726                let mut count = 0;
4727                seen_requirements.insert(parent_def_id);
4728                if is_auto_trait {
4729                    // We don't want to point at the ADT saying "required because it appears within
4730                    // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
4731                    while let ObligationCauseCode::BuiltinDerived(derived) = &*data.parent_code {
4732                        let child_trait_ref =
4733                            self.deeply_resolve_ignoring_regions(derived.parent_trait_pred);
4734                        let child_def_id = child_trait_ref.def_id();
4735                        if seen_requirements.insert(child_def_id) {
4736                            break;
4737                        }
4738                        data = derived;
4739                        parent_predicate = child_trait_ref.upcast(tcx);
4740                        parent_trait_pred = child_trait_ref;
4741                    }
4742                }
4743                while let ObligationCauseCode::ImplDerived(child) = &*data.parent_code {
4744                    // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
4745                    let child_trait_pred =
4746                        self.deeply_resolve_ignoring_regions(child.derived.parent_trait_pred);
4747                    let child_def_id = child_trait_pred.def_id();
4748                    if seen_requirements.insert(child_def_id) {
4749                        break;
4750                    }
4751                    count += 1;
4752                    data = &child.derived;
4753                    parent_predicate = child_trait_pred.upcast(tcx);
4754                    parent_trait_pred = child_trait_pred;
4755                }
4756                if count > 0 {
4757                    err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} redundant requirement{1} hidden",
                count, if count == 1 { "" } else { "s" }))
    })format!(
4758                        "{} redundant requirement{} hidden",
4759                        count,
4760                        pluralize!(count)
4761                    ));
4762                    let self_ty = tcx.short_string(
4763                        parent_trait_pred.skip_binder().self_ty(),
4764                        err.long_ty_path(),
4765                    );
4766                    let trait_path = tcx.short_string(
4767                        parent_trait_pred.print_modifiers_and_trait_path(),
4768                        err.long_ty_path(),
4769                    );
4770                    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}`"));
4771                }
4772                *closure_capture_ty = Some(parent_trait_pred.skip_binder().self_ty());
4773                self.note_obligation_cause_code_inner(
4774                    body_def_id,
4775                    err,
4776                    parent_predicate,
4777                    param_env,
4778                    &data.parent_code,
4779                    obligated_types,
4780                    seen_requirements,
4781                    closure_capture_ty,
4782                )
4783            }
4784            ObligationCauseCode::ImplDerivedHost(ref data) => {
4785                let self_ty = tcx.short_string(
4786                    self.deeply_resolve_ignoring_regions(data.derived.parent_host_clause.self_ty()),
4787                    err.long_ty_path(),
4788                );
4789                let trait_path = tcx.short_string(
4790                    data.derived
4791                        .parent_host_clause
4792                        .map_bound(|clause| clause.trait_ref)
4793                        .print_only_trait_path(),
4794                    err.long_ty_path(),
4795                );
4796                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("required for `{1}` to implement `{0} {2}`",
                data.derived.parent_host_clause.skip_binder().constness,
                self_ty, trait_path))
    })format!(
4797                    "required for `{self_ty}` to implement `{} {trait_path}`",
4798                    data.derived.parent_host_clause.skip_binder().constness,
4799                );
4800                match tcx.hir_get_if_local(data.impl_def_id) {
4801                    Some(Node::Item(hir::Item {
4802                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
4803                        ..
4804                    })) => {
4805                        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];
4806                        spans.extend(of_trait.map(|t| t.trait_ref.path.span));
4807                        let mut spans: MultiSpan = spans.into();
4808                        spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
4809                        err.span_note(spans, msg);
4810                    }
4811                    _ => {
4812                        err.note(msg);
4813                    }
4814                }
4815
4816                self.note_obligation_cause_code_inner(
4817                    body_def_id,
4818                    err,
4819                    data.derived.parent_host_clause,
4820                    param_env,
4821                    &data.derived.parent_code,
4822                    obligated_types,
4823                    seen_requirements,
4824                    closure_capture_ty,
4825                );
4826            }
4827            ObligationCauseCode::BuiltinDerivedHost(ref data) => {
4828                self.note_obligation_cause_code_inner(
4829                    body_def_id,
4830                    err,
4831                    data.parent_host_clause,
4832                    param_env,
4833                    &data.parent_code,
4834                    obligated_types,
4835                    seen_requirements,
4836                    closure_capture_ty,
4837                );
4838            }
4839            ObligationCauseCode::WellFormedDerived(ref data) => {
4840                let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred);
4841                let parent_predicate = parent_trait_ref;
4842
4843                *closure_capture_ty = Some(parent_trait_ref.skip_binder().self_ty());
4844                self.note_obligation_cause_code_inner(
4845                    body_def_id,
4846                    err,
4847                    parent_predicate,
4848                    param_env,
4849                    &data.parent_code,
4850                    obligated_types,
4851                    seen_requirements,
4852                    closure_capture_ty,
4853                );
4854            }
4855            ObligationCauseCode::TypeAlias(ref nested, span, def_id) => {
4856                self.note_obligation_cause_code_inner(
4857                    body_def_id,
4858                    err,
4859                    predicate,
4860                    param_env,
4861                    nested,
4862                    obligated_types,
4863                    seen_requirements,
4864                    closure_capture_ty,
4865                );
4866                let mut multispan = MultiSpan::from(span);
4867                multispan.push_span_label(span, "required by this bound");
4868                err.span_note(
4869                    multispan,
4870                    ::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)),
4871                );
4872            }
4873            ObligationCauseCode::FunctionArg {
4874                arg_hir_id, call_hir_id, ref parent_code, ..
4875            } => {
4876                self.note_function_argument_obligation(
4877                    body_def_id,
4878                    err,
4879                    arg_hir_id,
4880                    parent_code,
4881                    param_env,
4882                    predicate,
4883                    call_hir_id,
4884                );
4885
4886                self.note_obligation_cause_code_inner(
4887                    body_def_id,
4888                    err,
4889                    predicate,
4890                    param_env,
4891                    parent_code,
4892                    obligated_types,
4893                    seen_requirements,
4894                    closure_capture_ty,
4895                );
4896            }
4897            // Suppress `compare_type_clause_entailment` errors for RPITITs, since they
4898            // should be implied by the parent method.
4899            ObligationCauseCode::CompareImplItem { trait_item_def_id, .. }
4900                if tcx.is_impl_trait_in_trait(trait_item_def_id) => {}
4901            ObligationCauseCode::CompareImplItem { trait_item_def_id, kind, .. } => {
4902                let item_name = tcx.item_name(trait_item_def_id);
4903                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!(
4904                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
4905                     `{item_name}` but not on the corresponding trait's {kind}",
4906                );
4907                let sp = tcx
4908                    .opt_item_ident(trait_item_def_id)
4909                    .map(|i| i.span)
4910                    .unwrap_or_else(|| tcx.def_span(trait_item_def_id));
4911                let mut assoc_span: MultiSpan = sp.into();
4912                assoc_span.push_span_label(
4913                    sp,
4914                    ::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}`"),
4915                );
4916                if let Some(ident) = tcx
4917                    .opt_associated_item(trait_item_def_id)
4918                    .and_then(|i| tcx.opt_item_ident(i.container_id(tcx)))
4919                {
4920                    assoc_span.push_span_label(ident.span, "in this trait");
4921                }
4922                err.span_note(assoc_span, msg);
4923            }
4924            ObligationCauseCode::TrivialBound => {
4925                tcx.disabled_nightly_features(err, [(String::new(), sym::trivial_bounds)]);
4926            }
4927            ObligationCauseCode::OpaqueReturnType(expr_info) => {
4928                // Point at the method call in the returned expression's chain where an
4929                // associated type diverged from what the signature's opaque type expects,
4930                // regardless of how the failed predicate was derived from that expectation.
4931                if let Some(typeck_results) = self.typeck_results.as_deref() {
4932                    let chain_expr = match expr_info {
4933                        Some((_, hir_id)) => Some(tcx.hir_expect_expr(hir_id)),
4934                        None => tcx.hir_node_by_def_id(body_def_id).body_id().and_then(|body_id| {
4935                            match tcx.hir_body(body_id).value.kind {
4936                                hir::ExprKind::Block(block, _) => block.expr,
4937                                _ => None,
4938                            }
4939                        }),
4940                    };
4941                    if let Some(chain_expr) = chain_expr {
4942                        self.point_at_chain_in_return_position(
4943                            body_def_id,
4944                            chain_expr,
4945                            typeck_results,
4946                            param_env,
4947                            err,
4948                        );
4949                    }
4950                }
4951                let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
4952                    let expr = tcx.hir_expect_expr(hir_id);
4953                    (expr_ty, expr)
4954                } else if let Some(body_id) = tcx.hir_node_by_def_id(body_def_id).body_id()
4955                    && let body = tcx.hir_body(body_id)
4956                    && let hir::ExprKind::Block(block, _) = body.value.kind
4957                    && let Some(expr) = block.expr
4958                    && let Some(expr_ty) = self
4959                        .typeck_results
4960                        .as_ref()
4961                        .and_then(|typeck| typeck.node_type_opt(expr.hir_id))
4962                    && let Some(pred) = predicate.as_clause()
4963                    && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
4964                    && self.can_eq(param_env, pred.self_ty(), expr_ty)
4965                {
4966                    (expr_ty, expr)
4967                } else {
4968                    return;
4969                };
4970                let expr_ty_string = tcx.short_string(expr_ty, err.long_ty_path());
4971                if expr_ty.is_never()
4972                    && let span = expr.span.source_callsite()
4973                    && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span)
4974                    && span != expr.span
4975                {
4976                    err.span_suggestion(
4977                        span,
4978                        "`!` can be coerced to any type; consider casting it to a concrete type that implements the trait",
4979                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} as /* Type */", snippet))
    })format!("{snippet} as /* Type */"),
4980                        Applicability::HasPlaceholders,
4981                    );
4982                }
4983                err.span_label(
4984                    expr.span,
4985                    {
    let _guard = ForceTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("return type was inferred to be `{0}` here",
                    expr_ty_string))
        })
}with_forced_trimmed_paths!(format!(
4986                        "return type was inferred to be `{expr_ty_string}` here",
4987                    )),
4988                );
4989                suggest_remove_deref(err, &expr);
4990            }
4991            ObligationCauseCode::UnsizedNonPlaceExpr(span) => {
4992                err.span_note(
4993                    span,
4994                    "unsized values must be place expressions and cannot be put in temporaries",
4995                );
4996            }
4997            ObligationCauseCode::CompareEii { .. } => {
4998                {
    ::core::panicking::panic_fmt(format_args!("trait bounds on EII not yet supported "));
}panic!("trait bounds on EII not yet supported ")
4999            }
5000        }
5001    }
5002
5003    {}
#[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("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5003u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("obligation")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("obligation");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_pred")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_pred");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("span");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_pred.self_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_pred.self_ty");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_pred)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_pred.self_ty())
                                                            as &dyn ::tracing::field::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.deeply_resolve_ignoring_regions(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, ty::IsRigid::No, item_def_id,
                                [trait_pred.self_ty()])
                        });
            let InferOk { value: projection_ty, .. } =
                self.at(&obligation.cause,
                        obligation.param_env).normalize(Unnormalized::new_wip(projection_ty));
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5040",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5040u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("normalized_projection_type")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("normalized_projection_type");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.deeply_resolve_ignoring_regions(projection_ty))
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:5047",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(5047u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("try_trait_obligation")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("try_trait_obligation");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&try_obligation)
                                                        as &dyn ::tracing::field::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_def_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_def_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(
5004        level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
5005    )]
5006    pub(super) fn suggest_await_before_try(
5007        &self,
5008        err: &mut Diag<'_>,
5009        obligation: &PredicateObligation<'tcx>,
5010        trait_pred: ty::PolyTraitClause<'tcx>,
5011        span: Span,
5012    ) {
5013        let future_trait = self.tcx.require_lang_item(LangItem::Future, span);
5014
5015        let self_ty = self.deeply_resolve_ignoring_regions(trait_pred.self_ty());
5016        let impls_future = self.type_implements_trait(
5017            future_trait,
5018            [self.tcx.instantiate_bound_regions_with_erased(self_ty)],
5019            obligation.param_env,
5020        );
5021        if !impls_future.must_apply_modulo_regions() {
5022            return;
5023        }
5024
5025        let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
5026        // `<T as Future>::Output`
5027        let projection_ty = trait_pred.map_bound(|trait_pred| {
5028            Ty::new_projection(
5029                self.tcx,
5030                ty::IsRigid::No,
5031                item_def_id,
5032                // Future::Output has no args
5033                [trait_pred.self_ty()],
5034            )
5035        });
5036        let InferOk { value: projection_ty, .. } = self
5037            .at(&obligation.cause, obligation.param_env)
5038            .normalize(Unnormalized::new_wip(projection_ty));
5039
5040        debug!(
5041            normalized_projection_type = ?self.deeply_resolve_ignoring_regions(projection_ty)
5042        );
5043        let try_obligation = self.mk_trait_obligation_with_new_self_ty(
5044            obligation.param_env,
5045            trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
5046        );
5047        debug!(try_trait_obligation = ?try_obligation);
5048        if self.predicate_may_hold(&try_obligation)
5049            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
5050            && snippet.ends_with('?')
5051        {
5052            match self.tcx.coroutine_kind(obligation.cause.body_def_id) {
5053                Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
5054                    err.span_suggestion_verbose(
5055                        span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
5056                        "consider `await`ing on the `Future`",
5057                        ".await",
5058                        Applicability::MaybeIncorrect,
5059                    );
5060                }
5061                _ => {
5062                    let mut span: MultiSpan = span.with_lo(span.hi() - BytePos(1)).into();
5063                    span.push_span_label(
5064                        self.tcx.def_span(obligation.cause.body_def_id),
5065                        "this is not `async`",
5066                    );
5067                    err.span_note(
5068                        span,
5069                        "this implements `Future` and its output type supports \
5070                        `?`, but the future cannot be awaited in a synchronous function",
5071                    );
5072                }
5073            }
5074        }
5075    }
5076
5077    pub(super) fn suggest_floating_point_literal(
5078        &self,
5079        obligation: &PredicateObligation<'tcx>,
5080        err: &mut Diag<'_>,
5081        trait_pred: ty::PolyTraitClause<'tcx>,
5082    ) {
5083        let rhs_span = match obligation.cause.code() {
5084            ObligationCauseCode::BinOp { rhs_span, rhs_is_lit, .. } if *rhs_is_lit => rhs_span,
5085            _ => return,
5086        };
5087        if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind()
5088            && let ty::Infer(InferTy::IntVar(_)) =
5089                trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
5090        {
5091            err.span_suggestion_verbose(
5092                rhs_span.shrink_to_hi(),
5093                "consider using a floating-point literal by writing it with `.0`",
5094                ".0",
5095                Applicability::MaybeIncorrect,
5096            );
5097        }
5098    }
5099
5100    pub fn can_suggest_derive(
5101        &self,
5102        obligation: &PredicateObligation<'tcx>,
5103        trait_pred: ty::PolyTraitClause<'tcx>,
5104    ) -> bool {
5105        if trait_pred.polarity() == ty::ClausePolarity::Negative {
5106            return false;
5107        }
5108        let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
5109            return false;
5110        };
5111        let (adt, args) = match trait_pred.skip_binder().self_ty().kind() {
5112            ty::Adt(adt, args) if adt.did().is_local() => (adt, args),
5113            _ => return false,
5114        };
5115        if !self.tcx.def_span(adt.did()).can_be_used_for_suggestions() {
5116            return false;
5117        }
5118        let is_derivable_trait = match diagnostic_name {
5119            sym::Copy | sym::Clone => true,
5120            _ if adt.is_union() => false,
5121            sym::PartialEq | sym::PartialOrd => {
5122                let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
5123                trait_pred.skip_binder().self_ty() == rhs_ty
5124            }
5125            sym::Eq | sym::Ord | sym::Hash | sym::Debug | sym::Default => true,
5126            _ => false,
5127        };
5128        is_derivable_trait &&
5129            // Ensure all fields impl the trait.
5130            adt.all_fields().all(|field| {
5131                let field_ty = ty::GenericArg::from(field.ty(self.tcx, args).skip_norm_wip());
5132                let trait_args = match diagnostic_name {
5133                    sym::PartialEq | sym::PartialOrd => {
5134                        Some(field_ty)
5135                    }
5136                    _ => None,
5137                };
5138                let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitClause {
5139                    trait_ref: ty::TraitRef::new(self.tcx,
5140                        trait_pred.def_id(),
5141                        [field_ty].into_iter().chain(trait_args),
5142                    ),
5143                    ..*tr
5144                });
5145                let field_obl = Obligation::new(
5146                    self.tcx,
5147                    obligation.cause.clone(),
5148                    obligation.param_env,
5149                    trait_pred,
5150                );
5151                self.predicate_must_hold_modulo_regions(&field_obl)
5152            })
5153    }
5154
5155    pub fn suggest_derive(
5156        &self,
5157        obligation: &PredicateObligation<'tcx>,
5158        err: &mut Diag<'_>,
5159        trait_pred: ty::PolyTraitClause<'tcx>,
5160    ) {
5161        let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
5162            return;
5163        };
5164        let adt = match trait_pred.skip_binder().self_ty().kind() {
5165            ty::Adt(adt, _) if adt.did().is_local() => adt,
5166            _ => return,
5167        };
5168        if self.can_suggest_derive(obligation, trait_pred) {
5169            err.span_suggestion_verbose(
5170                self.tcx.def_span(adt.did()).shrink_to_lo(),
5171                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider annotating `{0}` with `#[derive({1})]`",
                trait_pred.skip_binder().self_ty(), diagnostic_name))
    })format!(
5172                    "consider annotating `{}` with `#[derive({})]`",
5173                    trait_pred.skip_binder().self_ty(),
5174                    diagnostic_name,
5175                ),
5176                // FIXME(const_trait_impl) derive_const as suggestion?
5177                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[derive({0})]\n",
                diagnostic_name))
    })format!("#[derive({diagnostic_name})]\n"),
5178                Applicability::MaybeIncorrect,
5179            );
5180        }
5181    }
5182
5183    pub(super) fn suggest_dereferencing_index(
5184        &self,
5185        obligation: &PredicateObligation<'tcx>,
5186        err: &mut Diag<'_>,
5187        trait_pred: ty::PolyTraitClause<'tcx>,
5188    ) {
5189        if let ObligationCauseCode::ImplDerived(_) = obligation.cause.code()
5190            && self
5191                .tcx
5192                .is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
5193            && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
5194            && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
5195            && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
5196        {
5197            // If the index is written as `&i`, suggest removing the borrow instead of
5198            // dereferencing it, i.e. `v[&i]` -> `v[i]` rather than `v[*&i]`.
5199            let span = obligation.cause.span;
5200            if !span.from_expansion()
5201                && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id)
5202                && let Some(expr) = {
5203                    let mut finder = FindExprBySpan::new(span, self.tcx);
5204                    finder.visit_expr(body.value);
5205                    finder.result
5206                }
5207                && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, borrowed) =
5208                    expr.kind
5209                && let Some(amp_span) = borrowed
5210                    .span
5211                    .find_ancestor_inside_same_ctxt(expr.span)
5212                    .map(|borrowed_span| expr.span.until(borrowed_span))
5213                && self
5214                    .tcx
5215                    .sess
5216                    .source_map()
5217                    .span_to_snippet(amp_span)
5218                    .is_ok_and(|snippet| snippet.starts_with('&'))
5219            {
5220                err.span_suggestion_verbose(
5221                    amp_span,
5222                    "remove this reference",
5223                    "",
5224                    Applicability::MachineApplicable,
5225                );
5226                return;
5227            }
5228
5229            err.span_suggestion_verbose(
5230                obligation.cause.span.shrink_to_lo(),
5231                "dereference this index",
5232                '*',
5233                Applicability::MachineApplicable,
5234            );
5235        }
5236    }
5237
5238    fn note_function_argument_obligation(
5239        &self,
5240        body_def_id: LocalDefId,
5241        err: &mut Diag<'_>,
5242        arg_hir_id: HirId,
5243        parent_code: &ObligationCauseCode<'tcx>,
5244        param_env: ty::ParamEnv<'tcx>,
5245        failed_pred: ty::Predicate<'tcx>,
5246        call_hir_id: HirId,
5247    ) {
5248        let tcx = self.tcx;
5249        if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
5250            && let Some(typeck_results) = &self.typeck_results
5251        {
5252            if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr
5253                && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id)
5254                && let Some(failed_pred) = failed_pred.as_trait_clause()
5255                && let pred = failed_pred.map_bound(|pred| pred.with_replaced_self_ty(tcx, ty))
5256                && self.predicate_must_hold_modulo_regions(&Obligation::misc(
5257                    tcx,
5258                    expr.span,
5259                    body_def_id,
5260                    param_env,
5261                    pred,
5262                ))
5263                && expr.span.hi() != rcvr.span.hi()
5264            {
5265                let should_sugg = match tcx.hir_node(call_hir_id) {
5266                    Node::Expr(hir::Expr {
5267                        kind: hir::ExprKind::MethodCall(_, call_receiver, _, _),
5268                        ..
5269                    }) if let Some((DefKind::AssocFn, did)) =
5270                        typeck_results.type_dependent_def(call_hir_id)
5271                        && call_receiver.hir_id == arg_hir_id =>
5272                    {
5273                        // Avoid suggesting removing a method call if the argument is the receiver of the parent call and
5274                        // removing the receiver would make the method inaccessible. i.e. `x.a().b()`, suggesting removing
5275                        // `.a()` could change the type and make `.b()` unavailable.
5276                        if tcx.inherent_impl_of_assoc(did).is_some() {
5277                            // if we're calling an inherent impl method, just try to make sure that the receiver type stays the same.
5278                            Some(ty) == typeck_results.node_type_opt(arg_hir_id)
5279                        } else {
5280                            // we're calling a trait method, so we just check removing the method call still satisfies the trait.
5281                            let trait_id = tcx
5282                                .trait_of_assoc(did)
5283                                .unwrap_or_else(|| tcx.impl_trait_id(tcx.parent(did)));
5284                            let args = typeck_results.node_args(call_hir_id);
5285                            let tr = ty::TraitRef::from_assoc(tcx, trait_id, args)
5286                                .with_replaced_self_ty(tcx, ty);
5287                            self.type_implements_trait(tr.def_id, tr.args, param_env)
5288                                .must_apply_modulo_regions()
5289                        }
5290                    }
5291                    _ => true,
5292                };
5293
5294                if should_sugg {
5295                    err.span_suggestion_verbose(
5296                        expr.span.with_lo(rcvr.span.hi()),
5297                        ::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!(
5298                            "consider removing this method call, as the receiver has type `{ty}` and \
5299                            `{pred}` trivially holds",
5300                        ),
5301                        "",
5302                        Applicability::MaybeIncorrect,
5303                    );
5304                }
5305            }
5306            if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
5307                let inner_expr = expr.peel_blocks();
5308                let ty = typeck_results
5309                    .expr_ty_adjusted_opt(inner_expr)
5310                    .unwrap_or(Ty::new_misc_error(tcx));
5311                let span = inner_expr.span;
5312                if Some(span) != err.span.primary_span()
5313                    && !span.in_external_macro(tcx.sess.source_map())
5314                {
5315                    err.span_label(
5316                        span,
5317                        if ty.references_error() {
5318                            String::new()
5319                        } else {
5320                            let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
5321                            ::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}`")
5322                        },
5323                    );
5324                    if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
5325                        && let ty::ClauseKind::Trait(pred) = clause
5326                        && tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
5327                    {
5328                        if let [stmt, ..] = block.stmts
5329                            && let hir::StmtKind::Semi(value) = stmt.kind
5330                            && let hir::ExprKind::Closure(hir::Closure {
5331                                body, fn_decl_span, ..
5332                            }) = value.kind
5333                            && let body = tcx.hir_body(*body)
5334                            && !#[allow(non_exhaustive_omitted_patterns)] match body.value.kind {
    hir::ExprKind::Block(..) => true,
    _ => false,
}matches!(body.value.kind, hir::ExprKind::Block(..))
5335                        {
5336                            // Check if the failed predicate was an expectation of a closure type
5337                            // and if there might have been a `{ |args|` typo instead of `|args| {`.
5338                            err.multipart_suggestion(
5339                                "you might have meant to open the closure body instead of placing \
5340                                 a closure within a block",
5341                                ::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![
5342                                    (expr.span.with_hi(value.span.lo()), String::new()),
5343                                    (fn_decl_span.shrink_to_hi(), " {".to_string()),
5344                                ],
5345                                Applicability::MaybeIncorrect,
5346                            );
5347                        } else {
5348                            // Maybe the bare block was meant to be a closure.
5349                            err.span_suggestion_verbose(
5350                                expr.span.shrink_to_lo(),
5351                                "you might have meant to create the closure instead of a block",
5352                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("|{0}| ",
                (0..pred.trait_ref.args.len() -
                                        1).map(|_| "_").collect::<Vec<_>>().join(", ")))
    })format!(
5353                                    "|{}| ",
5354                                    (0..pred.trait_ref.args.len() - 1)
5355                                        .map(|_| "_")
5356                                        .collect::<Vec<_>>()
5357                                        .join(", ")
5358                                ),
5359                                Applicability::MaybeIncorrect,
5360                            );
5361                        }
5362                    }
5363                }
5364            }
5365
5366            // FIXME: visit the ty to see if there's any closure involved, and if there is,
5367            // check whether its evaluated return type is the same as the one corresponding
5368            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
5369            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
5370            let mut type_diffs = ::alloc::vec::Vec::new()vec![];
5371            if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = *parent_code
5372                && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
5373                && let where_clauses = self.tcx.clauses_of(def_id).instantiate(self.tcx, node_args)
5374                && let Some(where_pred) = where_clauses.clauses.get(idx)
5375            {
5376                let where_pred = where_pred.as_ref().skip_norm_wip();
5377                if let Some(where_pred) = where_pred.as_trait_clause()
5378                    && let Some(failed_pred) = failed_pred.as_trait_clause()
5379                    && where_pred.def_id() == failed_pred.def_id()
5380                {
5381                    self.enter_forall(where_pred, |where_pred| {
5382                        let failed_pred = self.instantiate_binder_with_fresh_vars(
5383                            expr.span,
5384                            BoundRegionConversionTime::FnCall,
5385                            failed_pred,
5386                        );
5387
5388                        let zipped =
5389                            iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
5390                        for (expected, actual) in zipped {
5391                            self.probe(|_| {
5392                                match self
5393                                    .at(&ObligationCause::misc(expr.span, body_def_id), param_env)
5394                                    // Doesn't actually matter if we define opaque types here, this is just used for
5395                                    // diagnostics, and the result is never kept around.
5396                                    .eq(DefineOpaqueTypes::Yes, expected, actual)
5397                                {
5398                                    Ok(_) => (), // We ignore nested obligations here for now.
5399                                    Err(err) => type_diffs.push(err),
5400                                }
5401                            })
5402                        }
5403                    })
5404                } else if let Some(where_pred) = where_pred.as_projection_clause()
5405                    && let Some(failed_pred) = failed_pred.as_projection_clause()
5406                    && let Some(found) =
5407                        failed_pred.map_bound(|pred| pred.term.as_type()).transpose().map(|term| {
5408                            self.instantiate_binder_with_fresh_vars(
5409                                expr.span,
5410                                BoundRegionConversionTime::FnCall,
5411                                term,
5412                            )
5413                        })
5414                {
5415                    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: self.instantiate_binder_with_fresh_vars(expr.span,
                                    BoundRegionConversionTime::FnCall,
                                    where_pred.map_bound(|pred|
                                            pred.projection_term)).expect_ty().to_ty(self.tcx,
                            ty::IsRigid::No),
                        found,
                    })]))vec![TypeError::Sorts(ty::error::ExpectedFound {
5416                        expected: self
5417                            .instantiate_binder_with_fresh_vars(
5418                                expr.span,
5419                                BoundRegionConversionTime::FnCall,
5420                                where_pred.map_bound(|pred| pred.projection_term),
5421                            )
5422                            .expect_ty()
5423                            .to_ty(self.tcx, ty::IsRigid::No),
5424                        found,
5425                    })];
5426                }
5427            }
5428            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
5429                && let hir::Path { res: Res::Local(hir_id), .. } = path
5430                && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
5431                && let hir::Node::LetStmt(local) = self.tcx.parent_hir_node(binding.hir_id)
5432                && let Some(binding_expr) = local.init
5433            {
5434                // If the expression we're calling on is a binding, we want to point at the
5435                // `let` when talking about the type. Otherwise we'll point at every part
5436                // of the method chain with the type.
5437                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
5438            } else {
5439                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
5440            }
5441        }
5442        let call_node = tcx.hir_node(call_hir_id);
5443        if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) =
5444            call_node
5445        {
5446            if Some(rcvr.span) == err.span.primary_span() {
5447                err.replace_span_with(path.ident.span, true);
5448            }
5449        }
5450
5451        if let Node::Expr(expr) = call_node {
5452            if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
5453            | hir::ExprKind::MethodCall(
5454                hir::PathSegment { ident: Ident { span, .. }, .. },
5455                ..,
5456            ) = expr.kind
5457            {
5458                if Some(*span) != err.span.primary_span() {
5459                    let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true })
5460                    {
5461                        "required by this formatting parameter"
5462                    } else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) {
5463                        "required by a formatting parameter in this expression"
5464                    } else {
5465                        "required by a bound introduced by this call"
5466                    };
5467                    err.span_label(*span, msg);
5468                }
5469            }
5470
5471            if let hir::ExprKind::MethodCall(_, expr, ..) = expr.kind {
5472                self.suggest_option_method_if_applicable(failed_pred, param_env, err, expr);
5473            }
5474        }
5475    }
5476
5477    fn suggest_option_method_if_applicable(
5478        &self,
5479        failed_pred: ty::Predicate<'tcx>,
5480        param_env: ty::ParamEnv<'tcx>,
5481        err: &mut Diag<'_>,
5482        expr: &hir::Expr<'_>,
5483    ) {
5484        let tcx = self.tcx;
5485        let infcx = self.infcx;
5486        let Some(typeck_results) = self.typeck_results.as_ref() else { return };
5487
5488        // Make sure we're dealing with the `Option` type.
5489        let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
5490            return;
5491        };
5492        if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
5493            return;
5494        }
5495
5496        // Given the predicate `fn(&T): FnOnce<(U,)>`, extract `fn(&T)` and `(U,)`,
5497        // then suggest `Option::as_deref(_mut)` if `U` can deref to `T`
5498        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitClause { trait_ref, .. }))
5499            = failed_pred.kind().skip_binder()
5500            && tcx.is_fn_trait(trait_ref.def_id)
5501            && let [self_ty, found_ty] = trait_ref.args.as_slice()
5502            && let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
5503            && let fn_sig @ ty::FnSig {
5504                ..
5505            } = fn_ty.fn_sig(tcx).skip_binder()
5506            // FIXME(splat): this might need to change if the Fn* traits start using/supporting splat
5507            && fn_sig.abi() == ExternAbi::Rust
5508            && !fn_sig.c_variadic()
5509            && fn_sig.safety() == hir::Safety::Safe
5510
5511            // Extract first param of fn sig with peeled refs, e.g. `fn(&T)` -> `T`
5512            && let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
5513            && !target_ty.has_escaping_bound_vars()
5514
5515            // Extract first tuple element out of fn trait, e.g. `FnOnce<(U,)>` -> `U`
5516            && let Some(ty::Tuple(tys)) = found_ty.as_type().map(Ty::kind)
5517            && let &[found_ty] = tys.as_slice()
5518            && !found_ty.has_escaping_bound_vars()
5519
5520            // Extract `<U as Deref>::Target` assoc type and check that it is `T`
5521            && let Some(deref_target_did) = tcx.lang_items().deref_target()
5522            && let projection = Ty::new_projection_from_args(tcx,ty::IsRigid::No, deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
5523            && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(Unnormalized::new_wip(projection))
5524            && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
5525            && infcx.can_eq(param_env, deref_target, target_ty)
5526        {
5527            let help = if let hir::Mutability::Mut = needs_mut
5528                && let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()
5529                && infcx
5530                    .type_implements_trait(deref_mut_did, iter::once(found_ty), param_env)
5531                    .must_apply_modulo_regions()
5532            {
5533                Some(("call `Option::as_deref_mut()` first", ".as_deref_mut()"))
5534            } else if let hir::Mutability::Not = needs_mut {
5535                Some(("call `Option::as_deref()` first", ".as_deref()"))
5536            } else {
5537                None
5538            };
5539
5540            if let Some((msg, sugg)) = help {
5541                err.span_suggestion_with_style(
5542                    expr.span.shrink_to_hi(),
5543                    msg,
5544                    sugg,
5545                    Applicability::MaybeIncorrect,
5546                    SuggestionStyle::ShowAlways,
5547                );
5548            }
5549        }
5550    }
5551
5552    fn look_for_iterator_item_mistakes(
5553        &self,
5554        assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
5555        typeck_results: &TypeckResults<'tcx>,
5556        type_diffs: &[TypeError<'tcx>],
5557        param_env: ty::ParamEnv<'tcx>,
5558        path_segment: &hir::PathSegment<'_>,
5559        args: &[hir::Expr<'_>],
5560        prev_ty: Ty<'_>,
5561        err: &mut Diag<'_>,
5562    ) {
5563        let tcx = self.tcx;
5564        // Special case for iterator chains, we look at potential failures of `Iterator::Item`
5565        // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`.
5566        for entry in assocs_in_this_method {
5567            let Some((_span, (def_id, ty))) = entry else {
5568                continue;
5569            };
5570            for diff in type_diffs {
5571                let TypeError::Sorts(expected_found) = diff else {
5572                    continue;
5573                };
5574                if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
5575                    && path_segment.ident.name == sym::iter
5576                    && self.can_eq(
5577                        param_env,
5578                        Ty::new_ref(
5579                            tcx,
5580                            tcx.lifetimes.re_erased,
5581                            expected_found.found,
5582                            ty::Mutability::Not,
5583                        ),
5584                        *ty,
5585                    )
5586                    && let [] = args
5587                {
5588                    // Used `.iter()` when `.into_iter()` was likely meant.
5589                    err.span_suggestion_verbose(
5590                        path_segment.ident.span,
5591                        ::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`"),
5592                        "into_iter".to_string(),
5593                        Applicability::MachineApplicable,
5594                    );
5595                }
5596                if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
5597                    && path_segment.ident.name == sym::into_iter
5598                    && self.can_eq(
5599                        param_env,
5600                        expected_found.found,
5601                        Ty::new_ref(tcx, tcx.lifetimes.re_erased, *ty, ty::Mutability::Not),
5602                    )
5603                    && let [] = args
5604                {
5605                    // Used `.into_iter()` when `.iter()` was likely meant.
5606                    err.span_suggestion_verbose(
5607                        path_segment.ident.span,
5608                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider not consuming the `{0}` to construct the `Iterator`",
                prev_ty))
    })format!(
5609                            "consider not consuming the `{prev_ty}` to construct the `Iterator`"
5610                        ),
5611                        "iter".to_string(),
5612                        Applicability::MachineApplicable,
5613                    );
5614                }
5615                if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
5616                    && path_segment.ident.name == sym::map
5617                    && self.can_eq(param_env, expected_found.found, *ty)
5618                    && let [arg] = args
5619                    && let hir::ExprKind::Closure(closure) = arg.kind
5620                {
5621                    let body = tcx.hir_body(closure.body);
5622                    if let hir::ExprKind::Block(block, None) = body.value.kind
5623                        && let None = block.expr
5624                        && let [.., stmt] = block.stmts
5625                        && let hir::StmtKind::Semi(expr) = stmt.kind
5626                        // FIXME: actually check the expected vs found types, but right now
5627                        // the expected is a projection that we need to resolve.
5628                        // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
5629                        && expected_found.found.is_unit()
5630                        // FIXME: this happens with macro calls. Need to figure out why the stmt
5631                        // `println!();` doesn't include the `;` in its `Span`. (#133845)
5632                        // We filter these out to avoid ICEs with debug assertions on caused by
5633                        // empty suggestions.
5634                        && expr.span.hi() != stmt.span.hi()
5635                    {
5636                        err.span_suggestion_verbose(
5637                            expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
5638                            "consider removing this semicolon",
5639                            String::new(),
5640                            Applicability::MachineApplicable,
5641                        );
5642                    }
5643                    let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
5644                        && let Some(expr) = block.expr
5645                    {
5646                        expr
5647                    } else {
5648                        body.value
5649                    };
5650                    if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
5651                        && path_segment.ident.name == sym::clone
5652                        && let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
5653                        && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
5654                        && self.can_eq(param_env, expr_ty, rcvr_ty)
5655                        && let ty::Ref(_, ty, _) = expr_ty.kind()
5656                    {
5657                        err.span_label(
5658                            span,
5659                            ::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!(
5660                                "this method call is cloning the reference `{expr_ty}`, not \
5661                                 `{ty}` which doesn't implement `Clone`",
5662                            ),
5663                        );
5664                        let ty::Param(..) = ty.kind() else {
5665                            continue;
5666                        };
5667                        let node =
5668                            tcx.hir_node_by_def_id(tcx.hir_get_parent_item(expr.hir_id).def_id);
5669
5670                        let pred = ty::Binder::dummy(ty::TraitClause {
5671                            trait_ref: ty::TraitRef::new(
5672                                tcx,
5673                                tcx.require_lang_item(LangItem::Clone, span),
5674                                [*ty],
5675                            ),
5676                            polarity: ty::ClausePolarity::Positive,
5677                        });
5678                        let Some(generics) = node.generics() else {
5679                            continue;
5680                        };
5681                        let Some(body_id) = node.body_id() else {
5682                            continue;
5683                        };
5684                        suggest_restriction(
5685                            tcx,
5686                            tcx.hir_body_owner_def_id(body_id),
5687                            generics,
5688                            &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("type parameter `{0}`", ty))
    })format!("type parameter `{ty}`"),
5689                            err,
5690                            node.fn_sig(),
5691                            None,
5692                            pred,
5693                            None,
5694                        );
5695                    }
5696                }
5697            }
5698        }
5699    }
5700
5701    fn point_at_chain(
5702        &self,
5703        expr: &hir::Expr<'_>,
5704        typeck_results: &TypeckResults<'tcx>,
5705        type_diffs: Vec<TypeError<'tcx>>,
5706        param_env: ty::ParamEnv<'tcx>,
5707        err: &mut Diag<'_>,
5708    ) {
5709        let mut primary_spans = ::alloc::vec::Vec::new()vec![];
5710        let mut span_labels = ::alloc::vec::Vec::new()vec![];
5711
5712        let tcx = self.tcx;
5713
5714        let mut print_root_expr = true;
5715        let mut assocs = ::alloc::vec::Vec::new()vec![];
5716        let mut expr = expr;
5717        let mut prev_ty = self.deeply_resolve_ignoring_regions(
5718            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
5719        );
5720        while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {
5721            // Point at every method call in the chain with the resulting type.
5722            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
5723            //               ^^^^^^ ^^^^^^^^^^^
5724            expr = rcvr_expr;
5725            let assocs_in_this_method =
5726                self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
5727            prev_ty = self.deeply_resolve_ignoring_regions(
5728                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
5729            );
5730            self.look_for_iterator_item_mistakes(
5731                &assocs_in_this_method,
5732                typeck_results,
5733                &type_diffs,
5734                param_env,
5735                path_segment,
5736                args,
5737                prev_ty,
5738                err,
5739            );
5740            assocs.push(assocs_in_this_method);
5741
5742            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
5743                && let hir::Path { res: Res::Local(hir_id), .. } = path
5744                && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
5745            {
5746                let parent = self.tcx.parent_hir_node(binding.hir_id);
5747                // We've reached the root of the method call chain...
5748                if let hir::Node::LetStmt(local) = parent
5749                    && let Some(binding_expr) = local.init
5750                {
5751                    // ...and it is a binding. Get the binding creation and continue the chain.
5752                    expr = binding_expr;
5753                }
5754                if let hir::Node::Param(param) = parent {
5755                    // ...and it is an fn argument.
5756                    let prev_ty = self.deeply_resolve_ignoring_regions(
5757                        typeck_results
5758                            .node_type_opt(param.hir_id)
5759                            .unwrap_or(Ty::new_misc_error(tcx)),
5760                    );
5761                    let assocs_in_this_method = self.probe_assoc_types_at_expr(
5762                        &type_diffs,
5763                        param.ty_span,
5764                        prev_ty,
5765                        param.hir_id,
5766                        param_env,
5767                    );
5768                    if assocs_in_this_method.iter().any(|a| a.is_some()) {
5769                        assocs.push(assocs_in_this_method);
5770                        print_root_expr = false;
5771                    }
5772                    break;
5773                }
5774            }
5775        }
5776        // We want the type before deref coercions, otherwise we talk about `&[_]`
5777        // instead of `Vec<_>`.
5778        if let Some(ty) = typeck_results.expr_ty_opt(expr)
5779            && print_root_expr
5780        {
5781            let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
5782            // Point at the root expression
5783            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
5784            // ^^^^^^^^^^^^^
5785            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}`")));
5786        };
5787        // Only show this if it is not a "trivial" expression (not a method
5788        // chain) and there are associated types to talk about.
5789        let mut assocs = assocs.into_iter().peekable();
5790        while let Some(assocs_in_method) = assocs.next() {
5791            let Some(prev_assoc_in_method) = assocs.peek() else {
5792                for entry in assocs_in_method {
5793                    let Some((span, (assoc, ty))) = entry else {
5794                        continue;
5795                    };
5796                    if primary_spans.is_empty()
5797                        || type_diffs.iter().any(|diff| {
5798                            let TypeError::Sorts(expected_found) = diff else {
5799                                return false;
5800                            };
5801                            self.can_eq(param_env, expected_found.found, ty)
5802                        })
5803                    {
5804                        // FIXME: this doesn't quite work for `Iterator::collect`
5805                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
5806                        // to point at the `.into_iter()` call, but as long as we
5807                        // still point at the other method calls that might have
5808                        // introduced the issue, this is fine for now.
5809                        primary_spans.push(span);
5810                    }
5811                    span_labels.push((
5812                        span,
5813                        {
    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!(
5814                            "`{}` is `{ty}` here",
5815                            self.tcx.def_path_str(assoc),
5816                        )),
5817                    ));
5818                }
5819                break;
5820            };
5821            for (entry, prev_entry) in
5822                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
5823            {
5824                match (entry, prev_entry) {
5825                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
5826                        let ty_str = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
5827
5828                        let assoc = { let _guard = ForceTrimmedGuard::new(); self.tcx.def_path_str(assoc) }with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
5829                        if !self.can_eq(param_env, ty, *prev_ty) {
5830                            if type_diffs.iter().any(|diff| {
5831                                let TypeError::Sorts(expected_found) = diff else {
5832                                    return false;
5833                                };
5834                                self.can_eq(param_env, expected_found.found, ty)
5835                            }) {
5836                                primary_spans.push(span);
5837                            }
5838                            span_labels
5839                                .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")));
5840                        } else {
5841                            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")));
5842                        }
5843                    }
5844                    (Some((span, (assoc, ty))), None) => {
5845                        span_labels.push((
5846                            span,
5847                            {
    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!(
5848                                "`{}` is `{}` here",
5849                                self.tcx.def_path_str(assoc),
5850                                self.ty_to_string(ty),
5851                            )),
5852                        ));
5853                    }
5854                    (None, Some(_)) | (None, None) => {}
5855                }
5856            }
5857        }
5858        if !primary_spans.is_empty() {
5859            let mut multi_span: MultiSpan = primary_spans.into();
5860            for (span, label) in span_labels {
5861                multi_span.push_span_label(span, label);
5862            }
5863            err.span_note(
5864                multi_span,
5865                "the method call chain might not have had the expected associated types",
5866            );
5867        }
5868    }
5869
5870    fn probe_assoc_types_at_expr(
5871        &self,
5872        type_diffs: &[TypeError<'tcx>],
5873        span: Span,
5874        prev_ty: Ty<'tcx>,
5875        body_id: HirId,
5876        param_env: ty::ParamEnv<'tcx>,
5877    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
5878        let ocx = ObligationCtxt::new(self.infcx);
5879        let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
5880        for diff in type_diffs {
5881            let TypeError::Sorts(expected_found) = diff else {
5882                continue;
5883            };
5884            let &ty::Alias(_, ty::AliasTy { kind: kind @ ty::Projection { def_id }, .. }) =
5885                expected_found.expected.kind()
5886            else {
5887                continue;
5888            };
5889
5890            // Make `Self` be equivalent to the type of the call chain
5891            // expression we're looking at now, so that we can tell what
5892            // for example `Iterator::Item` is at this point in the chain.
5893            let args = GenericArgs::for_item(self.tcx, def_id, |param, _| {
5894                if param.index == 0 {
5895                    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 { .. });
5896                    return prev_ty.into();
5897                }
5898                self.var_for_def(span, param)
5899            });
5900            // This will hold the resolved type of the associated type, if the
5901            // current expression implements the trait that associated type is
5902            // in. For example, this would be what `Iterator::Item` is here.
5903            let ty = self.infcx.next_ty_var(span);
5904            // This corresponds to `<ExprTy as Iterator>::Item = _`.
5905            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
5906                ty::ClauseKind::Projection(ty::ProjectionClause {
5907                    projection_term: ty::AliasTerm::new_from_args(self.tcx, kind.into(), args),
5908                    term: ty.into(),
5909                }),
5910            ));
5911            let body_def_id = self.tcx.hir_enclosing_body_owner(body_id);
5912            // Add `<ExprTy as Iterator>::Item = _` obligation.
5913            ocx.register_obligation(Obligation::misc(
5914                self.tcx,
5915                span,
5916                body_def_id,
5917                param_env,
5918                projection,
5919            ));
5920            if ocx.try_evaluate_obligations().no_errors()
5921                && let ty = self.deeply_resolve_ignoring_regions(ty)
5922                && !ty.is_ty_var()
5923            {
5924                assocs_in_this_method.push(Some((span, (def_id, ty))));
5925            } else {
5926                // `<ExprTy as Iterator>` didn't select, so likely we've
5927                // reached the end of the iterator chain, like the originating
5928                // `Vec<_>` or the `ty` couldn't be determined.
5929                // Keep the space consistent for later zipping.
5930                assocs_in_this_method.push(None);
5931            }
5932        }
5933        assocs_in_this_method
5934    }
5935
5936    /// When a `-> impl Trait<Assoc = Ty>` return type obligation fails, walk the method call
5937    /// chain in the returned expression to point at where the associated type diverged from
5938    /// what the signature expects.
5939    ///
5940    /// ```text
5941    /// note: the method call chain might not have had the expected associated types
5942    ///   --> $DIR/invalid-iterator-chain-in-return-position.rs:16:18
5943    ///    |
5944    /// LL |     x.iter_mut().map(foo)
5945    ///    |     - ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here
5946    ///    |     | |
5947    ///    |     | `Iterator::Item` is `&mut Vec<u8>` here
5948    ///    |     this expression has type `Vec<Vec<u8>>`
5949    /// ```
5950    fn point_at_chain_in_return_position(
5951        &self,
5952        body_def_id: LocalDefId,
5953        expr: &hir::Expr<'_>,
5954        typeck_results: &TypeckResults<'tcx>,
5955        param_env: ty::ParamEnv<'tcx>,
5956        err: &mut Diag<'_>,
5957    ) {
5958        let tcx = self.tcx;
5959        if !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(body_def_id) {
    DefKind::Fn | DefKind::AssocFn => true,
    _ => false,
}matches!(tcx.def_kind(body_def_id), DefKind::Fn | DefKind::AssocFn) {
5960            return;
5961        }
5962
5963        let binder = tcx.fn_sig(body_def_id).instantiate_identity().skip_norm_wip().output();
5964        self.enter_forall(binder, |output| {
5965            let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, args, .. }) =
5966                output.kind()
5967            else {
5968                return;
5969            };
5970
5971            // The predicate that reaches here has been rewritten through the impls it was
5972            // derived from (e.g. `Iterator for Map<I, F>` turns `Iterator::Item` requirements
5973            // into requirements on `F`'s return type), so the associated types the user wrote
5974            // in the signature are recovered from the opaque's bounds instead.
5975            let mut probe_diffs = ::alloc::vec::Vec::new()vec![];
5976            for clause in tcx.item_bounds(opaque_def_id).instantiate(tcx, args).skip_norm_wip() {
5977                let Some(proj) = clause.as_projection_clause() else { continue };
5978                let proj = self.instantiate_binder_with_fresh_vars(
5979                    expr.span,
5980                    BoundRegionConversionTime::FnCall,
5981                    proj,
5982                );
5983                let Some(expected_term) = proj.term.as_type() else { continue };
5984                // Only the projection (for its `DefId`) is used when probing the chain; the
5985                // bound's own term is carried in `found` for the divergence check below and
5986                // is replaced with the probed type afterwards.
5987                probe_diffs.push(TypeError::Sorts(ty::error::ExpectedFound {
5988                    expected: proj.projection_term.expect_ty().to_ty(tcx, ty::IsRigid::No),
5989                    found: expected_term,
5990                }));
5991            }
5992            if probe_diffs.is_empty() {
5993                return;
5994            }
5995
5996            // If the returned expression is a binding, walk the chain that created it instead.
5997            let expr = if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
5998                && let hir::Path { res: Res::Local(hir_id), .. } = path
5999                && let hir::Node::Pat(binding) = tcx.hir_node(*hir_id)
6000                && let hir::Node::LetStmt(local) = tcx.parent_hir_node(binding.hir_id)
6001                && let Some(binding_expr) = local.init
6002            {
6003                binding_expr
6004            } else {
6005                expr
6006            };
6007
6008            // Resolve what each bound associated type actually is for the returned expression,
6009            // and keep only the ones that diverged from the signature.
6010            let expr_ty = self.deeply_resolve_ignoring_regions(
6011                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
6012            );
6013            let assocs = self.probe_assoc_types_at_expr(
6014                &probe_diffs,
6015                expr.span,
6016                expr_ty,
6017                expr.hir_id,
6018                param_env,
6019            );
6020            let mut type_diffs = ::alloc::vec::Vec::new()vec![];
6021            for (probe_diff, assoc) in iter::zip(probe_diffs, assocs) {
6022                let TypeError::Sorts(ty::error::ExpectedFound { expected, found: expected_term }) =
6023                    probe_diff
6024                else {
6025                    continue;
6026                };
6027                let Some((_, (_, actual_ty))) = assoc else { continue };
6028                if !self.can_eq(param_env, expected_term, actual_ty) {
6029                    type_diffs.push(TypeError::Sorts(ty::error::ExpectedFound {
6030                        expected,
6031                        found: actual_ty,
6032                    }));
6033                }
6034            }
6035            if !type_diffs.is_empty() {
6036                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
6037            }
6038        });
6039    }
6040
6041    /// If the type that failed selection is an array or a reference to an array,
6042    /// but the trait is implemented for slices, suggest that the user converts
6043    /// the array into a slice.
6044    pub(super) fn suggest_convert_to_slice(
6045        &self,
6046        err: &mut Diag<'_>,
6047        obligation: &PredicateObligation<'tcx>,
6048        trait_pred: ty::PolyTraitClause<'tcx>,
6049        candidate_impls: &[ImplCandidate<'tcx>],
6050        span: Span,
6051    ) {
6052        if span.in_external_macro(self.tcx.sess.source_map()) {
6053            return;
6054        }
6055        // We can only suggest the slice coercion for function and binary operation arguments,
6056        // since the suggestion would make no sense in turbofish or call
6057        let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
6058            obligation.cause.code()
6059        else {
6060            return;
6061        };
6062
6063        // Three cases where we can make a suggestion:
6064        // 1. `[T; _]` (array of T)
6065        // 2. `&[T; _]` (reference to array of T)
6066        // 3. `&mut [T; _]` (mutable reference to array of T)
6067        let (element_ty, mut mutability) = match *trait_pred.skip_binder().self_ty().kind() {
6068            ty::Array(element_ty, _) => (element_ty, None),
6069
6070            ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() {
6071                ty::Array(element_ty, _) => (element_ty, Some(mutability)),
6072                _ => return,
6073            },
6074
6075            _ => return,
6076        };
6077
6078        // Go through all the candidate impls to see if any of them is for
6079        // slices of `element_ty` with `mutability`.
6080        let mut is_slice = |candidate: Ty<'tcx>| match *candidate.kind() {
6081            ty::RawPtr(t, m) | ty::Ref(_, t, m) => {
6082                if let ty::Slice(e) = *t.kind()
6083                    && e == element_ty
6084                    && m == mutability.unwrap_or(m)
6085                {
6086                    // Use the candidate's mutability going forward.
6087                    mutability = Some(m);
6088                    true
6089                } else {
6090                    false
6091                }
6092            }
6093            _ => false,
6094        };
6095
6096        // Grab the first candidate that matches, if any, and make a suggestion.
6097        if let Some(slice_ty) = candidate_impls
6098            .iter()
6099            .map(|trait_ref| trait_ref.trait_ref.self_ty())
6100            .find(|t| is_slice(*t))
6101        {
6102            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");
6103
6104            if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
6105                let mut suggestions = ::alloc::vec::Vec::new()vec![];
6106                if snippet.starts_with('&') {
6107                } else if let Some(hir::Mutability::Mut) = mutability {
6108                    suggestions.push((span.shrink_to_lo(), "&mut ".into()));
6109                } else {
6110                    suggestions.push((span.shrink_to_lo(), "&".into()));
6111                }
6112                suggestions.push((span.shrink_to_hi(), "[..]".into()));
6113                err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
6114            } else {
6115                err.span_help(span, msg);
6116            }
6117        }
6118    }
6119
6120    /// If the type failed selection but the trait is implemented for `(T,)`, suggest that the user
6121    /// creates a unary tuple
6122    ///
6123    /// This is a common gotcha when using libraries that emulate variadic functions with traits for tuples.
6124    pub(super) fn suggest_tuple_wrapping(
6125        &self,
6126        err: &mut Diag<'_>,
6127        root_obligation: &PredicateObligation<'tcx>,
6128        obligation: &PredicateObligation<'tcx>,
6129    ) {
6130        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else {
6131            return;
6132        };
6133
6134        let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return };
6135
6136        let trait_ref = root_pred.map_bound(|root_pred| {
6137            root_pred.trait_ref.with_replaced_self_ty(
6138                self.tcx,
6139                Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()]),
6140            )
6141        });
6142
6143        let obligation =
6144            Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref);
6145
6146        if self.predicate_must_hold_modulo_regions(&obligation) {
6147            let arg_span = self.tcx.hir_span(*arg_hir_id);
6148            err.multipart_suggestion(
6149                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use a unary tuple instead"))
    })format!("use a unary tuple instead"),
6150                ::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())],
6151                Applicability::MaybeIncorrect,
6152            );
6153        }
6154    }
6155
6156    pub(super) fn suggest_shadowed_inherent_method(
6157        &self,
6158        err: &mut Diag<'_>,
6159        obligation: &PredicateObligation<'tcx>,
6160        trait_predicate: ty::PolyTraitClause<'tcx>,
6161    ) {
6162        let ObligationCauseCode::FunctionArg { call_hir_id, .. } = obligation.cause.code() else {
6163            return;
6164        };
6165        let Node::Expr(call) = self.tcx.hir_node(*call_hir_id) else { return };
6166        let hir::ExprKind::MethodCall(segment, rcvr, args, ..) = call.kind else { return };
6167        let Some(typeck) = &self.typeck_results else { return };
6168        let Some(rcvr_ty) = typeck.expr_ty_adjusted_opt(rcvr) else { return };
6169        let rcvr_ty = self.deeply_resolve_ignoring_regions(rcvr_ty);
6170        let autoderef = (self.autoderef_steps)(rcvr_ty);
6171        for (ty, def_id) in autoderef.iter().filter_map(|(ty, obligations)| {
6172            if let ty::Adt(def, _) = ty.kind()
6173                && *ty != rcvr_ty.peel_refs()
6174                && obligations.iter().all(|obligation| self.predicate_may_hold(obligation))
6175            {
6176                Some((ty, def.did()))
6177            } else {
6178                None
6179            }
6180        }) {
6181            for impl_def_id in self.tcx.inherent_impls(def_id) {
6182                if *impl_def_id == trait_predicate.def_id() {
6183                    continue;
6184                }
6185                for m in self
6186                    .tcx
6187                    .provided_trait_methods(*impl_def_id)
6188                    .filter(|m| m.name() == segment.ident.name)
6189                {
6190                    let fn_sig = self.tcx.fn_sig(m.def_id);
6191                    if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 {
6192                        continue;
6193                    }
6194                    let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder();
6195                    let (mutability, _ty) = match rcvr_ty.kind() {
6196                        ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty),
6197                        ty::Ref(_, ty, _) => ("&", ty),
6198                        _ => ("", &rcvr_ty),
6199                    };
6200                    let path = self.tcx.def_path_str(def_id);
6201                    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!(
6202                        "there's an inherent method on `{ty}` of the same name, which can be \
6203                         auto-dereferenced from `{rcvr_ty}`"
6204                    ));
6205                    err.multipart_suggestion(
6206                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("to access the inherent method on `{0}`, use the fully-qualified path",
                ty))
    })format!(
6207                            "to access the inherent method on `{ty}`, use the fully-qualified path",
6208                        ),
6209                        ::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![
6210                            (
6211                                call.span.until(rcvr.span),
6212                                format!("{path}::{}({}", m.name(), mutability),
6213                            ),
6214                            match &args {
6215                                [] => (
6216                                    rcvr.span.shrink_to_hi().with_hi(call.span.hi()),
6217                                    ")".to_string(),
6218                                ),
6219                                [first, ..] => (rcvr.span.between(first.span), ", ".to_string()),
6220                            },
6221                        ],
6222                        Applicability::MaybeIncorrect,
6223                    );
6224                }
6225            }
6226        }
6227    }
6228
6229    pub(super) fn explain_hrtb_projection(
6230        &self,
6231        diag: &mut Diag<'_>,
6232        pred: ty::PolyTraitClause<'tcx>,
6233        param_env: ty::ParamEnv<'tcx>,
6234        cause: &ObligationCause<'tcx>,
6235    ) {
6236        if pred.skip_binder().has_escaping_bound_vars() && pred.skip_binder().has_non_region_infer()
6237        {
6238            self.probe(|_| {
6239                let ocx = ObligationCtxt::new(self);
6240                ocx.register_obligation(Obligation::new(
6241                    self.tcx,
6242                    ObligationCause::dummy(),
6243                    param_env,
6244                    pred,
6245                ));
6246                if !ocx.try_evaluate_obligations().no_errors() {
6247                    // encountered errors.
6248                    return;
6249                }
6250
6251                if let ObligationCauseCode::FunctionArg {
6252                    call_hir_id,
6253                    arg_hir_id,
6254                    parent_code: _,
6255                } = cause.code()
6256                {
6257                    let arg_span = self.tcx.hir_span(*arg_hir_id);
6258                    let mut sp: MultiSpan = arg_span.into();
6259
6260                    sp.push_span_label(
6261                        arg_span,
6262                        "the trait solver is unable to infer the \
6263                        generic types that should be inferred from this argument",
6264                    );
6265                    sp.push_span_label(
6266                        self.tcx.hir_span(*call_hir_id),
6267                        "add turbofish arguments to this call to \
6268                        specify the types manually, even if it's redundant",
6269                    );
6270                    diag.span_note(
6271                        sp,
6272                        "this is a known limitation of the trait solver that \
6273                        will be lifted in the future",
6274                    );
6275                } else {
6276                    let mut sp: MultiSpan = cause.span.into();
6277                    sp.push_span_label(
6278                        cause.span,
6279                        "try adding turbofish arguments to this expression to \
6280                        specify the types manually, even if it's redundant",
6281                    );
6282                    diag.span_note(
6283                        sp,
6284                        "this is a known limitation of the trait solver that \
6285                        will be lifted in the future",
6286                    );
6287                }
6288            });
6289        }
6290    }
6291
6292    pub(super) fn suggest_desugaring_async_fn_in_trait(
6293        &self,
6294        err: &mut Diag<'_>,
6295        trait_pred: ty::PolyTraitClause<'tcx>,
6296    ) {
6297        // Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
6298        if self.tcx.features().return_type_notation() {
6299            return;
6300        }
6301
6302        let trait_def_id = trait_pred.def_id();
6303
6304        // Only suggest specifying auto traits
6305        if !self.tcx.trait_is_auto(trait_def_id) {
6306            return;
6307        }
6308
6309        // Look for an RPITIT
6310        let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) =
6311            trait_pred.self_ty().skip_binder().kind()
6312        else {
6313            return;
6314        };
6315        let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
6316            self.tcx.opt_rpitit_info(*def_id)
6317        else {
6318            return;
6319        };
6320
6321        let auto_trait = self.tcx.def_path_str(trait_def_id);
6322        // ... which is a local function
6323        let Some(fn_def_id) = fn_def_id.as_local() else {
6324            // If it's not local, we can at least mention that the method is async, if it is.
6325            if self.tcx.asyncness(fn_def_id).is_async() {
6326                err.span_note(
6327                    self.tcx.def_span(fn_def_id),
6328                    ::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!(
6329                        "`{}::{}` is an `async fn` in trait, which does not \
6330                    automatically imply that its future is `{auto_trait}`",
6331                        alias_ty.trait_ref(self.tcx),
6332                        self.tcx.item_name(fn_def_id)
6333                    ),
6334                );
6335            }
6336            return;
6337        };
6338        let hir::Node::TraitItem(item) = self.tcx.hir_node_by_def_id(fn_def_id) else {
6339            return;
6340        };
6341
6342        // ... whose signature is `async` (i.e. this is an AFIT)
6343        let (sig, body) = item.expect_fn();
6344        let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(opaq_def, ..), .. }) =
6345            sig.decl.output
6346        else {
6347            // This should never happen, but let's not ICE.
6348            return;
6349        };
6350
6351        // Check that this is *not* a nested `impl Future` RPIT in an async fn
6352        // (i.e. `async fn foo() -> impl Future`)
6353        if opaq_def.def_id.to_def_id() != opaque_def_id {
6354            return;
6355        }
6356
6357        let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait(
6358            self.tcx,
6359            *sig,
6360            *body,
6361            opaque_def_id.expect_local(),
6362            &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}", auto_trait))
    })format!(" + {auto_trait}"),
6363        ) else {
6364            return;
6365        };
6366
6367        let function_name = self.tcx.def_path_str(fn_def_id);
6368        err.multipart_suggestion(
6369            ::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!(
6370                "`{auto_trait}` can be made part of the associated future's \
6371                guarantees for all implementations of `{function_name}`"
6372            ),
6373            sugg,
6374            Applicability::MachineApplicable,
6375        );
6376    }
6377
6378    pub fn ty_kind_suggestion(
6379        &self,
6380        param_env: ty::ParamEnv<'tcx>,
6381        ty: Ty<'tcx>,
6382    ) -> Option<String> {
6383        let tcx = self.infcx.tcx;
6384        let implements_default = |ty| {
6385            let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
6386                return false;
6387            };
6388            self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
6389        };
6390
6391        Some(match *ty.kind() {
6392            ty::Never | ty::Error(_) => return None,
6393            ty::Bool => "false".to_string(),
6394            ty::Char => "\'x\'".to_string(),
6395            ty::Int(_) | ty::Uint(_) => "42".into(),
6396            ty::Float(_) => "3.14159".into(),
6397            ty::Slice(_) => "[]".to_string(),
6398            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
6399                "vec![]".to_string()
6400            }
6401            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
6402                "String::new()".to_string()
6403            }
6404            ty::Adt(def, args) if def.is_box() => {
6405                ::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())?)
6406            }
6407            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
6408                "None".to_string()
6409            }
6410            ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
6411                ::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())?)
6412            }
6413            ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
6414            ty::Ref(_, ty, mutability) => {
6415                if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
6416                    "\"\"".to_string()
6417                } else {
6418                    let ty = self.ty_kind_suggestion(param_env, ty)?;
6419                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("&{0}{1}", mutability.prefix_str(),
                ty))
    })format!("&{}{ty}", mutability.prefix_str())
6420                }
6421            }
6422            ty::Array(ty, len) if let Some(len) = len.try_to_target_usize(tcx) => {
6423                if len == 0 {
6424                    "[]".to_string()
6425                } else if self.type_is_copy_modulo_regions(param_env, ty) || len == 1 {
6426                    // Can only suggest `[ty; 0]` if sz == 1 or copy
6427                    ::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)
6428                } else {
6429                    "/* value */".to_string()
6430                }
6431            }
6432            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!(
6433                "({}{})",
6434                tys.iter()
6435                    .map(|ty| self.ty_kind_suggestion(param_env, ty))
6436                    .collect::<Option<Vec<String>>>()?
6437                    .join(", "),
6438                if tys.len() == 1 { "," } else { "" }
6439            ),
6440            _ => "/* value */".to_string(),
6441        })
6442    }
6443
6444    // For E0277 when use `?` operator, suggest adding
6445    // a suitable return type in `FnSig`, and a default
6446    // return value at the end of the function's body.
6447    pub(super) fn suggest_add_result_as_return_type(
6448        &self,
6449        obligation: &PredicateObligation<'tcx>,
6450        err: &mut Diag<'_>,
6451        trait_pred: ty::PolyTraitClause<'tcx>,
6452    ) {
6453        if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
6454            return;
6455        }
6456
6457        // Only suggest for local function and associated method,
6458        // because this suggest adding both return type in
6459        // the `FnSig` and a default return value in the body, so it
6460        // is not suitable for foreign function without a local body,
6461        // and neither for trait method which may be also implemented
6462        // in other place, so shouldn't change it's FnSig.
6463        fn choose_suggest_items<'tcx, 'hir>(
6464            tcx: TyCtxt<'tcx>,
6465            node: hir::Node<'hir>,
6466        ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
6467            match node {
6468                hir::Node::Item(item)
6469                    if let hir::ItemKind::Fn { sig, body: body_id, .. } = item.kind =>
6470                {
6471                    Some((sig.decl, body_id))
6472                }
6473                hir::Node::ImplItem(item)
6474                    if let hir::ImplItemKind::Fn(sig, body_id) = item.kind =>
6475                {
6476                    let parent = tcx.parent_hir_node(item.hir_id());
6477                    if let hir::Node::Item(item) = parent
6478                        && let hir::ItemKind::Impl(imp) = item.kind
6479                        && imp.of_trait.is_none()
6480                    {
6481                        return Some((sig.decl, body_id));
6482                    }
6483                    None
6484                }
6485                _ => None,
6486            }
6487        }
6488
6489        let node = self.tcx.hir_node_by_def_id(obligation.cause.body_def_id);
6490        if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node)
6491            && let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output
6492            && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
6493            && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
6494            && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
6495            && self.tcx.is_diagnostic_item(sym::Result, def.did())
6496        {
6497            let mut sugg_spans =
6498                ::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())];
6499            let body = self.tcx.hir_body(body_id);
6500            if let hir::ExprKind::Block(b, _) = body.value.kind
6501                && b.expr.is_none()
6502            {
6503                // The span of '}' in the end of block.
6504                let span = self.tcx.sess.source_map().end_point(b.span);
6505                sugg_spans.push((
6506                    span.shrink_to_lo(),
6507                    ::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!(
6508                        "{}{}",
6509                        "    Ok(())\n",
6510                        self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(),
6511                    ),
6512                ));
6513            }
6514            err.multipart_suggestion(
6515                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider adding return type"))
    })format!("consider adding return type"),
6516                sugg_spans,
6517                Applicability::MaybeIncorrect,
6518            );
6519        }
6520    }
6521
6522    {}
#[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("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(6522u32),
                                    ::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_all(&[]) })
                } 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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:6542",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(6542u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("pred")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("pred");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("item_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("item_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("span");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pred)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&item_def_id)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:6555",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(6555u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("generics.params")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("generics.params");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&generics.params)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:6556",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(6556u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("generics.predicates")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("generics.predicates");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&generics.predicates)
                                                        as &dyn ::tracing::field::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 /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:6569",
                                    "rustc_trait_selection::error_reporting::traits::suggestions",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                                    ::tracing_core::__macro_support::Option::Some(6569u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("param")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("param");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param)
                                                        as &dyn ::tracing::field::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)]
6523    pub(super) fn suggest_unsized_bound_if_applicable(
6524        &self,
6525        err: &mut Diag<'_>,
6526        obligation: &PredicateObligation<'tcx>,
6527    ) {
6528        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
6529            obligation.predicate.kind().skip_binder()
6530        else {
6531            return;
6532        };
6533        let (ObligationCauseCode::WhereClause(item_def_id, span)
6534        | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)) =
6535            *obligation.cause.code().peel_derives()
6536        else {
6537            return;
6538        };
6539        if span.is_dummy() {
6540            return;
6541        }
6542        debug!(?pred, ?item_def_id, ?span);
6543
6544        let (Some(node), true) = (
6545            self.tcx.hir_get_if_local(item_def_id),
6546            self.tcx.is_lang_item(pred.def_id(), LangItem::Sized),
6547        ) else {
6548            return;
6549        };
6550
6551        let Some(generics) = node.generics() else {
6552            return;
6553        };
6554        let sized_trait = self.tcx.lang_items().sized_trait();
6555        debug!(?generics.params);
6556        debug!(?generics.predicates);
6557        let Some(param) = generics.params.iter().find(|param| param.span == span) else {
6558            return;
6559        };
6560        // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
6561        // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
6562        let explicitly_sized = generics
6563            .bounds_for_param(param.def_id)
6564            .flat_map(|bp| bp.bounds)
6565            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
6566        if explicitly_sized {
6567            return;
6568        }
6569        debug!(?param);
6570        match node {
6571            hir::Node::Item(
6572                item @ hir::Item {
6573                    // Only suggest indirection for uses of type parameters in ADTs.
6574                    kind:
6575                        hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
6576                    ..
6577                },
6578            ) => {
6579                if self.suggest_indirection_for_unsized(err, item, param) {
6580                    return;
6581                }
6582            }
6583            _ => {}
6584        };
6585
6586        // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
6587        let (span, separator, open_paren_sp) =
6588            if let Some((s, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
6589                (s, " +", open_paren_sp)
6590            } else {
6591                (param.name.ident().span.shrink_to_hi(), ":", None)
6592            };
6593
6594        let mut suggs = vec![];
6595        let suggestion = format!("{separator} ?Sized");
6596
6597        if let Some(open_paren_sp) = open_paren_sp {
6598            suggs.push((open_paren_sp, "(".to_string()));
6599            suggs.push((span, format!("){suggestion}")));
6600        } else {
6601            suggs.push((span, suggestion));
6602        }
6603
6604        err.multipart_suggestion(
6605            "consider relaxing the implicit `Sized` restriction",
6606            suggs,
6607            Applicability::MachineApplicable,
6608        );
6609    }
6610
6611    fn suggest_indirection_for_unsized(
6612        &self,
6613        err: &mut Diag<'_>,
6614        item: &hir::Item<'tcx>,
6615        param: &hir::GenericParam<'tcx>,
6616    ) -> bool {
6617        // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
6618        // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
6619        // is not. Look for invalid "bare" parameter uses, and suggest using indirection.
6620        let mut visitor = FindTypeParam { param: param.name.ident().name, .. };
6621        visitor.visit_item(item);
6622        if visitor.invalid_spans.is_empty() {
6623            return false;
6624        }
6625        let mut multispan: MultiSpan = param.span.into();
6626        multispan.push_span_label(
6627            param.span,
6628            ::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()),
6629        );
6630        for sp in visitor.invalid_spans {
6631            multispan.push_span_label(
6632                sp,
6633                ::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()),
6634            );
6635        }
6636        err.span_help(
6637            multispan,
6638            ::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!(
6639                "you could relax the implicit `Sized` bound on `{T}` if it were \
6640                used through indirection like `&{T}` or `Box<{T}>`",
6641                T = param.name.ident(),
6642            ),
6643        );
6644        true
6645    }
6646    pub(crate) fn suggest_swapping_lhs_and_rhs<T>(
6647        &self,
6648        err: &mut Diag<'_>,
6649        predicate: T,
6650        param_env: ty::ParamEnv<'tcx>,
6651        cause_code: &ObligationCauseCode<'tcx>,
6652    ) where
6653        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
6654    {
6655        let tcx = self.tcx;
6656        let predicate = predicate.upcast(tcx);
6657        match *cause_code {
6658            ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, rhs_span, .. }
6659                if let Some(typeck_results) = &self.typeck_results
6660                    && let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id)
6661                    && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id)
6662                    && let Some(lhs_ty) = typeck_results.expr_ty_opt(lhs)
6663                    && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) =>
6664            {
6665                if let Some(pred) = predicate.as_trait_clause()
6666                    && tcx.is_lang_item(pred.def_id(), LangItem::PartialEq)
6667                    && self
6668                        .infcx
6669                        .type_implements_trait(pred.def_id(), [rhs_ty, lhs_ty], param_env)
6670                        .must_apply_modulo_regions()
6671                {
6672                    let lhs_span = tcx.hir_span(lhs_hir_id);
6673                    let sm = tcx.sess.source_map();
6674                    if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_span)
6675                        && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_span)
6676                    {
6677                        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}>`"));
6678                        err.multipart_suggestion(
6679                            "consider swapping the equality",
6680                            ::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)],
6681                            Applicability::MaybeIncorrect,
6682                        );
6683                    }
6684                }
6685            }
6686            _ => {}
6687        }
6688    }
6689
6690    /// Checks whether the field independently satisfies the trait bound, ignoring
6691    /// the specific generic parameter that caused the original E0277 error.
6692    fn is_truly_imperfect_derive(
6693        &self,
6694        parent_trait_pred: ty::PolyTraitClause<'tcx>,
6695        predicate: ty::Predicate<'tcx>,
6696        param_env: ty::ParamEnv<'tcx>,
6697    ) -> bool {
6698        let tcx = self.tcx;
6699        let ty::Adt(adt_def, parent_args) = parent_trait_pred.skip_binder().self_ty().kind() else {
6700            return false;
6701        };
6702        let Some(trait_clause) = predicate.as_trait_clause() else {
6703            return false;
6704        };
6705        let failing_ty = trait_clause.skip_binder().self_ty();
6706        let trait_def_id = parent_trait_pred.def_id();
6707
6708        let failing_adt_param_indices: FxHashSet<u32> = parent_args
6709            .iter()
6710            .enumerate()
6711            .filter_map(|(idx, arg)| {
6712                if let Some(t) = arg.as_type()
6713                    && t == failing_ty
6714                {
6715                    Some(idx as u32)
6716                } else {
6717                    None
6718                }
6719            })
6720            .collect();
6721
6722        if failing_adt_param_indices.is_empty() {
6723            return false;
6724        }
6725
6726        adt_def.all_fields().all(|field| {
6727            let raw_field_ty = tcx.type_of(field.did).skip_binder();
6728            // If the field type is exactly one of the failing parameters, it is not an imperfect derive.
6729            if let ty::Param(p) = raw_field_ty.kind()
6730                && failing_adt_param_indices.contains(&p.index)
6731            {
6732                return false;
6733            }
6734            // If the field type doesn't mention the parameter at all, it's independent.
6735            if !raw_field_ty.walk().any(|arg| {
6736                #[allow(non_exhaustive_omitted_patterns)] match arg.as_type().map(|t|
            t.kind()) {
    Some(ty::Param(p)) if failing_adt_param_indices.contains(&p.index) =>
        true,
    _ => false,
}matches!(arg.as_type().map(|t| t.kind()), Some(ty::Param(p)) if failing_adt_param_indices.contains(&p.index))
6737            }) {
6738                return true;
6739            }
6740
6741            self.probe(|_| {
6742                // We keep the generic parameters that didn't fail as-is from the parent args,
6743                // but replace the ones that did fail with fresh inference variable placeholders.
6744                let fresh_args = ty::GenericArgs::for_item(tcx, adt_def.did(), |param, _| {
6745                    if failing_adt_param_indices.contains(&param.index) {
6746                        self.var_for_def(DUMMY_SP, param)
6747                    } else {
6748                        parent_args[param.index as usize]
6749                    }
6750                });
6751
6752                let field_ty = field.ty(tcx, fresh_args).skip_norm_wip();
6753                // Substitute the field's type for the bound's `Self` type to check whether
6754                // the field alone would satisfy the trait, independent of other generics.
6755                let parent_trait_args = parent_trait_pred.skip_binder().trait_ref.args;
6756                let trait_args = parent_trait_args.iter().map(|arg| {
6757                    if arg.as_type() == Some(parent_trait_pred.skip_binder().self_ty()) {
6758                        field_ty.into()
6759                    } else {
6760                        arg
6761                    }
6762                });
6763                let obligation = Obligation::new(
6764                    tcx,
6765                    ObligationCause::dummy(),
6766                    param_env,
6767                    ty::TraitRef::new(tcx, trait_def_id, trait_args),
6768                );
6769                self.predicate_may_hold(&obligation)
6770            })
6771        })
6772    }
6773}
6774
6775/// Add a hint to add a missing borrow or remove an unnecessary one.
6776fn hint_missing_borrow<'tcx>(
6777    infcx: &InferCtxt<'tcx>,
6778    param_env: ty::ParamEnv<'tcx>,
6779    span: Span,
6780    found: Ty<'tcx>,
6781    expected: Ty<'tcx>,
6782    found_node: Node<'_>,
6783    err: &mut Diag<'_>,
6784) {
6785    if #[allow(non_exhaustive_omitted_patterns)] match found_node {
    Node::TraitItem(..) => true,
    _ => false,
}matches!(found_node, Node::TraitItem(..)) {
6786        return;
6787    }
6788
6789    let found_args = match found.kind() {
6790        ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
6791        kind => {
6792            ::rustc_span::macros::bug_impl(Some(span),
    format_args!("found was converted to a FnPtr above but is now {0:?}",
        kind), Location::caller())span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
6793        }
6794    };
6795    let expected_args = match expected.kind() {
6796        ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
6797        kind => {
6798            ::rustc_span::macros::bug_impl(Some(span),
    format_args!("expected was converted to a FnPtr above but is now {0:?}",
        kind), Location::caller())span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
6799        }
6800    };
6801
6802    // This could be a variant constructor, for example.
6803    let Some(fn_decl) = found_node.fn_decl() else {
6804        return;
6805    };
6806
6807    let args = fn_decl.inputs.iter();
6808
6809    let mut to_borrow = Vec::new();
6810    let mut remove_borrow = Vec::new();
6811
6812    for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
6813        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
6814        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
6815
6816        if infcx.can_eq(param_env, found_ty, expected_ty) {
6817            // FIXME: This could handle more exotic cases like mutability mismatches too!
6818            if found_refs.len() < expected_refs.len()
6819                && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]
6820            {
6821                to_borrow.push((
6822                    arg.span.shrink_to_lo(),
6823                    expected_refs[..expected_refs.len() - found_refs.len()]
6824                        .iter()
6825                        .map(|mutbl| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("&{0}", mutbl.prefix_str()))
    })format!("&{}", mutbl.prefix_str()))
6826                        .collect::<Vec<_>>()
6827                        .join(""),
6828                ));
6829            } else if found_refs.len() > expected_refs.len() {
6830                let mut span = arg.span.shrink_to_lo();
6831                let mut left = found_refs.len() - expected_refs.len();
6832                let mut ty = arg;
6833                while let hir::TyKind::Ref(_, mut_ty) = &ty.kind
6834                    && left > 0
6835                {
6836                    span = span.with_hi(mut_ty.ty.span.lo());
6837                    ty = mut_ty.ty;
6838                    left -= 1;
6839                }
6840                if left == 0 {
6841                    remove_borrow.push((span, String::new()));
6842                }
6843            }
6844        }
6845    }
6846
6847    if !to_borrow.is_empty() {
6848        err.subdiagnostic(diagnostics::AdjustSignatureBorrow::Borrow { to_borrow });
6849    }
6850
6851    if !remove_borrow.is_empty() {
6852        err.subdiagnostic(diagnostics::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
6853    }
6854}
6855
6856/// Collect all the paths that reference `Self`.
6857/// Used to suggest replacing associated types with an explicit type in `where` clauses.
6858#[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)]
6859pub struct SelfVisitor<'v> {
6860    pub paths: Vec<&'v hir::Ty<'v>> = Vec::new(),
6861    pub name: Option<Symbol>,
6862}
6863
6864impl<'v> Visitor<'v> for SelfVisitor<'v> {
6865    fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
6866        if let hir::TyKind::Path(path) = ty.kind
6867            && let hir::QPath::TypeRelative(inner_ty, segment) = path
6868            && (Some(segment.ident.name) == self.name || self.name.is_none())
6869            && let hir::TyKind::Path(inner_path) = inner_ty.kind
6870            && let hir::QPath::Resolved(None, inner_path) = inner_path
6871            && let Res::SelfTyAlias { .. } = inner_path.res
6872        {
6873            self.paths.push(ty.as_unambig_ty());
6874        }
6875        hir::intravisit::walk_ty(self, ty);
6876    }
6877}
6878
6879/// Collect all the returned expressions within the input expression.
6880/// Used to point at the return spans when we want to suggest some change to them.
6881#[derive(#[automatically_derived]
impl<'v> ::core::default::Default for ReturnsVisitor<'v> {
    #[inline]
    fn default() -> Self {
        Self {
            returns: ::core::default::Default::default(),
            in_block_tail: ::core::default::Default::default(),
        }
    }
}Default)]
6882pub struct ReturnsVisitor<'v> {
6883    pub returns: Vec<&'v hir::Expr<'v>>,
6884    in_block_tail: bool,
6885}
6886
6887impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
6888    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
6889        // Visit every expression to detect `return` paths, either through the function's tail
6890        // expression or `return` statements. We walk all nodes to find `return` statements, but
6891        // we only care about tail expressions when `in_block_tail` is `true`, which means that
6892        // they're in the return path of the function body.
6893        match ex.kind {
6894            hir::ExprKind::Ret(Some(ex)) => {
6895                self.returns.push(ex);
6896            }
6897            hir::ExprKind::Block(block, _) if self.in_block_tail => {
6898                self.in_block_tail = false;
6899                for stmt in block.stmts {
6900                    hir::intravisit::walk_stmt(self, stmt);
6901                }
6902                self.in_block_tail = true;
6903                if let Some(expr) = block.expr {
6904                    self.visit_expr(expr);
6905                }
6906            }
6907            hir::ExprKind::If(_, then, else_opt) if self.in_block_tail => {
6908                self.visit_expr(then);
6909                if let Some(el) = else_opt {
6910                    self.visit_expr(el);
6911                }
6912            }
6913            hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
6914                for arm in arms {
6915                    self.visit_expr(arm.body);
6916                }
6917            }
6918            // We need to walk to find `return`s in the entire body.
6919            _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
6920            _ => self.returns.push(ex),
6921        }
6922    }
6923
6924    fn visit_body(&mut self, body: &hir::Body<'v>) {
6925        if !!self.in_block_tail {
    ::core::panicking::panic("assertion failed: !self.in_block_tail")
};assert!(!self.in_block_tail);
6926        self.in_block_tail = true;
6927        hir::intravisit::walk_body(self, body);
6928    }
6929}
6930
6931/// Collect all the awaited expressions within the input expression.
6932#[derive(#[automatically_derived]
impl ::core::default::Default for AwaitsVisitor {
    #[inline]
    fn default() -> Self {
        Self { awaits: ::core::default::Default::default() }
    }
}Default)]
6933struct AwaitsVisitor {
6934    awaits: Vec<HirId>,
6935}
6936
6937impl<'v> Visitor<'v> for AwaitsVisitor {
6938    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
6939        if let hir::ExprKind::Yield(_, hir::YieldSource::Await { expr: Some(id) }) = ex.kind {
6940            self.awaits.push(id)
6941        }
6942        hir::intravisit::walk_expr(self, ex)
6943    }
6944}
6945
6946/// Suggest a new type parameter name for diagnostic purposes.
6947///
6948/// `name` is the preferred name you'd like to suggest if it's not in use already.
6949pub trait NextTypeParamName {
6950    fn next_type_param_name(&self, name: Option<&str>) -> String;
6951}
6952
6953impl NextTypeParamName for &[hir::GenericParam<'_>] {
6954    fn next_type_param_name(&self, name: Option<&str>) -> String {
6955        // Type names are usually single letters in uppercase. So convert the first letter of input string to uppercase.
6956        let name = name.and_then(|n| n.chars().next()).map(|c| c.to_uppercase().to_string());
6957        let name = name.as_deref();
6958
6959        // This is the list of possible parameter names that we might suggest.
6960        let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
6961
6962        // Filter out used names based on `filter_fn`.
6963        let used_names: Vec<Symbol> = self
6964            .iter()
6965            .filter_map(|param| match param.name {
6966                hir::ParamName::Plain(ident) => Some(ident.name),
6967                _ => None,
6968            })
6969            .collect();
6970
6971        // Find a name from `possible_names` that is not in `used_names`.
6972        possible_names
6973            .iter()
6974            .find(|n| !used_names.contains(&Symbol::intern(n)))
6975            .unwrap_or(&"ParamName")
6976            .to_string()
6977    }
6978}
6979
6980/// Collect the spans that we see the generic param `param_did`
6981struct ReplaceImplTraitVisitor<'a> {
6982    ty_spans: &'a mut Vec<Span>,
6983    param_did: DefId,
6984}
6985
6986impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
6987    fn visit_ty(&mut self, t: &'hir hir::Ty<'hir, AmbigArg>) {
6988        if let hir::TyKind::Path(hir::QPath::Resolved(
6989            None,
6990            hir::Path { res: Res::Def(_, segment_did), .. },
6991        )) = t.kind
6992        {
6993            if self.param_did == *segment_did {
6994                // `fn foo(t: impl Trait)`
6995                //            ^^^^^^^^^^ get this to suggest `T` instead
6996
6997                // There might be more than one `impl Trait`.
6998                self.ty_spans.push(t.span);
6999                return;
7000            }
7001        }
7002
7003        hir::intravisit::walk_ty(self, t);
7004    }
7005}
7006
7007pub(super) fn get_explanation_based_on_obligation<'tcx>(
7008    tcx: TyCtxt<'tcx>,
7009    obligation: &PredicateObligation<'tcx>,
7010    trait_predicate: ty::PolyTraitClause<'tcx>,
7011    pre_message: String,
7012    long_ty_path: &mut Option<PathBuf>,
7013) -> String {
7014    if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
7015        "consider using `()`, or a `Result`".to_owned()
7016    } else {
7017        let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
7018            ty::FnDef(_, _) => Some("fn item"),
7019            ty::Closure(_, _) => Some("closure"),
7020            _ => None,
7021        };
7022
7023        let desc = match ty_desc {
7024            Some(desc) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" {0}", desc))
    })format!(" {desc}"),
7025            None => String::new(),
7026        };
7027        if let ty::ClausePolarity::Positive = trait_predicate.polarity() {
7028            // If the trait in question is unstable, mention that fact in the diagnostic.
7029            // But if we're building with `-Zforce-unstable-if-unmarked` then _any_ trait
7030            // not explicitly marked stable is considered unstable, so the extra text is
7031            // unhelpful noise. See <https://github.com/rust-lang/rust/issues/152692>.
7032            let mention_unstable = !tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
7033                && try { tcx.lookup_stability(trait_predicate.def_id())?.level.is_stable() }
7034                    == Some(false);
7035            let unstable = if mention_unstable { "nightly-only, unstable " } else { "" };
7036
7037            ::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!(
7038                "{pre_message}the {unstable}trait `{}` is not implemented for{desc} `{}`",
7039                trait_predicate.print_modifiers_and_trait_path(),
7040                tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path),
7041            )
7042        } else {
7043            // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
7044            // not implemented for `T`".
7045            // FIXME: add note explaining explicit negative trait bounds.
7046            ::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")
7047        }
7048    }
7049}
7050
7051// Replace `param` with `replace_ty`
7052struct ReplaceImplTraitFolder<'tcx> {
7053    tcx: TyCtxt<'tcx>,
7054    param: &'tcx ty::GenericParamDef,
7055    replace_ty: Ty<'tcx>,
7056}
7057
7058impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
7059    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
7060        if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
7061            if self.param.index == *index {
7062                return self.replace_ty;
7063            }
7064        }
7065        t.super_fold_with(self)
7066    }
7067
7068    fn cx(&self) -> TyCtxt<'tcx> {
7069        self.tcx
7070    }
7071}
7072
7073pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
7074    tcx: TyCtxt<'tcx>,
7075    sig: hir::FnSig<'tcx>,
7076    body: hir::TraitFn<'tcx>,
7077    opaque_def_id: LocalDefId,
7078    add_bounds: &str,
7079) -> Option<Vec<(Span, String)>> {
7080    let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
7081        return None;
7082    };
7083    let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span);
7084
7085    let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
7086    let [hir::GenericBound::Trait(trait_ref)] = future.bounds else {
7087        // `async fn` should always lower to a single bound... but don't ICE.
7088        return None;
7089    };
7090    let Some(hir::PathSegment { args: Some(args), .. }) = trait_ref.trait_ref.path.segments.last()
7091    else {
7092        // desugaring to a single path segment for `Future<...>`.
7093        return None;
7094    };
7095    let Some(future_output_ty) = args.constraints.first().and_then(|constraint| constraint.ty())
7096    else {
7097        // Also should never happen.
7098        return None;
7099    };
7100
7101    let mut sugg = if future_output_ty.span.is_empty() {
7102        ::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![
7103            (async_span, String::new()),
7104            (
7105                future_output_ty.span,
7106                format!(" -> impl std::future::Future<Output = ()>{add_bounds}"),
7107            ),
7108        ]
7109    } else {
7110        ::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![
7111            (future_output_ty.span.shrink_to_lo(), "impl std::future::Future<Output = ".to_owned()),
7112            (future_output_ty.span.shrink_to_hi(), format!(">{add_bounds}")),
7113            (async_span, String::new()),
7114        ]
7115    };
7116
7117    // If there's a body, we also need to wrap it in `async {}`
7118    if let hir::TraitFn::Provided(body) = body {
7119        let body = tcx.hir_body(body);
7120        let body_span = body.value.span;
7121        let body_span_without_braces =
7122            body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
7123        if body_span_without_braces.is_empty() {
7124            sugg.push((body_span_without_braces, " async {} ".to_owned()));
7125        } else {
7126            sugg.extend([
7127                (body_span_without_braces.shrink_to_lo(), "async {".to_owned()),
7128                (body_span_without_braces.shrink_to_hi(), "} ".to_owned()),
7129            ]);
7130        }
7131    }
7132
7133    Some(sugg)
7134}
7135
7136/// On `impl` evaluation cycles, look for `Self::AssocTy` restrictions in `where` clauses, explain
7137/// they are not allowed and if possible suggest alternatives.
7138fn point_at_assoc_type_restriction(
7139    tcx: TyCtxt<'_>,
7140    err: &mut Diag<'_>,
7141    self_ty_str: &str,
7142    trait_name: &str,
7143    predicate: ty::Predicate<'_>,
7144    generics: &hir::Generics<'_>,
7145    data: &ImplDerivedCause<'_>,
7146) {
7147    let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() else {
7148        return;
7149    };
7150    let ty::ClauseKind::Projection(proj) = clause else {
7151        return;
7152    };
7153    let Some(name) = tcx
7154        .opt_rpitit_info(proj.def_id())
7155        .and_then(|data| match data {
7156            ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => Some(tcx.item_name(fn_def_id)),
7157            ty::ImplTraitInTraitData::Impl { .. } => None,
7158        })
7159        .or_else(|| tcx.opt_item_name(proj.def_id()))
7160    else {
7161        return;
7162    };
7163    let mut predicates = generics.predicates.iter().peekable();
7164    let mut prev: Option<(&hir::WhereBoundPredicate<'_>, Span)> = None;
7165    while let Some(pred) = predicates.next() {
7166        let curr_span = pred.span;
7167        let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
7168            continue;
7169        };
7170        let mut bounds = pred.bounds.iter();
7171        while let Some(bound) = bounds.next() {
7172            let Some(trait_ref) = bound.trait_ref() else {
7173                continue;
7174            };
7175            if bound.span() != data.span {
7176                continue;
7177            }
7178            if let hir::TyKind::Path(path) = pred.bounded_ty.kind
7179                && let hir::QPath::TypeRelative(ty, segment) = path
7180                && segment.ident.name == name
7181                && let hir::TyKind::Path(inner_path) = ty.kind
7182                && let hir::QPath::Resolved(None, inner_path) = inner_path
7183                && let Res::SelfTyAlias { .. } = inner_path.res
7184            {
7185                // The following block is to determine the right span to delete for this bound
7186                // that will leave valid code after the suggestion is applied.
7187                let span = if pred.origin == hir::PredicateOrigin::WhereClause
7188                    && generics
7189                        .predicates
7190                        .iter()
7191                        .filter(|p| {
7192                            #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    hir::WherePredicateKind::BoundPredicate(p) if
        hir::PredicateOrigin::WhereClause == p.origin => true,
    _ => false,
}matches!(
7193                                p.kind,
7194                                hir::WherePredicateKind::BoundPredicate(p)
7195                                if hir::PredicateOrigin::WhereClause == p.origin
7196                            )
7197                        })
7198                        .count()
7199                        == 1
7200                {
7201                    // There's only one `where` bound, that needs to be removed. Remove the whole
7202                    // `where` clause.
7203                    generics.where_clause_span
7204                } else if let Some(next_pred) = predicates.peek()
7205                    && let hir::WherePredicateKind::BoundPredicate(next) = next_pred.kind
7206                    && pred.origin == next.origin
7207                {
7208                    // There's another bound, include the comma for the current one.
7209                    curr_span.until(next_pred.span)
7210                } else if let Some((prev, prev_span)) = prev
7211                    && pred.origin == prev.origin
7212                {
7213                    // Last bound, try to remove the previous comma.
7214                    prev_span.shrink_to_hi().to(curr_span)
7215                } else if pred.origin == hir::PredicateOrigin::WhereClause {
7216                    curr_span.with_hi(generics.where_clause_span.hi())
7217                } else {
7218                    curr_span
7219                };
7220
7221                err.span_suggestion_verbose(
7222                    span,
7223                    "associated type for the current `impl` cannot be restricted in `where` \
7224                     clauses, remove this bound",
7225                    "",
7226                    Applicability::MaybeIncorrect,
7227                );
7228            }
7229            if let Some(new) =
7230                tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind(
7231                    tcx,
7232                    Ident::with_dummy_span(name),
7233                    ty::AssocTag::Type,
7234                    data.impl_or_alias_def_id,
7235                )
7236            {
7237                // The associated type is specified in the `impl` we're
7238                // looking at. Point at it.
7239                let span = tcx.def_span(new.def_id);
7240                err.span_label(
7241                    span,
7242                    ::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!(
7243                        "associated type `<{self_ty_str} as {trait_name}>::{name}` is specified \
7244                         here",
7245                    ),
7246                );
7247                // Search for the associated type `Self::{name}`, get
7248                // its type and suggest replacing the bound with it.
7249                let mut visitor = SelfVisitor { name: Some(name), .. };
7250                visitor.visit_trait_ref(trait_ref);
7251                for path in visitor.paths {
7252                    err.span_suggestion_verbose(
7253                        path.span,
7254                        "replace the associated type with the type specified in this `impl`",
7255                        tcx.type_of(new.def_id).skip_binder(),
7256                        Applicability::MachineApplicable,
7257                    );
7258                }
7259            } else {
7260                let mut visitor = SelfVisitor { name: None, .. };
7261                visitor.visit_trait_ref(trait_ref);
7262                let span: MultiSpan =
7263                    visitor.paths.iter().map(|p| p.span).collect::<Vec<Span>>().into();
7264                err.span_note(
7265                    span,
7266                    "associated types for the current `impl` cannot be restricted in `where` \
7267                     clauses",
7268                );
7269            }
7270        }
7271        prev = Some((pred, curr_span));
7272    }
7273}
7274
7275fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, Vec<hir::Mutability>) {
7276    let mut refs = ::alloc::vec::Vec::new()vec![];
7277
7278    while let ty::Ref(_, new_ty, mutbl) = ty.kind() {
7279        ty = *new_ty;
7280        refs.push(*mutbl);
7281    }
7282
7283    (ty, refs)
7284}
7285
7286/// Look for type `param` in an ADT being used only through a reference to confirm that suggesting
7287/// `param: ?Sized` would be a valid constraint.
7288struct FindTypeParam {
7289    param: rustc_span::Symbol,
7290    invalid_spans: Vec<Span> = Vec::new(),
7291    nested: bool = false,
7292}
7293
7294impl<'v> Visitor<'v> for FindTypeParam {
7295    fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
7296        // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
7297    }
7298
7299    fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
7300        // We collect the spans of all uses of the "bare" type param, like in `field: T` or
7301        // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
7302        // valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized`
7303        // obligations like `Box<T>` and `Vec<T>`, but we perform no extra analysis for those cases
7304        // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors
7305        // in that case should make what happened clear enough.
7306        match ty.kind {
7307            hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {}
7308            hir::TyKind::Path(hir::QPath::Resolved(None, path))
7309                if let [segment] = path.segments
7310                    && segment.ident.name == self.param =>
7311            {
7312                if !self.nested {
7313                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs:7313",
                        "rustc_trait_selection::error_reporting::traits::suggestions",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
                        ::tracing_core::__macro_support::Option::Some(7313u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("ty")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("ty");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("FindTypeParam::visit_ty")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?ty, "FindTypeParam::visit_ty");
7314                    self.invalid_spans.push(ty.span);
7315                }
7316            }
7317            hir::TyKind::Path(_) => {
7318                let prev = self.nested;
7319                self.nested = true;
7320                hir::intravisit::walk_ty(self, ty);
7321                self.nested = prev;
7322            }
7323            _ => {
7324                hir::intravisit::walk_ty(self, ty);
7325            }
7326        }
7327    }
7328}
7329
7330/// Look for type parameters in predicates. We use this to identify whether a bound is suitable in
7331/// on a given item.
7332struct ParamFinder {
7333    params: Vec<Symbol> = Vec::new(),
7334}
7335
7336impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamFinder {
7337    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
7338        match t.kind() {
7339            ty::Param(p) => self.params.push(p.name),
7340            _ => {}
7341        }
7342        t.super_visit_with(self)
7343    }
7344}
7345
7346impl ParamFinder {
7347    /// Whether the `hir::Generics` of the current item can suggest the evaluated bound because its
7348    /// references to type parameters are present in the generics.
7349    fn can_suggest_bound(&self, generics: &hir::Generics<'_>) -> bool {
7350        if self.params.is_empty() {
7351            // There are no references to type parameters at all, so suggesting the bound
7352            // would be reasonable.
7353            return true;
7354        }
7355        generics.params.iter().any(|p| match p.name {
7356            hir::ParamName::Plain(p_name) => {
7357                // All of the parameters in the bound can be referenced in the current item.
7358                self.params.iter().any(|p| *p == p_name.name || *p == kw::SelfUpper)
7359            }
7360            _ => true,
7361        })
7362    }
7363}