Skip to main content

rustc_trait_selection/error_reporting/infer/
region.rs

1use std::iter;
2
3use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
4use rustc_errors::{
5    Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, msg, struct_span_code_err,
6};
7use rustc_hir::def::{DefKind, Namespace};
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::intravisit::Visitor;
10use rustc_hir::{self as hir, GenericParamKind, ParamName};
11use rustc_middle::hir::nested_filter;
12use rustc_middle::middle::resolve_bound_vars as rbv;
13use rustc_middle::traits::ObligationCauseCode;
14use rustc_middle::ty::error::TypeError;
15use rustc_middle::ty::print::RegionHighlightMode;
16use rustc_middle::ty::{
17    self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _,
18};
19use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, bug, kw, sym};
20use tracing::{debug, instrument};
21
22use super::ObligationCauseAsDiagArg;
23use super::nice_region_error::find_anon_type;
24use crate::diagnostics::{
25    self, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
26    RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, note_and_explain,
27};
28use crate::error_reporting::TypeErrCtxt;
29use crate::error_reporting::infer::ObligationCauseExt;
30use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
31use crate::infer::region_constraints::GenericKind;
32use crate::infer::{
33    BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin,
34    SubregionOrigin,
35};
36
37impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
38    pub fn report_region_errors(
39        &self,
40        generic_param_scope: LocalDefId,
41        errors: &[RegionResolutionError<'tcx>],
42    ) -> ErrorGuaranteed {
43        if !!errors.is_empty() {
    ::core::panicking::panic("assertion failed: !errors.is_empty()")
};assert!(!errors.is_empty());
44
45        if let Some(guaranteed) = self.infcx.tainted_by_errors() {
46            return guaranteed;
47        }
48
49        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:49",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(49u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_region_errors(): {0} errors to start",
                                                    errors.len()) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_region_errors(): {} errors to start", errors.len());
50
51        // try to pre-process the errors, which will group some of them
52        // together into a `ProcessedErrors` group:
53        let errors = self.process_errors(errors);
54
55        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:55",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(55u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_region_errors: {0} errors after preprocessing",
                                                    errors.len()) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_region_errors: {} errors after preprocessing", errors.len());
56
57        let mut guar = None;
58        for error in errors {
59            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:59",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(59u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_region_errors: error = {0:?}",
                                                    error) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_region_errors: error = {:?}", error);
