Skip to main content

rustc_trait_selection/error_reporting/infer/nice_region_error/
static_impl_trait.rs

1//! Error Reporting for static impl Traits.
2
3use rustc_data_structures::fx::FxIndexSet;
4use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
5use rustc_hir::def_id::DefId;
6use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
7use rustc_hir::{
8    self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime,
9    LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
10};
11use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
12use rustc_span::def_id::LocalDefId;
13use rustc_span::{Ident, Span};
14use tracing::debug;
15
16use crate::diagnostics::ButNeedsToSatisfy;
17use crate::error_reporting::infer::nice_region_error::NiceRegionError;
18use crate::infer::{RegionResolutionError, SubregionOrigin};
19
20impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
21    /// Print the error message for lifetime errors when the return type is a static `impl Trait`,
22    /// `dyn Trait` or if a method call on a trait object introduces a static requirement.
23    pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
24        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:24",
                        "rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(24u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait(error={0:?})",
                                                    self.error) as &dyn Value))])
            });
    } else { ; }
};debug!("try_report_static_impl_trait(error={:?})", self.error);
25        let tcx = self.tcx();
26        let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
27            RegionResolutionError::SubSupConflict(
28                _,
29                var_origin,
30                sub_origin,
31                sub_r,
32                sup_origin,
33                sup_r,
34                spans,
35            ) if sub_r.is_static() => (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans),
36            _ => return None,
37        };
38        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:38",
                        "rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(38u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait(var={0:?}, sub={1:?} {2:?} sup={3:?} {4:?})",
                                                    var_origin, sub_origin, sub_r, sup_origin, sup_r) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(
39            "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
40            var_origin, sub_origin, sub_r, sup_origin, sup_r
41        );
42        let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
43        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:43",
                        "rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(43u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: anon_reg_sup={0:?}",
                                                    anon_reg_sup) as &dyn Value))])
            });
    } else { ; }
};debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
44        let sp = var_origin.span();
45        let return_sp = sub_origin.span();
46        let param = self.find_param_with_region(*sup_r, *sub_r)?;
47        let simple_ident = param.param.pat.simple_ident();
48        let lifetime_name =
49            if sup_r.is_named(self.tcx()) { sup_r.to_string() } else { "'_".to_owned() };
50
51        let (mention_influencer, influencer_point) =
52            if sup_origin.span().overlaps(param.param_ty_span) {
53                // Account for `async fn` like in `async-await/issues/issue-62097.rs`.
54                // The desugaring of `async fn`s causes `sup_origin` and `param` to point at the same
55                // place (but with different `ctxt`, hence `overlaps` instead of `==` above).
56                //
57                // This avoids the following:
58                //
59                // LL |     pub async fn run_dummy_fn(&self) {
60                //    |                               ^^^^^
61                //    |                               |
62                //    |                               this data with an anonymous lifetime `'_`...
63                //    |                               ...is captured here...
64                (false, sup_origin.span())
65            } else {
66                (!sup_origin.span().overlaps(return_sp), param.param_ty_span)
67            };
68
69        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:69",
                        "rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(69u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: param_info={0:?}",
                                                    param) as &dyn Value))])
            });
    } else { ; }
};debug!("try_report_static_impl_trait: param_info={:?}", param);
70
71        let mut spans = spans.clone();
72
73        if mention_influencer {
74            spans.push(sup_origin.span());
75        }
76        // We dedup the spans *ignoring* expansion context.
77        spans.sort();
78        spans.dedup_by_key(|span| (span.lo(), span.hi()));
79
80        // We try to make the output have fewer overlapping spans if possible.
81        let require_span =
82            if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
83
84        let spans_empty = spans.is_empty();
85        let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp);
86        let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
87            Some(*bound)
88        } else {
89            None
90        };
91
92        let diag = ButNeedsToSatisfy {
93            sp,
94            influencer_point,
95            spans: spans.clone(),
96            // If any of the "captured here" labels appears on the same line or after
97            // `require_span`, we put it on a note to ensure the text flows by appearing
98            // always at the end.
99            require_span_as_note: require_as_note.then_some(require_span),
100            // We don't need a note, it's already at the end, it can be shown as a `span_label`.
101            require_span_as_label: (!require_as_note).then_some(require_span),
102
103            has_lifetime: sup_r.is_named(self.tcx()),
104            lifetime: lifetime_name.clone(),
105            has_param_name: simple_ident.is_some(),
106            param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
107            spans_empty,
108            bound,
109        };
110
111        let mut err = self.tcx().dcx().create_err(diag);
112
113        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.scope);
114
115        let arg = match param.param.pat.simple_ident() {
116            Some(simple_ident) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument `{0}`", simple_ident))
    })format!("argument `{simple_ident}`"),