60
61            let e = if let Some(guar) =
62                self.try_report_nice_region_error(generic_param_scope, &error)
63            {
64                guar
65            } else {
66                match error.clone() {
67                    // These errors could indicate all manner of different
68                    // problems with many different solutions. Rather
69                    // than generate a "one size fits all" error, what we
70                    // attempt to do is go through a number of specific
71                    // scenarios and try to find the best way to present
72                    // the error. If all of these fails, we fall back to a rather
73                    // general bit of code that displays the error information
74                    RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
75                        if sub.is_placeholder() || sup.is_placeholder() {
76                            self.report_placeholder_failure(generic_param_scope, origin, sub, sup)
77                                .emit_err()
78                        } else {
79                            self.report_concrete_failure(generic_param_scope, origin, sub, sup)
80                                .emit_err()
81                        }
82                    }
83
84                    RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => self
85                        .report_generic_bound_failure(
86                            generic_param_scope,
87                            origin.span(),
88                            Some(origin),
89                            param_ty,
90                            sub,
91                        ),
92
93                    RegionResolutionError::SubSupConflict(
94                        _,
95                        var_origin,
96                        sub_origin,
97                        sub_r,
98                        sup_origin,
99                        sup_r,
100                        _,
101                    ) => {
102                        if sub_r.is_placeholder() {
103                            self.report_placeholder_failure(
104                                generic_param_scope,
105                                sub_origin,
106                                sub_r,
107                                sup_r,
108                            )
109                            .emit_err()
110                        } else if sup_r.is_placeholder() {
111                            self.report_placeholder_failure(
112                                generic_param_scope,
113                                sup_origin,
114                                sub_r,
115                                sup_r,
116                            )
117                            .emit_err()
118                        } else {
119                            self.report_sub_sup_conflict(
120                                generic_param_scope,
121                                var_origin,
122                                sub_origin,
123                                sub_r,
124                                sup_origin,
125                                sup_r,
126                            )
127                        }
128                    }
129
130                    RegionResolutionError::UpperBoundUniverseConflict(
131                        _,
132                        _,
133                        _,
134                        sup_origin,
135                        sup_r,
136                    ) => {
137                        if !sup_r.is_placeholder() {
    ::core::panicking::panic("assertion failed: sup_r.is_placeholder()")
};assert!(sup_r.is_placeholder());
138
139                        // Make a dummy value for the "sub region" --
140                        // this is the initial value of the
141                        // placeholder. In practice, we expect more
142                        // tailored errors that don't really use this
143                        // value.
144                        let sub_r = self.tcx.lifetimes.re_erased;
145
146                        self.report_placeholder_failure(
147                            generic_param_scope,
148                            sup_origin,
149                            sub_r,
150                            sup_r,
151                        )
152                        .emit_err()
153                    }
154
155                    RegionResolutionError::CannotNormalize(clause, origin) => {
156                        let clause: ty::Clause<'tcx> =
157                            clause.map_bound(ty::ClauseKind::TypeOutlives).upcast(self.tcx);
158                        self.tcx
159                            .dcx()
160                            .struct_span_err(origin.span(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot normalize `{0}`", clause))
    })format!("cannot normalize `{clause}`"))
161                            .emit_err()
162                    }
163                }
164            };
165
166            guar = Some(e)
167        }
168
169        guar.unwrap()
170    }
171
172    // This method goes through all the errors and try to group certain types
173    // of error together, for the purpose of suggesting explicit lifetime
174    // parameters to the user. This is done so that we can have a more
175    // complete view of what lifetimes should be the same.
176    // If the return value is an empty vector, it means that processing
177    // failed (so the return value of this method should not be used).
178    //
179    // The method also attempts to weed out messages that seem like
180    // duplicates that will be unhelpful to the end-user. But
181    // obviously it never weeds out ALL errors.
182    fn process_errors(
183        &self,
184        errors: &[RegionResolutionError<'tcx>],
185    ) -> Vec<RegionResolutionError<'tcx>> {
186        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:186",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(186u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("process_errors()")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("process_errors()");
187
188        // We want to avoid reporting generic-bound failures if we can
189        // avoid it: these have a very high rate of being unhelpful in
190        // practice. This is because they are basically secondary
191        // checks that test the state of the region graph after the
192        // rest of inference is done, and the other kinds of errors
193        // indicate that the region constraint graph is internally
194        // inconsistent, so these test results are likely to be
195        // meaningless.
196        //
197        // Therefore, we filter them out of the list unless they are
198        // the only thing in the list.
199
200        let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
201            RegionResolutionError::GenericBoundFailure(..) => true,
202            RegionResolutionError::ConcreteFailure(..)
203            | RegionResolutionError::SubSupConflict(..)
204            | RegionResolutionError::UpperBoundUniverseConflict(..)
205            | RegionResolutionError::CannotNormalize(..) => false,
206        };
207
208        let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
209            errors.to_owned()
210        } else {
211            errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
212        };
213
214        // sort the errors by span, for better error message stability.
215        errors.sort_by_key(|u| {
216            match *u {
217                RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
218                RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
219                RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
220                RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => {
221                    rvo.span()
222                }
223                RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(),
224            }
225            .lo_hi()
226        });
227        errors
228    }
229
230    pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
231        match *origin {
232            SubregionOrigin::Subtype(ref trace) => RegionOriginNote::WithRequirement {
233                span: trace.cause.span,
234                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
235                expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()),
236            }
237            .add_to_diag(err),
238            SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain {
239                span,
240                msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that reference does not outlive borrowed content"))msg!("...so that reference does not outlive borrowed content"),
241            }
242            .add_to_diag(err),
243            SubregionOrigin::RelateObjectBound(span) => {
244                RegionOriginNote::Plain {
245                    span,
246                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that it can be closed over into an object"))msg!("...so that it can be closed over into an object"),
247                }
248                .add_to_diag(err);
249            }
250            SubregionOrigin::ReferenceOutlivesReferent(ty, span) => {
251                RegionOriginNote::WithName {
252                    span,
253                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that the reference type `{$name}` does not outlive the data it points at"))msg!("...so that the reference type `{$name}` does not outlive the data it points at"),
254                    name: &self.ty_to_string(ty),
255                    continues: false,
256                }
257                .add_to_diag(err);
258            }
259            SubregionOrigin::RelateParamBound(span, ty, opt_span) => {
260                RegionOriginNote::WithName {
261                    span,
262                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that the type `{$name}` will meet its required lifetime bounds{$continues ->\n                            [true] ...\n                            *[false] {\"\"}\n                        }"))msg!(
263                        "...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
264                            [true] ...
265                            *[false] {\"\"}
266                        }"
267                    ),
268                    name: &self.ty_to_string(ty),
269                    continues: opt_span.is_some(),
270                }
271                .add_to_diag(err);
272                if let Some(span) = opt_span {
273                    RegionOriginNote::Plain {
274                        span,
275                        msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...that is required by this bound"))msg!("...that is required by this bound"),
276                    }
277                    .add_to_diag(err);
278                }
279            }
280            SubregionOrigin::RelateRegionParamBound(span, _) => {
281                RegionOriginNote::Plain {
282                    span,
283                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that the declared lifetime parameter bounds are satisfied"))msg!("...so that the declared lifetime parameter bounds are satisfied"),
284                }
285                .add_to_diag(err);
286            }
287            SubregionOrigin::CompareImplItemObligation { span, .. } => {
288                RegionOriginNote::Plain {
289                    span,
290                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that the definition in impl matches the definition from the trait"))msg!(
291                        "...so that the definition in impl matches the definition from the trait"
292                    ),
293                }
294                .add_to_diag(err);
295            }
296            SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => {
297                self.note_region_origin(err, parent);
298            }
299            SubregionOrigin::AscribeUserTypeProvePredicate(span, _) => {
300                RegionOriginNote::Plain { span, msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that the where clause holds"))msg!("...so that the where clause holds") }
301                    .add_to_diag(err);
302            }
303            SubregionOrigin::SolverRegionConstraint(span) => {
304                RegionOriginNote::Plain {
305                    span,
306                    msg: rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...so that a higher-ranked lifetime bound can be satisfied"))msg!("...so that a higher-ranked lifetime bound can be satisfied"),
307                }
308                .add_to_diag(err);
309            }
310        }
311    }
312
313    pub(super) fn report_concrete_failure(
314        &self,
315        generic_param_scope: LocalDefId,
316        origin: SubregionOrigin<'tcx>,
317        sub: Region<'tcx>,
318        sup: Region<'tcx>,
319    ) -> Diag<'a> {
320        let mut err = match origin {
321            SubregionOrigin::Subtype(trace) => {
322                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
323                let mut err = self.report_and_explain_type_error(
324                    *trace,
325                    self.tcx.param_env(generic_param_scope),
326                    terr,
327                );
328                match (sub.kind(), sup.kind()) {
329                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
330                    (ty::RePlaceholder(_), _) => {
331                        note_and_explain_region(
332                            self.tcx,
333                            &mut err,
334                            generic_param_scope,
335                            "",
336                            sup,
337                            " doesn't meet the lifetime requirements",
338                            None,
339                        );
340                    }
341                    (_, ty::RePlaceholder(_)) => {
342                        note_and_explain_region(
343                            self.tcx,
344                            &mut err,
345                            generic_param_scope,
346                            "the required lifetime does not necessarily outlive ",
347                            sub,
348                            "",
349                            None,
350                        );
351                    }
352                    _ => {
353                        note_and_explain_region(
354                            self.tcx,
355                            &mut err,
356                            generic_param_scope,
357                            "",
358                            sup,
359                            "...",
360                            None,
361                        );
362                        note_and_explain_region(
363                            self.tcx,
364                            &mut err,
365                            generic_param_scope,
366                            "...does not necessarily outlive ",
367                            sub,
368                            "",
369                            None,
370                        );
371                    }
372                }
373                err
374            }
375            SubregionOrigin::Reborrow(span) => {
376                let reference_valid = note_and_explain::RegionExplanation::new(
377                    self.tcx,
378                    generic_param_scope,
379                    sub,
380                    None,
381                    note_and_explain::PrefixKind::RefValidFor,
382                    note_and_explain::SuffixKind::Continues,
383                );
384                let content_valid = note_and_explain::RegionExplanation::new(
385                    self.tcx,
386                    generic_param_scope,
387                    sup,
388                    None,
389                    note_and_explain::PrefixKind::ContentValidFor,
390                    note_and_explain::SuffixKind::Empty,
391                );
392                self.dcx().create_err(OutlivesContent {
393                    span,
394                    notes: reference_valid.into_iter().chain(content_valid).collect(),
395                })
396            }
397            SubregionOrigin::RelateObjectBound(span) => {
398                let object_valid = note_and_explain::RegionExplanation::new(
399                    self.tcx,
400                    generic_param_scope,
401                    sub,
402                    None,
403                    note_and_explain::PrefixKind::TypeObjValidFor,
404                    note_and_explain::SuffixKind::Empty,
405                );
406                let pointer_valid = note_and_explain::RegionExplanation::new(
407                    self.tcx,
408                    generic_param_scope,
409                    sup,
410                    None,
411                    note_and_explain::PrefixKind::SourcePointerValidFor,
412                    note_and_explain::SuffixKind::Empty,
413                );
414                self.dcx().create_err(OutlivesBound {
415                    span,
416                    notes: object_valid.into_iter().chain(pointer_valid).collect(),
417                })
418            }
419            SubregionOrigin::RelateParamBound(span, ty, opt_span) => {
420                let prefix = match sub.kind() {
421                    ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
422                    _ => note_and_explain::PrefixKind::TypeOutlive,
423                };
424                let suffix = if opt_span.is_some() {
425                    note_and_explain::SuffixKind::ReqByBinding
426                } else {
427                    note_and_explain::SuffixKind::Empty
428                };
429                let note = note_and_explain::RegionExplanation::new(
430                    self.tcx,
431                    generic_param_scope,
432                    sub,
433                    opt_span,
434                    prefix,
435                    suffix,
436                );
437                self.dcx().create_err(FulfillReqLifetime {
438                    span,
439                    ty: self.deeply_resolve_ignoring_regions(ty),
440                    note,
441                })
442            }
443            SubregionOrigin::RelateRegionParamBound(span, ty) => {
444                let param_instantiated = note_and_explain::RegionExplanation::new(
445                    self.tcx,
446                    generic_param_scope,
447                    sup,
448                    None,
449                    note_and_explain::PrefixKind::LfParamInstantiatedWith,
450                    note_and_explain::SuffixKind::Empty,
451                );
452                let mut alt_span = None;
453                if let Some(ty) = ty
454                    && sub.is_static()
455                    && let ty::Dynamic(preds, _) = ty.kind()
456                    && let Some(def_id) = preds.principal_def_id()
457                {
458                    for (clause, span) in
459                        self.tcx.clauses_of(def_id).instantiate_identity(self.tcx).into_iter()
460                    {
461                        if let ty::ClauseKind::TypeOutlives(ty::OutlivesClause(a, b)) =
462                            clause.kind().skip_binder()
463                            && let ty::Param(param) = a.kind()
464                            && param.name == kw::SelfUpper
465                            && b.is_static()
466                        {
467                            // Point at explicit `'static` bound on the trait (`trait T: 'static`).
468                            alt_span = Some(span);
469                        }
470                    }
471                }
472                let param_must_outlive = note_and_explain::RegionExplanation::new(
473                    self.tcx,
474                    generic_param_scope,
475                    sub,
476                    alt_span,
477                    note_and_explain::PrefixKind::LfParamMustOutlive,
478                    note_and_explain::SuffixKind::Empty,
479                );
480                self.dcx().create_err(LfBoundNotSatisfied {
481                    span,
482                    notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
483                })
484            }
485            SubregionOrigin::ReferenceOutlivesReferent(ty, span) => {
486                let pointer_valid = note_and_explain::RegionExplanation::new(
487                    self.tcx,
488                    generic_param_scope,
489                    sub,
490                    None,
491                    note_and_explain::PrefixKind::PointerValidFor,
492                    note_and_explain::SuffixKind::Empty,
493                );
494                let data_valid = note_and_explain::RegionExplanation::new(
495                    self.tcx,
496                    generic_param_scope,
497                    sup,
498                    None,
499                    note_and_explain::PrefixKind::DataValidFor,
500                    note_and_explain::SuffixKind::Empty,
501                );
502                self.dcx().create_err(RefLongerThanData {
503                    span,
504                    ty: self.deeply_resolve_ignoring_regions(ty),
505                    notes: pointer_valid.into_iter().chain(data_valid).collect(),
506                })
507            }
508            SubregionOrigin::CompareImplItemObligation {
509                span,
510                impl_item_def_id,
511                trait_item_def_id,
512            } => {
513                let mut err = self.report_extra_impl_obligation(
514                    span,
515                    impl_item_def_id,
516                    trait_item_def_id,
517                    &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}: {1}`", sup, sub))
    })format!("`{sup}: {sub}`"),
518                );
519                // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
520                if let Some(generics) = self.tcx.hir_get_generics(impl_item_def_id)
521                    && generics.where_clause_span.contains(span)
522                {
523                    self.suggest_copy_trait_method_bounds(
524                        trait_item_def_id,
525                        impl_item_def_id,
526                        &mut err,
527                    );
528                }
529                err
530            }
531            SubregionOrigin::CheckAssociatedTypeBounds {
532                impl_item_def_id,
533                trait_item_def_id,
534                parent,
535            } => {
536                let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup);
537
538                // Don't mention the item name if it's an RPITIT, since that'll just confuse
539                // folks.
540                if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) {
541                    let trait_item_span = self.tcx.def_span(trait_item_def_id);
542                    let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
543                    err.span_label(
544                        trait_item_span,
545                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("definition of `{0}` from trait",
                item_name))
    })format!("definition of `{item_name}` from trait"),
546                    );
547                }
548
549                self.suggest_copy_trait_method_bounds(
550                    trait_item_def_id,
551                    impl_item_def_id,
552                    &mut err,
553                );
554                err
555            }
556            SubregionOrigin::AscribeUserTypeProvePredicate(span, _) => {
557                let instantiated = note_and_explain::RegionExplanation::new(
558                    self.tcx,
559                    generic_param_scope,
560                    sup,
561                    None,
562                    note_and_explain::PrefixKind::LfInstantiatedWith,
563                    note_and_explain::SuffixKind::Empty,
564                );
565                let must_outlive = note_and_explain::RegionExplanation::new(
566                    self.tcx,
567                    generic_param_scope,
568                    sub,
569                    None,
570                    note_and_explain::PrefixKind::LfMustOutlive,
571                    note_and_explain::SuffixKind::Empty,
572                );
573                self.dcx().create_err(LfBoundNotSatisfied {
574                    span,
575                    notes: instantiated.into_iter().chain(must_outlive).collect(),
576                })
577            }
578            SubregionOrigin::SolverRegionConstraint(span) => self
579                .dcx()
580                .struct_span_err(span, "higher-ranked lifetime bound could not be satisfied"),
581        };
582        if sub.is_error() || sup.is_error() {
583            err.downgrade_to_delayed_bug();
584        }
585        err
586    }
587
588    pub fn suggest_copy_trait_method_bounds(
589        &self,
590        trait_item_def_id: DefId,
591        impl_item_def_id: LocalDefId,
592        err: &mut Diag<'_>,
593    ) {
594        // FIXME(compiler-errors): Right now this is only being used for region
595        // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
596        // but right now it's not really very smart when it comes to implicit `Sized`
597        // predicates and bounds on the trait itself.
598
599        let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else {
600            return;
601        };
602        let trait_ref = self.tcx.impl_trait_ref(impl_def_id);
603        let trait_args = trait_ref
604            .instantiate_identity()
605            .skip_norm_wip()
606            // Replace the explicit self type with `Self` for better suggestion rendering
607            .with_replaced_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
608            .args;
609        let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
610            .rebase_onto(self.tcx, impl_def_id, trait_args);
611
612        let Ok(trait_predicates) = self
613            .tcx
614            .explicit_clauses_of(trait_item_def_id)
615            .instantiate_own(self.tcx, trait_item_args)
616            .map(|(clause, _)| {
617                let clause = clause.skip_norm_wip();
618                if clause.is_suggestable(self.tcx, false) {
619                    Ok(clause.to_string())
620                } else {
621                    Err(())
622                }
623            })
624            .collect::<Result<Vec<_>, ()>>()
625        else {
626            return;
627        };
628
629        let Some(generics) = self.tcx.hir_get_generics(impl_item_def_id) else {
630            return;
631        };
632
633        let suggestion = if trait_predicates.is_empty() {
634            WhereClauseSuggestions::Remove { span: generics.where_clause_span }
635        } else {
636            let space = if generics.where_clause_span.is_empty() { " " } else { "" };
637            WhereClauseSuggestions::CopyPredicates {
638                span: generics.where_clause_span,
639                space,
640                trait_predicates: trait_predicates.join(", "),
641            }
642        };
643        err.subdiagnostic(suggestion);
644    }
645
646    pub(super) fn report_placeholder_failure(
647        &self,
648        generic_param_scope: LocalDefId,
649        placeholder_origin: SubregionOrigin<'tcx>,
650        sub: Region<'tcx>,
651        sup: Region<'tcx>,
652    ) -> Diag<'a> {
653        // I can't think how to do better than this right now. -nikomatsakis
654        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:654",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(654u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("placeholder_origin")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("placeholder_origin");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("sub")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("sub");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("sup")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("sup");
                                            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!("report_placeholder_failure")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&placeholder_origin)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sup)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
655        match placeholder_origin {
656            SubregionOrigin::Subtype(ref trace)
657                if #[allow(non_exhaustive_omitted_patterns)] match &trace.cause.code().peel_derives()
    {
    ObligationCauseCode::WhereClause(..) |
        ObligationCauseCode::WhereClauseInExpr(..) => true,
    _ => false,
}matches!(
658                    &trace.cause.code().peel_derives(),
659                    ObligationCauseCode::WhereClause(..)
660                        | ObligationCauseCode::WhereClauseInExpr(..)
661                ) =>
662            {
663                // Hack to get around the borrow checker because trace.cause has an `Rc`.
664                if let ObligationCauseCode::WhereClause(_, span)
665                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
666                    &trace.cause.code().peel_derives()
667                {
668                    let span = *span;
669                    let mut err = self.report_concrete_failure(
670                        generic_param_scope,
671                        placeholder_origin,
672                        sub,
673                        sup,
674                    );
675                    if !span.is_dummy() {
676                        err =
677                            err.with_span_note(span, "the lifetime requirement is introduced here");
678                    }
679                    err
680                } else {
681                    {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here...")));
}unreachable!(
682                        "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
683                    )
684                }
685            }
686            SubregionOrigin::Subtype(trace) => {
687                let terr = TypeError::RegionsPlaceholderMismatch;
688                return self.report_and_explain_type_error(
689                    *trace,
690                    self.tcx.param_env(generic_param_scope),
691                    terr,
692                );
693            }
694            _ => {
695                return self.report_concrete_failure(
696                    generic_param_scope,
697                    placeholder_origin,
698                    sub,
699                    sup,
700                );
701            }
702        }
703    }
704
705    pub fn report_generic_bound_failure(
706        &self,
707        generic_param_scope: LocalDefId,
708        span: Span,
709        origin: Option<SubregionOrigin<'tcx>>,
710        bound_kind: GenericKind<'tcx>,
711        sub: Region<'tcx>,
712    ) -> ErrorGuaranteed {
713        self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub)
714            .emit_err()
715    }
716
717    pub fn construct_generic_bound_failure(
718        &self,
719        generic_param_scope: LocalDefId,
720        span: Span,
721        origin: Option<SubregionOrigin<'tcx>>,
722        bound_kind: GenericKind<'tcx>,
723        sub: Region<'tcx>,
724    ) -> Diag<'a> {
725        if let Some(SubregionOrigin::CompareImplItemObligation {
726            span,
727            impl_item_def_id,
728            trait_item_def_id,
729        }) = origin
730        {
731            return self.report_extra_impl_obligation(
732                span,
733                impl_item_def_id,
734                trait_item_def_id,
735                &::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}: {1}`", bound_kind, sub))
    })format!("`{bound_kind}: {sub}`"),
736            );
737        }
738
739        let labeled_user_string = match bound_kind {
740            GenericKind::Param(_) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the parameter type `{0}`",
                bound_kind))
    })format!("the parameter type `{bound_kind}`"),
741            GenericKind::Placeholder(_) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the placeholder type `{0}`",
                bound_kind))
    })format!("the placeholder type `{bound_kind}`"),
742            GenericKind::Alias(p) => match p.kind {
743                ty::Projection { .. } | ty::Inherent { .. } => {
744                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the associated type `{0}`",
                bound_kind))
    })format!("the associated type `{bound_kind}`")
745                }
746                ty::Free { .. } => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the type alias `{0}`", bound_kind))
    })format!("the type alias `{bound_kind}`"),
747                ty::Opaque { .. } => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the opaque type `{0}`",
                bound_kind))
    })format!("the opaque type `{bound_kind}`"),
748            },
749        };
750
751        let mut err = self
752            .tcx
753            .dcx()
754            .struct_span_err(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} may not live long enough",
                labeled_user_string))
    })format!("{labeled_user_string} may not live long enough"));
755        err.code(match sub.kind() {
756            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.is_named(self.tcx) => E0309,
757            ty::ReStatic => E0310,
758            _ => E0311,
759        });
760
761        '_explain: {
762            let (description, span) = match sub.kind() {
763                ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
764                    msg_span_from_named_region(self.tcx, generic_param_scope, sub, Some(span))
765                }
766                _ => (::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("lifetime `{0}`", sub))
    })format!("lifetime `{sub}`"), Some(span)),
767            };
768            let prefix = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} must be valid for ",
                labeled_user_string))
    })format!("{labeled_user_string} must be valid for ");