117            None => "the argument".to_string(),
118        };
119        let captures = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("captures data from {0}", arg))
    })format!("captures data from {arg}");
120        suggest_new_region_bound(
121            tcx,
122            &mut err,
123            fn_returns,
124            lifetime_name,
125            Some(arg),
126            captures,
127            Some((param.param_ty_span, param.param_ty.to_string())),
128            Some(anon_reg_sup.scope),
129        );
130
131        let reported = err.emit();
132        Some(reported)
133    }
134}
135
136pub fn suggest_new_region_bound(
137    tcx: TyCtxt<'_>,
138    err: &mut Diag<'_>,
139    fn_returns: Vec<&rustc_hir::Ty<'_>>,
140    lifetime_name: String,
141    arg: Option<String>,
142    captures: String,
143    param: Option<(Span, String)>,
144    scope_def_id: Option<LocalDefId>,
145) {
146    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:146",
                        "rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(146u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: fn_return={0:?}",
                                                    fn_returns) as &dyn Value))])
            });
    } else { ; }
};debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
147    // FIXME: account for the need of parens in `&(dyn Trait + '_)`
148    let consider = "consider changing";
149    let declare = "to declare that";
150    let explicit = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you can add an explicit `{0}` lifetime bound",
                lifetime_name))
    })format!("you can add an explicit `{lifetime_name}` lifetime bound");
151    let explicit_static =
152        arg.map(|arg| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("explicit `\'static` bound to the lifetime of {0}",
                arg))
    })format!("explicit `'static` bound to the lifetime of {arg}"));
153    let add_static_bound = "alternatively, add an explicit `'static` bound to this reference";
154    let plus_lt = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}", lifetime_name))
    })format!(" + {lifetime_name}");
155    for fn_return in fn_returns {
156        if fn_return.span.desugaring_kind().is_some() {
157            // Skip `async` desugaring `impl Future`.
158            continue;
159        }
160        match fn_return.kind {
161            // FIXME(precise_captures): Suggest adding to `use<...>` list instead.
162            TyKind::OpaqueDef(opaque) => {
163                // Get the identity type for this RPIT
164                let did = opaque.def_id.to_def_id();
165                let ty = Ty::new_opaque(
166                    tcx,
167                    ty::IsRigid::No,
168                    did,
169                    ty::GenericArgs::identity_for_item(tcx, did),
170                );
171
172                if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
173                    GenericBound::Outlives(Lifetime {
174                        kind: LifetimeKind::Static, ident, ..
175                    }) => Some(ident.span),
176                    _ => None,
177                }) {
178                    if let Some(explicit_static) = &explicit_static {
179                        err.span_suggestion_verbose(
180                            span,
181                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}`\'s {2}", consider, ty,
                explicit_static))
    })format!("{consider} `{ty}`'s {explicit_static}"),
182                            &lifetime_name,
183                            Applicability::MaybeIncorrect,
184                        );
185                    }
186                    if let Some((param_span, ref param_ty)) = param {
187                        err.span_suggestion_verbose(
188                            param_span,
189                            add_static_bound,
190                            param_ty,
191                            Applicability::MaybeIncorrect,
192                        );
193                    }
194                } else if opaque.bounds.iter().any(|arg| {
195                    #[allow(non_exhaustive_omitted_patterns)] match arg {
    GenericBound::Outlives(Lifetime { ident, .. }) if
        ident.name.to_string() == lifetime_name => true,
    _ => false,
}matches!(arg,
196                        GenericBound::Outlives(Lifetime { ident, .. })
197                        if ident.name.to_string() == lifetime_name )
198                }) {
199                } else {
200                    // get a lifetime name of existing named lifetimes if any
201                    let existing_lt_name = if let Some(id) = scope_def_id
202                        && let Some(generics) = tcx.hir_get_generics(id)
203                        && let named_lifetimes = generics
204                            .params
205                            .iter()
206                            .filter(|p| {
207                                #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } =>
        true,
    _ => false,
}matches!(
208                                    p.kind,
209                                    GenericParamKind::Lifetime {
210                                        kind: hir::LifetimeParamKind::Explicit
211                                    }
212                                )
213                            })
214                            .map(|p| {
215                                if let hir::ParamName::Plain(name) = p.name {
216                                    Some(name.to_string())
217                                } else {
218                                    None
219                                }
220                            })
221                            .filter(|n| !#[allow(non_exhaustive_omitted_patterns)] match n {
    None => true,
    _ => false,
}matches!(n, None))
222                            .collect::<Vec<_>>()
223                        && named_lifetimes.len() > 0
224                    {
225                        named_lifetimes[0].clone()
226                    } else {
227                        None
228                    };
229                    let name = if let Some(name) = &existing_lt_name { name } else { "'a" };
230                    // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used.
231                    // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any
232                    if let Some(id) = scope_def_id
233                        && let Some(generics) = tcx.hir_get_generics(id)
234                        && let mut spans_suggs =
235                            make_elided_region_spans_suggs(name, generics.params.iter())
236                        && spans_suggs.len() > 1
237                    {
238                        let use_lt = if existing_lt_name == None {
239                            spans_suggs.push((generics.span.shrink_to_hi(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", name))
    })format!("<{name}>")));
240                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you can introduce a named lifetime parameter `{0}`",
                name))
    })format!("you can introduce a named lifetime parameter `{name}`")
241                        } else {
242                            // make use the existing named lifetime
243                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you can use the named lifetime parameter `{0}`",
                name))
    })format!("you can use the named lifetime parameter `{name}`")
244                        };
245                        spans_suggs.push((fn_return.span.shrink_to_hi(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0} ", name))
    })format!(" + {name} ")));
246                        err.multipart_suggestion(
247                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}` {2}, {3}", declare, ty,
                captures, use_lt))
    })format!("{declare} `{ty}` {captures}, {use_lt}"),