769            label_msg_span(&mut err, &prefix, description, span, "...");
770            if let Some(origin) = origin {
771                self.note_region_origin(&mut err, &origin);
772            }
773        }
774
775        let msg = "consider adding an explicit lifetime bound";
776        'suggestion: {
777            if (bound_kind, sub).has_infer_regions()
778                || (bound_kind, sub).has_placeholders()
779                || !bound_kind.is_suggestable(self.tcx, false)
780            {
781                let lt_name = sub.get_name_or_anon(self.tcx).to_string();
782                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}: {2}`...", msg,
                bound_kind, lt_name))
    })format!("{msg} `{bound_kind}: {lt_name}`..."));
783                break 'suggestion;
784            }
785
786            let mut generic_param_scope = generic_param_scope;
787            while self.tcx.def_kind(generic_param_scope) == DefKind::OpaqueTy {
788                generic_param_scope = self.tcx.local_parent(generic_param_scope);
789            }
790
791            // type_param_sugg_span is (span, has_bounds, needs_parentheses)
792            let (type_scope, type_param_sugg_span) = match bound_kind {
793                GenericKind::Param(param) => {
794                    let generics = self.tcx.generics_of(generic_param_scope);
795                    let type_param = generics.type_param(param, self.tcx);
796                    let def_id = type_param.def_id.expect_local();
797                    let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
798                    // Get the `hir::Param` to verify whether it already has any bounds.
799                    // We do this to avoid suggesting code that ends up as `T: 'a'b`,
800                    // instead we suggest `T: 'a + 'b` in that case.
801                    let hir_generics = self.tcx.hir_get_generics(scope).unwrap();
802                    let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
803                        Some((span, open_paren_sp)) => {
804                            Some((span, LifetimeSuggestion::NeedsPlus(open_paren_sp)))
805                        }
806                        // If `param` corresponds to `Self`, no usable suggestion span.
807                        None if generics.has_self && param.index == 0 => None,
808                        None => {
809                            let mut colon_flag = false;
810                            let span = if let Some(param) =
811                                hir_generics.params.iter().find(|param| param.def_id == def_id)
812                                && let ParamName::Plain(ident) = param.name
813                            {
814                                if let Some(sp) = param.colon_span {
815                                    colon_flag = true;
816                                    sp.shrink_to_hi()
817                                } else {
818                                    ident.span.shrink_to_hi()
819                                }
820                            } else {
821                                let span = self.tcx.def_span(def_id);
822                                span.shrink_to_hi()
823                            };
824                            match colon_flag {
825                                true => Some((span, LifetimeSuggestion::HasColon)),
826                                false => Some((span, LifetimeSuggestion::NeedsColon)),
827                            }
828                        }
829                    };
830                    (scope, sugg_span)
831                }
832                _ => (generic_param_scope, None),
833            };
834            let suggestion_scope = {
835                let lifetime_scope = match sub.kind() {
836                    ty::ReStatic => hir::def_id::CRATE_DEF_ID,
837                    _ => match self.tcx.is_suitable_region(generic_param_scope, sub) {
838                        Some(info) => info.scope,
839                        None => generic_param_scope,
840                    },
841                };
842                match self.tcx.is_descendant_of(type_scope, lifetime_scope) {
843                    true => type_scope,
844                    false => lifetime_scope,
845                }
846            };
847
848            let mut suggs = ::alloc::vec::Vec::new()vec![];
849            if let Some(lt_name) = self.suggest_name_region(generic_param_scope, sub, &mut suggs) {
850                if let Some((sp, suggestion_type)) = type_param_sugg_span
851                    && suggestion_scope == type_scope
852                {
853                    match suggestion_type {
854                        LifetimeSuggestion::NeedsPlus(open_paren_sp) => {
855                            let suggestion = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}", lt_name))
    })format!(" + {lt_name}");
856                            if let Some(open_paren_sp) = open_paren_sp {
857                                suggs.push((open_paren_sp, "(".to_string()));
858                                suggs.push((sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("){0}", suggestion))
    })format!("){suggestion}")));
859                            } else {
860                                suggs.push((sp, suggestion));
861                            }
862                        }
863                        LifetimeSuggestion::NeedsColon => suggs.push((sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(": {0}", lt_name))
    })format!(": {lt_name}"))),
864                        LifetimeSuggestion::HasColon => suggs.push((sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" {0}", lt_name))
    })format!(" {lt_name}"))),
865                    }
866                } else if let GenericKind::Alias(ref p) = bound_kind
867                    && let ty::Projection { def_id } = p.kind(self.tcx)
868                    && let DefKind::AssocTy = self.tcx.def_kind(def_id)
869                    && let Some(ty::ImplTraitInTraitData::Trait { .. }) =
870                        self.tcx.opt_rpitit_info(def_id)
871                {
872                    // The lifetime found in the `impl` is longer than the one on the RPITIT.
873                    // Do not suggest `<Type as Trait>::{opaque}: 'static`.
874                } else if let Some(generics) = self.tcx.hir_get_generics(suggestion_scope) {
875                    let pred = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", bound_kind, lt_name))
    })format!("{bound_kind}: {lt_name}");
876                    let suggestion = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}",
                generics.add_where_or_trailing_comma(), pred))
    })format!("{} {}", generics.add_where_or_trailing_comma(), pred);
877                    suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
878                } else {
879                    let consider = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}: {2}`...", msg,
                bound_kind, sub))
    })format!("{msg} `{bound_kind}: {sub}`...");
880                    err.help(consider);
881                }
882            }
883
884            if !suggs.is_empty() {
885                err.multipart_suggestion(
886                    msg,
887                    suggs,
888                    Applicability::MaybeIncorrect, // Issue #41966
889                );
890            }
891        }
892
893        if sub.kind() == ty::ReStatic
894            && let Some(node) = self.tcx.hir_get_if_local(generic_param_scope.into())
895            && let hir::Node::Item(hir::Item {
896                kind: hir::ItemKind::Fn { sig, body, generics, has_body: true, .. },
897                ..
898            })
899            | hir::Node::TraitItem(hir::TraitItem {
900                kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
901                generics,
902                ..
903            })
904            | hir::Node::ImplItem(hir::ImplItem {
905                kind: hir::ImplItemKind::Fn(sig, body),
906                generics,
907                ..
908            }) = node
909            && let hir::Node::Expr(expr) = self.tcx.hir_node(body.hir_id)
910            && let hir::ExprKind::Block(block, _) = expr.kind
911            && let Some(tail) = block.expr
912            && tail.span == span
913            && let hir::FnRetTy::Return(ty) = sig.decl.output
914            && let hir::TyKind::Path(path) = ty.kind
915            && let hir::QPath::Resolved(None, path) = path
916            && let hir::def::Res::Def(_, def_id) = path.res
917            && Some(def_id) == self.tcx.lang_items().owned_box()
918            && let [segment] = path.segments
919            && let Some(args) = segment.args
920            && let [hir::GenericArg::Type(ty)] = args.args
921            && let hir::TyKind::TraitObject(_, tagged_ref) = ty.kind
922            && let hir::LifetimeKind::ImplicitObjectLifetimeDefault = tagged_ref.pointer().kind
923        {
924            // Explicitly look for `-> Box<dyn Trait>` to point at it as the *likely* source of
925            // the `'static` lifetime requirement.
926            err.span_label(
927                ty.span,
928                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this `dyn Trait` has an implicit `\'static` lifetime bound"))
    })format!("this `dyn Trait` has an implicit `'static` lifetime bound"),
929            );
930            let lt_name = "'a";
931            if generics
932                .params
933                .iter()
934                .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    GenericParamKind::Lifetime { .. } => true,
    _ => false,
}matches!(p.kind, GenericParamKind::Lifetime { .. }))
935                .count()
936                == 0
937            {
938                let (span, suggestion) = if let Some(span) = generics.span_for_lifetime_suggestion()
939                {
940                    (span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", lt_name))
    })format!("{lt_name}, "))
941                } else {
942                    (generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", lt_name))
    })format!("<{lt_name}>"))
943                };
944
945                err.multipart_suggestion(
946                    msg,
947                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span, suggestion),
                (ty.span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!(" + {0}", lt_name))
                        }))]))vec![(span, suggestion), (ty.span.shrink_to_hi(), format!(" + {lt_name}"))],
948                    Applicability::MaybeIncorrect,
949                );
950            }
951        }
952
953        err
954    }
955
956    pub fn suggest_name_region(
957        &self,
958        generic_param_scope: LocalDefId,
959        lifetime: Region<'tcx>,
960        add_lt_suggs: &mut Vec<(Span, String)>,
961    ) -> Option<String> {
962        let [name] =
963            suggest_name_regions(self.tcx, generic_param_scope, &[lifetime], add_lt_suggs)?
964                .try_into()
965                .unwrap();
966        Some(name)
967    }
968
969    fn report_sub_sup_conflict(
970        &self,
971        generic_param_scope: LocalDefId,
972        var_origin: RegionVariableOrigin<'tcx>,
973        sub_origin: SubregionOrigin<'tcx>,
974        sub_region: Region<'tcx>,
975        sup_origin: SubregionOrigin<'tcx>,
976        sup_region: Region<'tcx>,
977    ) -> ErrorGuaranteed {
978        let mut err = self.report_inference_failure(var_origin);
979
980        note_and_explain_region(
981            self.tcx,
982            &mut err,
983            generic_param_scope,
984            "first, the lifetime cannot outlive ",
985            sup_region,
986            "...",
987            None,
988        );
989
990        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:990",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(990u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_sub_sup_conflict: var_origin={0:?}",
                                                    var_origin) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
991        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:991",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(991u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_sub_sup_conflict: sub_region={0:?}",
                                                    sub_region) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
992        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:992",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(992u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_sub_sup_conflict: sub_origin={0:?}",
                                                    sub_origin) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
993        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:993",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(993u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_sub_sup_conflict: sup_region={0:?}",
                                                    sup_region) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
994        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs:994",
                        "rustc_trait_selection::error_reporting::infer::region",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                        ::tracing_core::__macro_support::Option::Some(994u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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!("report_sub_sup_conflict: sup_origin={0:?}",
                                                    sup_origin) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
995
996        if let SubregionOrigin::Subtype(ref sup_trace) = sup_origin
997            && let SubregionOrigin::Subtype(ref sub_trace) = sub_origin
998            && let Some((sup_expected, sup_found)) =
999                self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path())
1000            && let Some((sub_expected, sub_found)) =
1001                self.values_str(sub_trace.values, &sub_trace.cause, err.long_ty_path())
1002            && sub_expected == sup_expected
1003            && sub_found == sup_found
1004        {
1005            note_and_explain_region(
1006                self.tcx,
1007                &mut err,
1008                generic_param_scope,
1009                "...but the lifetime must also be valid for ",
1010                sub_region,
1011                "...",
1012                None,
1013            );
1014            err.span_note(
1015                sup_trace.cause.span,
1016                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("...so that the {0}",
                sup_trace.cause.as_requirement_str()))
    })format!("...so that the {}", sup_trace.cause.as_requirement_str()),