248                            spans_suggs,
249                            Applicability::MaybeIncorrect,
250                        );
251                    } else {
252                        err.span_suggestion_verbose(
253                            fn_return.span.shrink_to_hi(),
254                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}` {2}, {3}", declare, ty,
                captures, explicit))
    })format!("{declare} `{ty}` {captures}, {explicit}"),
255                            &plus_lt,
256                            Applicability::MaybeIncorrect,
257                        );
258                    }
259                }
260            }
261            TyKind::TraitObject(_, lt) => {
262                if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind {
263                    err.span_suggestion_verbose(
264                        fn_return.span.shrink_to_hi(),
265                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} the trait object {1}, {2}",
                declare, captures, explicit))
    })format!("{declare} the trait object {captures}, {explicit}"),
266                        &plus_lt,
267                        Applicability::MaybeIncorrect,
268                    );
269                } else if lt.ident.name.to_string() != lifetime_name {
270                    // With this check we avoid suggesting redundant bounds. This
271                    // would happen if there are nested impl/dyn traits and only
272                    // one of them has the bound we'd suggest already there, like
273                    // in `impl Foo<X = dyn Bar> + '_`.
274                    if let Some(explicit_static) = &explicit_static {
275                        err.span_suggestion_verbose(
276                            lt.ident.span,
277                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} the trait object\'s {1}",
                consider, explicit_static))
    })format!("{consider} the trait object's {explicit_static}"),