1017            );
1018
1019            err.note_expected_found("", sup_expected, "", sup_found);
1020            return if sub_region.is_error() | sup_region.is_error() {
1021                err.delay_as_bug()
1022            } else {
1023                err.emit_err()
1024            };
1025        }
1026
1027        self.note_region_origin(&mut err, &sup_origin);
1028
1029        note_and_explain_region(
1030            self.tcx,
1031            &mut err,
1032            generic_param_scope,
1033            "but, the lifetime must be valid for ",
1034            sub_region,
1035            "...",
1036            None,
1037        );
1038
1039        self.note_region_origin(&mut err, &sub_origin);
1040        if sub_region.is_error() | sup_region.is_error() {
1041            err.delay_as_bug()
1042        } else {
1043            err.emit_err()
1044        }
1045    }
1046
1047    fn report_inference_failure(&self, var_origin: RegionVariableOrigin<'tcx>) -> Diag<'_> {
1048        let br_string = |br: ty::BoundRegionKind<'tcx>| match br {
1049            ty::BoundRegionKind::Named(def_id) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` ",
                self.tcx.item_name(def_id)))
    })format!("`{}` ", self.tcx.item_name(def_id)),
1050            _ => String::new(),
1051        };
1052        let var_description = match var_origin {
1053            RegionVariableOrigin::Misc(_) => String::new(),
1054            RegionVariableOrigin::PatternRegion(_) => " for pattern".to_string(),
1055            RegionVariableOrigin::BorrowRegion(_) => " for borrow expression".to_string(),
1056            RegionVariableOrigin::Autoref(_) => " for autoref".to_string(),
1057            RegionVariableOrigin::Coercion(_) => " for automatic coercion".to_string(),
1058            RegionVariableOrigin::BoundRegion(_, br, BoundRegionConversionTime::FnCall) => {
1059                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for lifetime parameter {0}in function call",
                br_string(br)))
    })format!(" for lifetime parameter {}in function call", br_string(br))
1060            }
1061            RegionVariableOrigin::BoundRegion(
1062                _,
1063                br,
1064                BoundRegionConversionTime::HigherRankedType,
1065            ) => {
1066                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for lifetime parameter {0}in generic type",
                br_string(br)))
    })format!(" for lifetime parameter {}in generic type", br_string(br))
1067            }
1068            RegionVariableOrigin::BoundRegion(
1069                _,
1070                br,
1071                BoundRegionConversionTime::AssocTypeProjection(def_id),
1072            ) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for lifetime parameter {0}in trait containing associated type `{1}`",
                br_string(br), self.tcx.associated_item(def_id).name()))
    })format!(
1073                " for lifetime parameter {}in trait containing associated type `{}`",
1074                br_string(br),
1075                self.tcx.associated_item(def_id).name()
1076            ),
1077            RegionVariableOrigin::RegionParameterDefinition(_, name) => {
1078                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for lifetime parameter `{0}`",
                name))
    })format!(" for lifetime parameter `{name}`")
1079            }
1080            RegionVariableOrigin::UpvarRegion(ref upvar_id, _) => {
1081                let var_name = self.tcx.hir_name(upvar_id.var_path.hir_id);
1082                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for capture of `{0}` by closure",
                var_name))
    })format!(" for capture of `{var_name}` by closure")
1083            }
1084            RegionVariableOrigin::Nll(..) => ::rustc_span::macros::bug_impl(None,
    format_args!("NLL variable found in lexical phase"), Location::caller())bug!("NLL variable found in lexical phase"),
1085        };
1086
1087        {
    self.dcx().struct_span_err(var_origin.span(),
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot infer an appropriate lifetime{0} due to conflicting requirements",
                            var_description))
                })).with_code(E0803)
}struct_span_code_err!(
1088            self.dcx(),
1089            var_origin.span(),
1090            E0803,
1091            "cannot infer an appropriate lifetime{} due to conflicting requirements",
1092            var_description
1093        )
1094    }
1095}
1096
1097enum LifetimeSuggestion {
1098    NeedsPlus(Option<Span>),
1099    NeedsColon,
1100    HasColon,
1101}
1102
1103pub(super) fn note_and_explain_region<'tcx>(
1104    tcx: TyCtxt<'tcx>,
1105    err: &mut Diag<'_>,
1106    generic_param_scope: LocalDefId,
1107    prefix: &str,
1108    region: ty::Region<'tcx>,
1109    suffix: &str,
1110    alt_span: Option<Span>,
1111) {
1112    let (description, span) = match region.kind() {
1113        ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
1114            msg_span_from_named_region(tcx, generic_param_scope, region, alt_span)
1115        }
1116
1117        ty::ReError(_) => return,
1118
1119        // FIXME(#125431): `ReVar` shouldn't reach here.
1120        ty::ReVar(_) => (::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("lifetime `{0}`", region))
    })format!("lifetime `{region}`"), alt_span),
1121
1122        ty::ReBound(..) | ty::ReErased => {
1123            ::rustc_span::macros::bug_impl(None,
    format_args!("unexpected region for note_and_explain_region: {0:?}",
        region), Location::caller());bug!("unexpected region for note_and_explain_region: {:?}", region);
1124        }
1125    };
1126
1127    emit_msg_span(err, prefix, description, span, suffix);
1128}
1129
1130fn suggest_name_regions<'tcx>(
1131    tcx: TyCtxt<'tcx>,
1132    generic_param_scope: LocalDefId,
1133    lifetimes: &[Region<'tcx>],
1134    add_lt_suggs: &mut Vec<(Span, String)>,
1135) -> Option<Vec<String>> {
1136    struct LifetimeReplaceVisitor<'a> {
1137        new_lts: &'a [(LocalDefId, String)],
1138        add_lt_suggs: &'a mut Vec<(Span, String)>,
1139    }
1140
1141    impl<'hir> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'_> {
1142        fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
1143            if let hir::LifetimeKind::Param(def_id) = lt.kind
1144                && let Some((_, new_lt)) = self.new_lts.iter().find(|(id, _)| *id == def_id)
1145            {
1146                self.add_lt_suggs.push(lt.suggestion(new_lt));
1147            }
1148        }
1149    }
1150
1151    let mut lifetime_scope = None;
1152    let mut used_names = ::alloc::vec::Vec::new()vec![];
1153    let mut new_lts: Vec<(LocalDefId, String)> = ::alloc::vec::Vec::new()vec![];
1154    let names: Vec<_> = lifetimes
1155        .iter()
1156        .map(|&lifetime| {
1157            let (lifetime_def_id, scope) =
1158                match tcx.is_suitable_region(generic_param_scope, lifetime) {
1159                    Some(info) if !lifetime.is_named(tcx) => {
1160                        (info.region_def_id.expect_local(), info.scope)
1161                    }
1162                    _ => return Some(lifetime.get_name(tcx)?.to_string()),
1163                };
1164            if *lifetime_scope.get_or_insert_with(|| {
1165                used_names.extend(
1166                    iter::successors(Some(tcx.generics_of(scope)), |g| {
1167                        g.parent.map(|p| tcx.generics_of(p))
1168                    })
1169                    .flat_map(|g| &g.own_params)
1170                    .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    ty::GenericParamDefKind::Lifetime => true,
    _ => false,
}matches!(p.kind, ty::GenericParamDefKind::Lifetime))
1171                    .map(|p| p.name),
1172                );
1173                // consider late-bound lifetimes ...
1174                used_names.extend(
1175                    tcx.late_bound_vars(tcx.local_def_id_to_hir_id(scope)).into_iter().filter_map(
1176                        |p| match p {
1177                            ty::BoundVariableKind::Region(lt) => lt.get_name(tcx),
1178                            _ => None,
1179                        },
1180                    ),
1181                );
1182                scope
1183            }) != scope
1184            {
1185                return Some(lifetime.get_name(tcx)?.to_string());
1186            }
1187            if let Some((_, name)) = new_lts.iter().find(|(id, _)| *id == lifetime_def_id) {
1188                return Some(name.clone());
1189            }
1190            let new_lt = (b'a'..=b'z')
1191                .map(|c| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\'{0}", c as char))
    })format!("'{}", c as char))
1192                .find(|candidate| !used_names.iter().any(|e| e.as_str() == candidate))
1193                .unwrap_or_else(|| "'lt".to_string());
1194            used_names.push(Symbol::intern(&new_lt));
1195            new_lts.push((lifetime_def_id, new_lt.clone()));
1196            Some(new_lt)
1197        })
1198        .collect::<Option<_>>()?;
1199
1200    let Some(lifetime_scope) = lifetime_scope else {
1201        return Some(names);
1202    };
1203
1204    let mut visitor = LifetimeReplaceVisitor { new_lts: &new_lts, add_lt_suggs };
1205    match tcx.expect_hir_owner_node(lifetime_scope) {
1206        hir::OwnerNode::Item(i) => visitor.visit_item(i),
1207        hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i),
1208        hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i),
1209        hir::OwnerNode::TraitItem(i) => visitor.visit_trait_item(i),
1210        hir::OwnerNode::Crate(_) => ::rustc_span::macros::bug_impl(None,
    format_args!("OwnerNode::Crate doesn\'t not have generics"),
    Location::caller())bug!("OwnerNode::Crate doesn't not have generics"),
1211        hir::OwnerNode::Synthetic => ::core::panicking::unreachable_default_msg()unreachable!(),
1212    }
1213
1214    let new_lt = new_lts.into_iter().map(|(_, name)| name).collect::<Vec<_>>().join(", ");
1215    let ast_generics = tcx.hir_get_generics(lifetime_scope).unwrap();
1216    let sugg = ast_generics
1217        .span_for_lifetime_suggestion()
1218        .map(|span| (span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", new_lt))
    })format!("{new_lt}, ")))
1219        .unwrap_or_else(|| (ast_generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", new_lt))
    })format!("<{new_lt}>")));
1220    add_lt_suggs.push(sugg);
1221
1222    Some(names)
1223}
1224
1225fn explain_free_region<'tcx>(
1226    tcx: TyCtxt<'tcx>,
1227    err: &mut Diag<'_>,
1228    generic_param_scope: LocalDefId,
1229    prefix: &str,
1230    region: ty::Region<'tcx>,
1231    suffix: &str,
1232) {
1233    let (description, span) = msg_span_from_named_region(tcx, generic_param_scope, region, None);
1234
1235    label_msg_span(err, prefix, description, span, suffix);
1236}
1237
1238fn msg_span_from_named_region<'tcx>(
1239    tcx: TyCtxt<'tcx>,
1240    generic_param_scope: LocalDefId,
1241    region: ty::Region<'tcx>,
1242    alt_span: Option<Span>,
1243) -> (String, Option<Span>) {
1244    match region.kind() {
1245        ty::ReEarlyParam(br) => {
1246            let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id;
1247            let span = tcx.def_span(param_def_id);
1248            let text = if br.is_named() {
1249                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the lifetime `{0}` as defined here",
                br.name))
    })format!("the lifetime `{}` as defined here", br.name)
1250            } else {
1251                "the anonymous lifetime as defined here".to_string()
1252            };
1253            (text, Some(span))
1254        }
1255        ty::ReLateParam(ref fr) => {
1256            if !fr.kind.is_named(tcx)
1257                && let Some((ty, _)) = find_anon_type(tcx, generic_param_scope, region)
1258            {
1259                ("the anonymous lifetime defined here".to_string(), Some(ty.span))
1260            } else {
1261                match fr.kind {
1262                    ty::LateParamRegionKind::Named(param_def_id) => {
1263                        let name = tcx.item_name(param_def_id);
1264                        let span = tcx.def_span(param_def_id);
1265                        let text = if name == kw::UnderscoreLifetime {
1266                            "the anonymous lifetime as defined here".to_string()
1267                        } else {
1268                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the lifetime `{0}` as defined here",
                name))
    })format!("the lifetime `{name}` as defined here")
1269                        };
1270                        (text, Some(span))
1271                    }
1272                    ty::LateParamRegionKind::Anon(_) => (
1273                        "the anonymous lifetime as defined here".to_string(),
1274                        Some(tcx.def_span(generic_param_scope)),
1275                    ),
1276                    _ => (
1277                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the lifetime `{0}` as defined here",
                region))
    })format!("the lifetime `{region}` as defined here"),
1278                        Some(tcx.def_span(generic_param_scope)),
1279                    ),
1280                }
1281            }
1282        }
1283        ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
1284        ty::RePlaceholder(ty::PlaceholderRegion {
1285            bound: ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. },
1286            ..
1287        }) => (
1288            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the lifetime `{0}` as defined here",
                tcx.item_name(def_id)))
    })format!("the lifetime `{}` as defined here", tcx.item_name(def_id)),
1289            Some(tcx.def_span(def_id)),
1290        ),
1291        ty::RePlaceholder(ty::PlaceholderRegion {
1292            bound: ty::BoundRegion { kind: ty::BoundRegionKind::Anon, .. },
1293            ..
1294        }) => ("an anonymous lifetime".to_owned(), None),
1295        _ => ::rustc_span::macros::bug_impl(None, format_args!("{0:?}", region),
    Location::caller())bug!("{:?}", region),
1296    }
1297}
1298
1299fn emit_msg_span(
1300    err: &mut Diag<'_>,
1301    prefix: &str,
1302    description: String,
1303    span: Option<Span>,
1304    suffix: &str,
1305) {
1306    let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}{2}", prefix, description,
                suffix))
    })format!("{prefix}{description}{suffix}");
1307
1308    if let Some(span) = span {
1309        err.span_note(span, message);
1310    } else {
1311        err.note(message);
1312    }
1313}
1314
1315fn label_msg_span(
1316    err: &mut Diag<'_>,
1317    prefix: &str,
1318    description: String,
1319    span: Option<Span>,
1320    suffix: &str,
1321) {
1322    let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}{2}", prefix, description,
                suffix))
    })format!("{prefix}{description}{suffix}");
1323
1324    if let Some(span) = span {
1325        err.span_label(span, message);
1326    } else {
1327        err.note(message);
1328    }
1329}
1330
1331{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("unexpected_hidden_region_diagnostic",
                                    "rustc_trait_selection::error_reporting::infer::region",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs"),
                                    ::tracing_core::__macro_support::Option::Some(1331u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::region"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("generic_param_scope")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("generic_param_scope");
                                                        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("hidden_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("hidden_ty");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("hidden_region")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("hidden_region");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("opaque_ty_key")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("opaque_ty_key");
                                                        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::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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(&generic_param_scope)
                                                            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(&hidden_ty)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&hidden_region)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&opaque_ty_key)
                                                            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: Diag<'a> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = infcx.tcx;
            let mut err =
                infcx.dcx().create_err(diagnostics::OpaqueCapturesLifetime {
                        span,
                        opaque_ty: Ty::new_opaque(tcx, ty::IsRigid::No,
                            opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args),
                        opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
                    });
            let mut highlight = RegionHighlightMode::default();
            highlight.keep_regions = true;
            let hidden_ty =
                Highlighted {
                    highlight,
                    ns: Namespace::TypeNS,
                    tcx,
                    value: hidden_ty,
                };
            match hidden_region.kind() {
                ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
                    explain_free_region(tcx, &mut err, generic_param_scope,
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("hidden type `{0}` captures ",
                                            hidden_ty))
                                }), hidden_region, "");
                    if let Some(_) =
                            tcx.is_suitable_region(generic_param_scope, hidden_region) {
                        suggest_precise_capturing(tcx, generic_param_scope,
                            opaque_ty_key.def_id, hidden_ty.value, hidden_region,
                            &mut err);
                    }
                }
                ty::RePlaceholder(_) => {
                    explain_free_region(tcx, &mut err, generic_param_scope,
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("hidden type `{0}` captures ",
                                            hidden_ty))
                                }), hidden_region, "");
                }
                ty::ReError(_) => { err.downgrade_to_delayed_bug(); }
                _ => {
                    note_and_explain_region(tcx, &mut err, generic_param_scope,
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("hidden type `{0}` captures ",
                                            hidden_ty))
                                }), hidden_region, "", None);
                }
            }
            err
        }
    }
}#[instrument(level = "trace", skip(infcx))]
1332pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>(
1333    infcx: &'a InferCtxt<'tcx>,
1334    generic_param_scope: LocalDefId,
1335    span: Span,
1336    hidden_ty: Ty<'tcx>,
1337    hidden_region: ty::Region<'tcx>,
1338    opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
1339) -> Diag<'a> {
1340    let tcx = infcx.tcx;
1341    let mut err = infcx.dcx().create_err(diagnostics::OpaqueCapturesLifetime {
1342        span,
1343        opaque_ty: Ty::new_opaque(
1344            tcx,
1345            ty::IsRigid::No,
1346            opaque_ty_key.def_id.to_def_id(),
1347            opaque_ty_key.args,
1348        ),
1349        opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
1350    });
1351    let mut highlight = RegionHighlightMode::default();
1352    highlight.keep_regions = true;
1353    let hidden_ty = Highlighted { highlight, ns: Namespace::TypeNS, tcx, value: hidden_ty };
1354
1355    // Explain the region we are capturing.
1356    match hidden_region.kind() {
1357        ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
1358            // Assuming regionck succeeded (*), we ought to always be
1359            // capturing *some* region from the fn header, and hence it
1360            // ought to be free. So under normal circumstances, we will go
1361            // down this path which gives a decent human readable
1362            // explanation.
1363            //
1364            // (*) if not, the `tainted_by_errors` field would be set to
1365            // `Some(ErrorGuaranteed)` in any case, so we wouldn't be here at all.
1366            explain_free_region(
1367                tcx,
1368                &mut err,
1369                generic_param_scope,
1370                &format!("hidden type `{hidden_ty}` captures "),
1371                hidden_region,
1372                "",
1373            );
1374            if let Some(_) = tcx.is_suitable_region(generic_param_scope, hidden_region) {
1375                suggest_precise_capturing(
1376                    tcx,
1377                    generic_param_scope,
1378                    opaque_ty_key.def_id,
1379                    hidden_ty.value,
1380                    hidden_region,
1381                    &mut err,
1382                );
1383            }
1384        }
1385        ty::RePlaceholder(_) => {
1386            explain_free_region(
1387                tcx,
1388                &mut err,
1389                generic_param_scope,
1390                &format!("hidden type `{}` captures ", hidden_ty),
1391                hidden_region,
1392                "",
1393            );
1394        }
1395        ty::ReError(_) => {
1396            err.downgrade_to_delayed_bug();
1397        }
1398        _ => {
1399            // Ugh. This is a painful case: the hidden region is not one
1400            // that we can easily summarize or explain. This can happen
1401            // in a case like
1402            // `tests/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
1403            //
1404            // ```
1405            // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
1406            //   if condition() { a } else { b }
1407            // }
1408            // ```
1409            //
1410            // Here the captured lifetime is the intersection of `'a` and
1411            // `'b`, which we can't quite express.
1412
1413            // We can at least report a really cryptic error for now.
1414            note_and_explain_region(
1415                tcx,
1416                &mut err,
1417                generic_param_scope,
1418                &format!("hidden type `{hidden_ty}` captures "),
1419                hidden_region,
1420                "",
1421                None,
1422            );
1423        }
1424    }
1425
1426    err
1427}
1428
1429fn suggest_precise_capturing<'tcx>(
1430    tcx: TyCtxt<'tcx>,
1431    generic_param_scope: LocalDefId,
1432    opaque_def_id: LocalDefId,
1433    hidden_ty: Ty<'tcx>,
1434    captured_lifetime: ty::Region<'tcx>,
1435    diag: &mut Diag<'_>,
1436) {
1437    let hir::OpaqueTy { bounds, origin, .. } =
1438        tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
1439
1440    let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } = *origin else {
1441        return;
1442    };
1443
1444    let new_lifetime = Symbol::intern(&captured_lifetime.to_string());
1445
1446    if let Some((args, span)) = bounds.iter().find_map(|bound| match bound {
1447        hir::GenericBound::Use(args, span) => Some((args, span)),
1448        _ => None,
1449    }) {
1450        // '_ is an elision marker, not a lifetime name, so it cannot appear twice in a
1451        // capture list. the branch for opaques with no use<..> yet already skips captured
1452        // lifetimes; do the same here to avoid suggesting use<'_, '_>.
1453        if args.iter().any(|arg| {
1454            #[allow(non_exhaustive_omitted_patterns)] match arg {
    hir::PreciseCapturingArg::Lifetime(lt) if lt.ident.name == new_lifetime =>
        true,
    _ => false,
}matches!(arg, hir::PreciseCapturingArg::Lifetime(lt) if lt.ident.name == new_lifetime)
1455        }) {
1456            return;
1457        }
1458
1459        let last_lifetime_span = args.iter().rev().find_map(|arg| match arg {
1460            hir::PreciseCapturingArg::Lifetime(lt) => Some(lt.ident.span),
1461            _ => None,
1462        });
1463
1464        let first_param_span = args.iter().find_map(|arg| match arg {
1465            hir::PreciseCapturingArg::Param(p) => Some(p.ident.span),
1466            _ => None,
1467        });
1468
1469        let (span, pre, post) = if let Some(last_lifetime_span) = last_lifetime_span {
1470            (last_lifetime_span.shrink_to_hi(), ", ", "")
1471        } else if let Some(first_param_span) = first_param_span {
1472            (first_param_span.shrink_to_lo(), "", ", ")
1473        } else {
1474            // If we have no args, then have `use<>` and need to fall back to using
1475            // span math. This sucks, but should be reliable due to the construction
1476            // of the `use<>` span.
1477            (span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), "", "")
1478        };
1479
1480        diag.subdiagnostic(diagnostics::AddPreciseCapturing::Existing {
1481            span,
1482            new_lifetime,
1483            pre,
1484            post,
1485        });
1486    } else {
1487        let mut captured_lifetimes = FxIndexSet::default();
1488        let mut captured_non_lifetimes = FxIndexSet::default();
1489
1490        let variances = tcx.variances_of(opaque_def_id);
1491        let mut generics = tcx.generics_of(opaque_def_id);
1492        let mut synthetics = ::alloc::vec::Vec::new()vec![];
1493        loop {
1494            for param in &generics.own_params {
1495                if variances[param.index as usize] == ty::Bivariant {
1496                    continue;
1497                }
1498
1499                match param.kind {
1500                    ty::GenericParamDefKind::Lifetime => {
1501                        captured_lifetimes.insert(param.name);
1502                    }
1503                    ty::GenericParamDefKind::Type { synthetic: true, .. } => {
1504                        synthetics.push((tcx.def_span(param.def_id), param.name));
1505                    }
1506                    ty::GenericParamDefKind::Type { .. }
1507                    | ty::GenericParamDefKind::Const { .. } => {
1508                        captured_non_lifetimes.insert(param.name);
1509                    }
1510                }
1511            }
1512
1513            if let Some(parent) = generics.parent {
1514                generics = tcx.generics_of(parent);
1515            } else {
1516                break;
1517            }
1518        }
1519
1520        if captured_lifetimes.contains(&new_lifetime) {
1521            // Uh, strange. This lifetime appears to already be captured...
1522            return;
1523        }
1524
1525        let mut next_fresh_param = || {
1526            ['T', 'U', 'V', 'W', 'X', 'Y', 'A', 'B', 'C']
1527                .into_iter()
1528                .map(sym::character)
1529                .chain((0..).map(|i| Symbol::intern(&::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("T{0}", i)) })format!("T{i}"))))
1530                .find(|s| captured_non_lifetimes.insert(*s))
1531                .unwrap()
1532        };
1533
1534        let mut new_params = String::new();
1535        let mut suggs = ::alloc::vec::Vec::new()vec![];
1536        let mut apit_spans = ::alloc::vec::Vec::new()vec![];
1537
1538        for (i, (span, name)) in synthetics.into_iter().enumerate() {
1539            apit_spans.push(span);
1540
1541            let fresh_param = next_fresh_param();
1542
1543            // Suggest renaming.
1544            suggs.push((span, fresh_param.to_string()));
1545
1546            // Super jank. Turn `impl Trait` into `T: Trait`.
1547            //
1548            // This currently involves stripping the `impl` from the name of
1549            // the parameter, since APITs are always named after how they are
1550            // rendered in the AST. This sucks! But to recreate the bound list
1551            // from the APIT itself would be miserable, so we're stuck with
1552            // this for now!
1553            if i > 0 {
1554                new_params += ", ";
1555            }
1556            let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
1557            new_params += fresh_param.as_str();
1558            new_params += ": ";
1559            new_params += name_as_bounds;
1560        }
1561
1562        // `'_` in a capture list only resolves when the signature has a single anonymous
1563        // lifetime, so when there are several the suggestion has to name them first.
1564        let named_suggs = name_anon_lifetimes_suggestion(
1565            tcx,
1566            generic_param_scope,
1567            opaque_def_id,
1568            fn_def_id,
1569            hidden_ty,
1570            &captured_lifetimes,
1571            &captured_non_lifetimes,
1572        )
1573        // a lifetime inside an APIT bound gets its own replacement part from
1574        // `LifetimeReplaceVisitor`, whose span falls inside the APIT span. overlapping parts in one
1575        // multipart suggestion panic the emitter, so the filter drops the whole named suggestion
1576        // and falls back to `'_`.
1577        .filter(|named| {
1578            !named.iter().any(|(span, _)| apit_spans.iter().any(|apit| apit.overlaps(*span)))
1579        });
1580
1581        if apit_spans.is_empty() {
1582            if let Some(suggs) = named_suggs {
1583                diag.subdiagnostic(diagnostics::AddPreciseCapturingAndNameLifetimes { suggs });
1584                return;
1585            }
1586
1587            captured_lifetimes.insert(new_lifetime);
1588
1589            let concatenated_bounds = captured_lifetimes
1590                .into_iter()
1591                .chain(captured_non_lifetimes)
1592                .map(|sym| sym.to_string())
1593                .collect::<Vec<_>>()
1594                .join(", ");
1595
1596            diag.subdiagnostic(diagnostics::AddPreciseCapturing::New {
1597                span: tcx.def_span(opaque_def_id).shrink_to_hi(),
1598                new_lifetime,
1599                concatenated_bounds,
1600            });
1601        } else {
1602            let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
1603                // This shouldn't happen, but don't ICE.
1604                return;
1605            };
1606
1607            let names_lifetimes = named_suggs.is_some();
1608            if let Some(named) = named_suggs {
1609                suggs.extend(named);
1610            } else {
1611                captured_lifetimes.insert(new_lifetime);
1612
1613                let concatenated_bounds = captured_lifetimes
1614                    .into_iter()
1615                    .chain(captured_non_lifetimes)
1616                    .map(|sym| sym.to_string())
1617                    .collect::<Vec<_>>()
1618                    .join(", ");
1619
1620                suggs.push((
1621                    tcx.def_span(opaque_def_id).shrink_to_hi(),
1622                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + use<{0}>", concatenated_bounds))
    })format!(" + use<{concatenated_bounds}>"),
1623                ));
1624            }
1625
1626            // Add generics or concatenate to the end of the list.
1627            if let Some(params_span) = generics.span_for_param_suggestion() {
1628                suggs.push((params_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", new_params))
    })format!(", {new_params}")));
1629            } else if let Some((_, new_lifetimes)) =
1630                suggs.iter_mut().find(|(span, _)| *span == generics.span)
1631            {
1632                // `suggest_name_regions` already pushed `<'a, 'b>` at `generics.span`, so a second
1633                // part at the same empty span cannot apply. the type params are spliced into the
1634                // existing string, with lifetimes first because the grammar requires it.
1635                *new_lifetimes = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, {1}>",
                new_lifetimes.trim_end_matches('>'), new_params))
    })format!("{}, {new_params}>", new_lifetimes.trim_end_matches('>'));
1636            } else {
1637                suggs.push((generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", new_params))
    })format!("<{new_params}>")));
1638            }
1639
1640            if names_lifetimes {
1641                diag.subdiagnostic(diagnostics::AddPreciseCapturingNameLifetimesAndParams {
1642                    suggs,
1643                    apit_spans,
1644                });
1645            } else {
1646                diag.subdiagnostic(diagnostics::AddPreciseCapturingAndParams {
1647                    suggs,
1648                    new_lifetime,
1649                    apit_spans,
1650                });
1651            }
1652        }
1653    }
1654}
1655
1656/// Build a suggestion that names every anonymous lifetime the hidden type captures and then
1657/// lists them in a `use<..>` bound.
1658///
1659/// This exists because a `use<..>` list cannot refer to more than one anonymous lifetime: `'_`
1660/// resolves like any other elided lifetime, so with several in the signature it either picks the
1661/// wrong one or fails to resolve at all. Naming them is the only way to write the bound the hidden
1662/// type actually needs.
1663///
1664/// Returns `None` whenever the plain `'_` suggestion is still correct, so that the common
1665/// single-lifetime case keeps its shorter form.
1666fn name_anon_lifetimes_suggestion<'tcx>(
1667    tcx: TyCtxt<'tcx>,
1668    generic_param_scope: LocalDefId,
1669    opaque_def_id: LocalDefId,
1670    fn_def_id: LocalDefId,
1671    hidden_ty: Ty<'tcx>,
1672    captured_lifetimes: &FxIndexSet<Symbol>,
1673    captured_non_lifetimes: &FxIndexSet<Symbol>,
1674) -> Option<Vec<(Span, String)>> {
1675    let fn_sig = tcx.hir_node_by_def_id(fn_def_id).fn_sig()?;
1676
1677    let mut collector = AnonLifetimeCollector { tcx, anon_lifetimes: Default::default() };
1678    for input in fn_sig.decl.inputs {
1679        collector.visit_ty_unambig(input);
1680    }
1681    // With a single anonymous lifetime in the signature `'_` resolves to it, so leave that case
1682    // to the caller.
1683    if collector.anon_lifetimes.len() < 2 {
1684        return None;
1685    }
1686
1687    let mut hidden_regions = FxIndexMap::default();
1688    tcx.for_each_free_region(&hidden_ty, |region| {
1689        if let Some(info) = tcx.is_suitable_region(generic_param_scope, region) {
1690            hidden_regions.entry(info.region_def_id).or_insert(region);
1691        }
1692    });
1693
1694    // A lifetime the user already named stays as it is; only the anonymous ones need inventing
1695    // a name, and they are named in the order they appear in the signature.
1696    let named = hidden_regions
1697        .iter()
1698        .filter(|(def_id, _)| !collector.anon_lifetimes.contains(*def_id))
1699        .map(|(_, &region)| region);
1700    let anon: Vec<_> = collector
1701        .anon_lifetimes
1702        .iter()
1703        .filter_map(|def_id| hidden_regions.get(def_id).copied())
1704        .collect();
1705    if anon.is_empty() {
1706        return None;
1707    }
1708    let regions: Vec<_> = named.chain(anon).collect();
1709
1710    let mut suggs = ::alloc::vec::Vec::new()vec![];
1711    let mut bounds = captured_lifetimes.clone();
1712    bounds.extend(
1713        suggest_name_regions(tcx, generic_param_scope, &regions, &mut suggs)?
1714            .iter()
1715            .map(|name| Symbol::intern(name)),
1716    );
1717
1718    let concatenated_bounds = bounds
1719        .into_iter()
1720        .chain(captured_non_lifetimes.iter().copied())
1721        .map(|sym| sym.to_string())
1722        .collect::<Vec<_>>()
1723        .join(", ");
1724    suggs.push((
1725        tcx.def_span(opaque_def_id).shrink_to_hi(),
1726        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + use<{0}>", concatenated_bounds))
    })format!(" + use<{concatenated_bounds}>"),
1727    ));
1728
1729    Some(suggs)
1730}
1731
1732/// Collects every anonymous lifetime written in a function signature.
1733struct AnonLifetimeCollector<'tcx> {
1734    tcx: TyCtxt<'tcx>,
1735    anon_lifetimes: FxIndexSet<DefId>,
1736}
1737
1738impl<'tcx> Visitor<'tcx> for AnonLifetimeCollector<'tcx> {
1739    type NestedFilter = nested_filter::OnlyBodies;
1740
1741    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1742        self.tcx
1743    }
1744
1745    fn visit_lifetime(&mut self, lifetime: &'tcx hir::Lifetime) {
1746        if lifetime.is_anonymous()
1747            && let Some(
1748                rbv::ResolvedArg::EarlyBound(def_id) | rbv::ResolvedArg::LateBound(_, _, def_id),
1749            ) = self.tcx.named_bound_var(lifetime.hir_id)
1750        {
1751            self.anon_lifetimes.insert(def_id.to_def_id());
1752        }
1753    }
1754}