278                            &lifetime_name,
279                            Applicability::MaybeIncorrect,
280                        );
281                    }
282                    if let Some((param_span, param_ty)) = param.clone() {
283                        err.span_suggestion_verbose(
284                            param_span,
285                            add_static_bound,
286                            param_ty,
287                            Applicability::MaybeIncorrect,
288                        );
289                    }
290                }
291            }
292            _ => {}
293        }
294    }
295}
296
297fn make_elided_region_spans_suggs<'a>(
298    name: &str,
299    generic_params: impl Iterator<Item = &'a GenericParam<'a>>,
300) -> Vec<(Span, String)> {
301    let mut spans_suggs = Vec::new();
302    let mut bracket_span = None;
303    let mut consecutive_brackets = 0;
304
305    let mut process_consecutive_brackets =
306        |span: Option<Span>, spans_suggs: &mut Vec<(Span, String)>| {
307            if let Some(span) = span
308                && bracket_span.is_none_or(|bracket_span| span == bracket_span)
309            {
310                consecutive_brackets += 1;
311            } else if let Some(bracket_span) = bracket_span.take() {
312                let sugg = std::iter::once("<")
313                    .chain(std::iter::repeat_n(name, consecutive_brackets).intersperse(", "))
314                    .chain([">"])
315                    .collect();
316                spans_suggs.push((bracket_span.shrink_to_hi(), sugg));
317                consecutive_brackets = 0;
318            }
319            bracket_span = span;
320        };
321
322    for p in generic_params {
323        if let GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(kind) } = p.kind {
324            match kind {
325                MissingLifetimeKind::Underscore => {
326                    process_consecutive_brackets(None, &mut spans_suggs);
327                    spans_suggs.push((p.span, name.to_string()))
328                }
329                MissingLifetimeKind::Ampersand => {
330                    process_consecutive_brackets(None, &mut spans_suggs);
331                    spans_suggs.push((p.span.shrink_to_hi(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} ", name))
    })format!("{name} ")));
332                }
333                MissingLifetimeKind::Comma => {
334                    process_consecutive_brackets(None, &mut spans_suggs);
335                    spans_suggs.push((p.span.shrink_to_hi(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", name))
    })format!("{name}, ")));
336                }
337                MissingLifetimeKind::Brackets => {
338                    process_consecutive_brackets(Some(p.span), &mut spans_suggs);
339                }
340            }
341        }
342    }
343    process_consecutive_brackets(None, &mut spans_suggs);
344
345    spans_suggs
346}
347
348impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
349    pub fn get_impl_ident_and_self_ty_from_trait(
350        tcx: TyCtxt<'tcx>,
351        def_id: DefId,
352        trait_objects: &FxIndexSet<DefId>,
353    ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
354        match tcx.hir_get_if_local(def_id)? {
355            Node::ImplItem(impl_item) => {
356                let impl_did = tcx.hir_get_parent_item(impl_item.hir_id());
357                if let hir::OwnerNode::Item(Item {
358                    kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
359                    ..
360                }) = tcx.hir_owner_node(impl_did)
361                {
362                    Some((impl_item.ident, self_ty))
363                } else {
364                    None
365                }
366            }
367            Node::TraitItem(trait_item) => {
368                let trait_id = tcx.hir_get_parent_item(trait_item.hir_id());
369                if true {
    {
        match (&tcx.def_kind(trait_id.def_id), &hir::def::DefKind::Trait) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait);
370                // The method being called is defined in the `trait`, but the `'static`
371                // obligation comes from the `impl`. Find that `impl` so that we can point
372                // at it in the suggestion.
373                let trait_did = trait_id.to_def_id();
374                tcx.local_trait_impls(trait_did).iter().find_map(|&impl_did| {
375                    if let Node::Item(Item {
376                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
377                    }) = tcx.hir_node_by_def_id(impl_did)
378                        && trait_objects.iter().all(|did| {
379                            // FIXME: we should check `self_ty`, but for now, use
380                            // this imperfect proxy. This will fail if there are
381                            // multiple `impl`s for the same trait like
382                            // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
383                            // In that case, only the first one will get suggestions.
384                            let mut traits = ::alloc::vec::Vec::new()vec![];
385                            let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
386                            hir_v.visit_ty_unambig(self_ty);
387                            !traits.is_empty()
388                        })
389                    {
390                        Some((trait_item.ident, *self_ty))
391                    } else {
392                        None
393                    }
394                })
395            }
396            _ => None,
397        }
398    }
399}
400
401/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
402pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
403
404impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
405    fn visit_ty(&mut self, t: Ty<'tcx>) {
406        match t.kind() {
407            ty::Dynamic(preds, re) if re.is_static() => {
408                if let Some(def_id) = preds.principal_def_id() {
409                    self.0.insert(def_id);
410                }
411            }
412            _ => t.super_visit_with(self),
413        }
414    }
415}
416
417/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
418pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
419
420impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
421    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) {
422        if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind
423            && let Lifetime { kind: LifetimeKind::ImplicitObjectLifetimeDefault, .. } =
424                lifetime_ptr.pointer()
425        {
426            for ptr in poly_trait_refs {
427                if Some(self.1) == ptr.trait_ref.trait_def_id() {
428                    self.0.push(ptr.span);
429                }
430            }
431        }
432        walk_ty(self, t);
433    }
434}