Skip to main content

rustc_trait_selection/traits/
outlives_for_liveness.rs

1use rustc_data_structures::fx::FxIndexSet;
2use rustc_hir::def::DefKind;
3use rustc_hir::def_id::{DefId, LocalDefId};
4use rustc_middle::bug;
5use rustc_middle::ty::{
6    self, Flags, ImplTraitInTraitData, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
7    TypeVisitableExt, TypeVisitor,
8};
9
10use crate::infer::outlives::test_type_match;
11use crate::infer::region_constraints::VerifyIfEq;
12use crate::regions::{region_known_to_outlive, ty_known_to_outlive};
13
14/// For a given alias type, this returns the set of (identity) generic args that
15/// are relevant for liveness, that can be inferred from outlives bounds on the
16/// alias itself, and the explicit and implicit outlives clauses of the alias.
17/// Callers should instantiate the returned args with the concrete args of the alias.
18///
19/// There are three cases to consider:
20/// 1. If there are *no* outlives bounds, then we return None.
21/// 2. If there is a `'static` outlives bound, then we know that all args are
22///    irrelevant, so we return an empty list.
23/// 3. If there are *any* outlives bounds, then we find any args that are known
24///    to outlive those bounds, since those are the args whose regions the
25///    underlying type could capture.
26x;#[tracing::instrument(level = "debug", skip(tcx), ret)]
27pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>(
28    tcx: TyCtxt<'tcx>,
29    kind: ty::AliasTyKind<'tcx>,
30) -> Option<ty::EarlyBinder<'tcx, Vec<ty::GenericArg<'tcx>>>> {
31    let def_id = match kind {
32        ty::AliasTyKind::Projection { def_id }
33        | ty::AliasTyKind::Inherent { def_id }
34        | ty::AliasTyKind::Opaque { def_id }
35        | ty::AliasTyKind::Free { def_id } => def_id,
36    };
37    let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
38
39    // We first want to collect the outlives bounds of the alias.
40    let bounds = tcx.item_bounds(def_id).instantiate_identity().skip_norm_wip();
41    tracing::debug!(?bounds);
42    let alias_ty = Ty::new_alias(
43        tcx,
44        ty::IsRigid::No,
45        ty::AliasTy::new_from_args(tcx, kind, self_identity_args),
46    );
47    let outlives_regions: Vec<_> = bounds
48        .iter()
49        .filter_map(|clause| {
50            let outlives = clause.as_type_outlives_clause()?;
51            if let Some(outlives) = outlives.no_bound_vars()
52                && outlives.0 == alias_ty
53            {
54                Some(outlives.1)
55            } else {
56                test_type_match::extract_verify_if_eq(
57                    tcx,
58                    &outlives
59                        .map_bound(|ty::OutlivesPredicate(ty, bound)| VerifyIfEq { ty, bound }),
60                    // FIXME(#155345): Region handling should generally only
61                    // deal with rigid aliases, making sure we do so correctly
62                    // everywhere is effort, so we're just using `No` everywhere
63                    // for now. This should change soon.
64                    alias_ty,
65                )
66            }
67        })
68        .collect();
69    tracing::debug!(?outlives_regions);
70
71    // If there are no outlives bounds, then all (non-bivariant) args are potentially live.
72    if outlives_regions.is_empty() {
73        return None;
74    }
75
76    // If any of the outlives bounds are `'static`, then we know the alias
77    // doesn't capture *any* regions, so we can skip visiting any regions at all.
78    //
79    // I was originally a bit concerned about something like `'a: 'static`, and
80    // whether or not we need to mark `'a` as live. I don't think that we do.
81    //
82    // To dig in a bit: Think about the function using this alias. For the alias
83    // to be well-formed, then it must be proven that the arg (`'a` in this case)
84    // outlives `'static`. Well, if that is proven *once*, then it must be true
85    // across the entire function (because `'static` is free).
86    //
87    // I think this similarly applies to any other free region, like `'a: 'b`
88    // where `'b` is *also* free. Though, we of course can't know *here* which
89    // regions are going to be instantiated with free regions.
90    if outlives_regions.contains(&tcx.lifetimes.re_static) {
91        tracing::debug!("alias has a 'static outlives bound, so skipping visiting any regions");
92        return Some(ty::EarlyBinder::bind(tcx, vec![]));
93    }
94
95    // Okay, so we know we have some outlives bounds, and that none of them are `'static`.
96    // Now, we need to find all other potentially-live args, those that outlive
97    // an outlives-bound region. `args_known_to_outlive_alias_params` does this
98    // for us, and in the case of opaques only includes *captured* regions, too.
99
100    let args_known_to_outlive =
101        tcx.args_known_to_outlive_alias_params(def_id).as_ref().skip_binder();
102    tracing::debug!(?args_known_to_outlive);
103    let mut live_args: Option<FxIndexSet<ty::GenericArg<'tcx>>> = None;
104    for outlives_region in outlives_regions {
105        let Some(outlives_params) =
106            args_known_to_outlive.iter().find(|(r, _)| *r == outlives_region)
107        else {
108            continue;
109        };
110        let new_live_args = outlives_params.1.iter().copied().collect();
111        match &mut live_args {
112            None => live_args = Some(new_live_args),
113            Some(prev) => *prev = prev.intersection(&new_live_args).copied().collect(),
114        };
115    }
116    live_args.map(|c| ty::EarlyBinder::bind(tcx, c.into_iter().collect()))
117}
118
119/// For each region param of this alias compute the identity args that are known
120/// to outlive it, given only the alias's declared where-clauses.
121///
122/// Note: for opaques (including synthetic associated types from RPITITs),
123/// the outlives relationships are identified in the context of the *parent*,
124/// since bounds and well-formed types are not lowered.
125// FIXME: this likely should return a `BitSet` instead of a `Vec<Vec<>>`
126x;#[tracing::instrument(level = "debug", skip(tcx), ret)]
127pub(crate) fn args_known_to_outlive_alias_params<'tcx>(
128    tcx: TyCtxt<'tcx>,
129    def_id: LocalDefId,
130) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec<ty::GenericArg<'tcx>>)>> {
131    match tcx.def_kind(def_id) {
132        DefKind::OpaqueTy => args_known_to_outlive_opaque_params(tcx, def_id),
133        DefKind::AssocTy
134            if let Some(ImplTraitInTraitData::Trait { fn_def_id: _, opaque_def_id }) =
135                tcx.opt_rpitit_info(def_id.to_def_id()) =>
136        {
137            args_known_to_outlive_opaque_params(tcx, opaque_def_id.expect_local())
138        }
139        DefKind::AssocTy | DefKind::TyAlias => args_known_to_outlive_non_opaque_params(tcx, def_id),
140        kind => {
141            bug!("improper def_kind {kind:?} passed to `live_args_for_alias_from_outlives_bounds`")
142        }
143    }
144}
145
146/// For each *captured* region of this alias, compute the *captured* identity
147/// args that are known to outlive it, given the definition of the opaque type
148/// in the the *parent* context.
149///
150/// Some examples:
151/// ```ignore (illustrative)
152/// // Returns `[('a, ['a]), ('b, ['b])]`
153/// fn foo<'a, 'b>() -> impl Sized + use<'a, 'b> {}
154///
155/// // Returns `[('a, ['a]), ('b, ['b])]`
156/// fn foo<'a: 'a, 'b>() -> impl Sized + use<'a, 'b> {}
157///
158/// // Returns `[('a, ['a])]`
159/// fn foo<'a, 'b>() -> impl Sized + use<'a> {}
160///
161/// // Returns `[('a, ['a, 'b]), ('b, ['b])]`
162/// fn foo<'a, 'b: 'a>() -> impl Sized + use<'a, 'b> {}
163///
164/// // Returns `[('a, ['a, 'b]), ('b, ['b])]`
165/// fn foo<'a, 'b>(_: &'a &'b ()) -> impl Sized + use<'a, 'b> {}
166/// ```
167///
168/// Importantly:
169///   - *All* captured regions are considered (not just those in outlives bounds)
170///   - It doesn't matter if the captured region is early-bound or late-bound
171x;#[tracing::instrument(level = "debug", skip(tcx), ret)]
172pub(crate) fn args_known_to_outlive_opaque_params<'tcx>(
173    tcx: TyCtxt<'tcx>,
174    def_id: LocalDefId,
175) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec<ty::GenericArg<'tcx>>)>> {
176    let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
177
178    let mut result = Vec::new();
179
180    // For implied bounds, we need the set of WF types from the parents.
181    //  - For functions, this is all the input and output types.
182    //  - For type alias, there are no implied bounds, so this is empty.
183    let (parent_def_id, wf_tys) = match tcx.opaque_ty_origin(def_id) {
184        rustc_hir::OpaqueTyOrigin::FnReturn { parent, .. }
185        | rustc_hir::OpaqueTyOrigin::AsyncFn { parent, .. }
186        | rustc_hir::OpaqueTyOrigin::TyAlias { parent, .. } => {
187            let wf_tys = FxIndexSet::from_iter(
188                tcx.assumed_wf_types(parent.expect_local()).iter().map(|(ty, _)| *ty),
189            );
190            (parent, wf_tys)
191        }
192    };
193    let parent_param_env = tcx.param_env(parent_def_id);
194    tracing::debug!(?parent_param_env);
195
196    // Map the outlives regions to the parent regions.
197    // If we have `fn foo<'a>() -> impl Sized + 'a`, then this gets lowered as
198    // ```ignore (illustrative)
199    // opaque foo_opaque<'a0>: Sized + 'a0;
200    // fn foo<'a>() -> foo::<'a>::foo_opaque<'a> { ... }
201    // ```
202    // This maps `'a0` to `'a`, because that is what will be used to get the
203    // explicit and implied outlives relations.
204    //
205    // I suppose, an alternative way to do this would be iterate through all the
206    // *parent* regions and then find those that are captured. This should be
207    // basically equivalent (except with the added frustration of needing to
208    // build a `Region` from the opaque region's `LocalDefId`).
209    let generics = tcx.generics_of(def_id);
210    let mut parent_outlives_regions = Vec::with_capacity(generics.own_params.len());
211    for opaque_arg in self_identity_args[generics.parent_count..].iter() {
212        let Some(opaque_region) = opaque_arg.as_region() else {
213            continue;
214        };
215        let region_def_id = match opaque_region.kind() {
216            ty::ReEarlyParam(ebr) => generics.param_at(ebr.index as usize, tcx).def_id,
217            _ => panic!("unexpected region `{opaque_region}` in opaque bounds"),
218        };
219        let parent_region =
220            tcx.map_opaque_lifetime_to_parent_lifetime(region_def_id.expect_local());
221        tracing::debug!(?region_def_id, ?parent_region);
222        parent_outlives_regions.push((parent_region, opaque_region));
223    }
224    tracing::debug!(?parent_outlives_regions);
225
226    // For every captured region, we want to consider outlived args from two sources:
227    // 1) *Types*: These come from *parent* generics (and are not duplicated to the opaque)
228    // 2) *Captured Regions*
229    //
230    // In both cases, we need to check known outlives for the *parent* region, because that's where the param_env and wf_tys are.
231    for (parent_outlived_region, opaque_outlived_region) in parent_outlives_regions.iter() {
232        let mut opaque_outlives_args = Vec::with_capacity(self_identity_args.len());
233        for parent_outlives_arg in self_identity_args[..generics.parent_count].iter() {
234            let type_outlives = match parent_outlives_arg.kind() {
235                // Consts don't have any non-static regions
236                ty::GenericArgKind::Const(_) => continue,
237                // Lifetimes should be captured
238                ty::GenericArgKind::Lifetime(_) => continue,
239                ty::GenericArgKind::Type(t) => ty_known_to_outlive(
240                    tcx,
241                    def_id,
242                    parent_param_env,
243                    &wf_tys,
244                    t,
245                    *parent_outlived_region,
246                ),
247            };
248            if !type_outlives {
249                continue;
250            }
251
252            // Types aren't captured, so don't need to map to the opaque
253            opaque_outlives_args.push(*parent_outlives_arg);
254        }
255
256        for &(parent_outlives_region, opaque_region) in parent_outlives_regions.iter() {
257            let region_outlives = parent_outlives_region == *parent_outlived_region
258                || region_known_to_outlive(
259                    tcx,
260                    def_id,
261                    parent_param_env,
262                    &wf_tys,
263                    parent_outlives_region,
264                    *parent_outlived_region,
265                );
266            if !region_outlives {
267                continue;
268            }
269
270            opaque_outlives_args.push(opaque_region.into());
271        }
272
273        result.push((*opaque_outlived_region, opaque_outlives_args));
274    }
275
276    ty::EarlyBinder::bind(tcx, result)
277}
278
279x;#[tracing::instrument(level = "debug", skip(tcx), ret)]
280pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>(
281    tcx: TyCtxt<'tcx>,
282    def_id: LocalDefId,
283) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec<ty::GenericArg<'tcx>>)>> {
284    let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
285    let param_env = tcx.param_env(def_id);
286    tracing::debug!(?param_env);
287    let wf_tys = tcx.assumed_wf_types(def_id).iter().map(|(ty, _)| *ty).collect::<FxIndexSet<_>>();
288    let mut result = Vec::new();
289    for outlived_arg in self_identity_args.iter() {
290        let Some(outlived_region) = outlived_arg.as_region() else {
291            continue;
292        };
293        let outliving_args = self_identity_args
294            .iter()
295            .filter(|arg| match arg.kind() {
296                ty::GenericArgKind::Lifetime(r) => {
297                    region_known_to_outlive(tcx, def_id, param_env, &wf_tys, r, outlived_region)
298                }
299                ty::GenericArgKind::Type(t) => {
300                    ty_known_to_outlive(tcx, def_id, param_env, &wf_tys, t, outlived_region)
301                }
302                ty::GenericArgKind::Const(_) => false,
303            })
304            .collect();
305        result.push((outlived_region, outliving_args));
306    }
307    ty::EarlyBinder::bind(tcx, result)
308}
309
310/// For a param-env clause `for<'v..> <T as Trait>::Assoc<..>: 'bound` that
311/// applies to `ty` (an alias with `alias_def_id`), returns the set of (identity) args
312/// that the underlying type could possibly capture, as restricted by this clause.
313///
314/// As an example, let's imagine we had the following associated type definition:
315/// ```ignore (illustrative)
316/// type Assoc<'a, 'b, 'c: 'a> = (&'a &'c (), &'b ());
317/// ```
318///
319/// the following clause:
320/// ```ignore (illustrative)
321/// for<'x, 'y> T::Assoc<'x, 'x, 'y>: 'x
322/// ```
323///
324/// We know from the clause alone that *given some substitution of `T:Assoc`*,
325/// we know that it can capture either the first or the second region. However,
326/// the bounds on the associated type itself additionally imply that the
327/// third region can *also* be captured, because it outlives the first.
328///
329/// Now, let's assume we had this clause:
330/// ```ignore (illustrative)
331/// for<'x, 'y> T::Assoc<'x, 'y, 'x>: 'x
332/// ```
333///
334/// Here, we know that `'a` and `'c` could be captured, but there is no outlives
335/// relationship to `'b` for either of those, so the underlying type can't
336/// capture any arg containing `'b`.
337///
338/// Note: because higher-ranked bounds don't have implications, there will be
339/// some cases (like `for<'x, 'y, 'z> T::Assoc<'x, 'y, 'z>: 'x`) that won't
340/// be satisfiable today, but the logic here should hold whenever there *is*.
341///
342/// Returns `None` if the clause doesn't apply to `ty` or gives us no information.
343x;#[tracing::instrument(level = "debug", skip(tcx), ret)]
344fn live_args_for_outlives_clause<'tcx>(
345    tcx: TyCtxt<'tcx>,
346    alias_def_id: DefId,
347    ty: Ty<'tcx>,
348    outlives: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
349) -> Option<FxIndexSet<ty::EarlyBinder<'tcx, ty::GenericArg<'tcx>>>> {
350    // N.B. it's okay to skip the binder here (and in the rest of the function),
351    // because all variables under binders do not escape
352    let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) =
353        *outlives.skip_binder().0.kind()
354    else {
355        return None;
356    };
357    let clause_def_id = match clause_alias_kind {
358        ty::AliasTyKind::Projection { def_id }
359        | ty::AliasTyKind::Inherent { def_id }
360        | ty::AliasTyKind::Opaque { def_id }
361        | ty::AliasTyKind::Free { def_id } => def_id,
362    };
363    if clause_def_id != alias_def_id {
364        return None;
365    }
366
367    // Here, we're just using this to check if the clause *could apply* to `ty`,
368    // but importantly we don't want to use the returned region, because that is
369    // the "last visited" region in `ty` that matches the outlves bound. Actually,
370    // we want *all* the identity regions in `ty` that match the outlives bound.
371    test_type_match::extract_verify_if_eq(
372        tcx,
373        &outlives.map_bound(|ty::OutlivesPredicate(ty, bound)| VerifyIfEq { ty, bound }),
374        ty,
375    )?;
376
377    let outlived_region = outlives.skip_binder().1;
378    let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id);
379    match outlived_region.kind() {
380        // The underlying type must outlive `'static`, so it can't capture any of the args at all.
381        //
382        // Of course, you may ask: "what if the function has a `'a: 'static` bound?" See the corresponding
383        // comment in `live_args_for_alias_from_outlives_bounds` for why we don't need to worry about that.
384        ty::ReStatic => Some(FxIndexSet::default()),
385        ty::ReBound(_, br) => {
386            // The bound is one of the clause's higher-ranked vars. Find the arg
387            // positions it occupies, then (at the alias's identity level) find
388            // all args that are known to outlive one of those positions given
389            // the alias's declared bounds -- only those can be captured by the
390            // underlying type.
391            let mut outlived_regions = Vec::new();
392            for (clause_arg, identity_arg) in clause_args.iter().zip(clause_identity_args.iter()) {
393                match clause_arg.kind() {
394                    ty::GenericArgKind::Lifetime(r) => {
395                        if let ty::ReBound(_, arg_br) = r.kind()
396                            && arg_br.var == br.var
397                        {
398                            outlived_regions.push(identity_arg.expect_region());
399                        }
400                    }
401                    ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) => {
402                        // A bound var inside a type or const arg (e.g.
403                        // `for<'a> <F as FnOnce<(&'a mut i32,)>>::Output: 'a`)
404                        // can't be reasoned about at the identity-param level,
405                        // so conservatively treat the clause as giving no
406                        // restriction at all.
407                        if clause_arg.has_escaping_bound_vars() {
408                            return None;
409                        }
410                    }
411                }
412            }
413            if outlived_regions.is_empty() {
414                // The bound var doesn't appear in the args at all, so the clause
415                // requires the underlying type to outlive *every* region, which
416                // is equivalent to a `'static` bound.
417                return Some(FxIndexSet::default());
418            }
419
420            // The underlying type can capture any arg that's known to outlive one
421            // of the bound var's positions (they're all instantiated to the same
422            // region at any use site this clause applies to).
423            let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(alias_def_id);
424            tracing::debug!(?outlived_regions, ?args_known_to_outlive);
425            let mut capturable_args = FxIndexSet::default();
426            for &outlived_region in &outlived_regions {
427                // There's a bit of a dance here around `Earlybinder::skip_binder`
428                // and then later a `Earlybinder::bind`. This is because there's
429                // no real good way today to move the `EarlyBinder` inward
430                // declaratively without cloning the entire thing.
431                let (_, outliving_args) = args_known_to_outlive
432                    .as_ref()
433                    .skip_binder()
434                    .iter()
435                    .find(|(region, _)| *region == outlived_region)
436                    .unwrap();
437                capturable_args
438                    .extend(outliving_args.iter().copied().map(|a| ty::EarlyBinder::bind(tcx, a)));
439            }
440            Some(capturable_args)
441        }
442        // A free region (e.g. `for<a> T::Assoc<'a, 'x>: 'x`, where `'x` is free).
443        // This is effectively the same as `for<'a, 'b> T::Assoc<'a, 'b>: 'b`,
444        // but that only is sound if we either know that the second substituted
445        // lifetime equals `'x` or if we *constrain* that lifetime to be `'x`.
446        //
447        // In either case, something like this doesn't work today:
448        // ```ignore (illustrative)
449        //  fn bar<'a, 'b>(a: &'a mut (), b: &'b ()) -> <Foo as MyTrait>::Assoc<'a, 'b> { b }
450        //  fn foo<'x>()
451        //  where
452        //      for<'h> <Foo as MyTrait>::Assoc<'h, 'x>: 'x,
453        //  {
454        //      let a = &mut ();
455        //      let b: &'x () = &();
456        //      let val1 = rpit(a, b);
457        //      let val2 = rpit(a, b);
458        //      drop(val1);
459        //      drop(val32);
460        //  }
461        // ```
462        // So, we conservatively treat this as giving no restriction on which args can be captured.
463        ty::ReEarlyParam(..) => None,
464        // Don't know that we actually hit this (maybe `ReError`), go ahead and be conservative.
465        _ => None,
466    }
467}
468
469/// Visits free regions in the type that are relevant for liveness computation.
470/// These regions are passed to `OP`.
471///
472/// Specifically, we visit all of the regions of types recursively, except if
473/// the type is an alias, we look at the outlives bounds in the param-env and
474/// the alias's item bounds. Each such bound restricts which of the alias's
475/// args the underlying type could have captured, so only those (capturable)
476/// args are visited. If there are no applicable bounds, we walk through the
477/// alias's (non-bivariant) args structurally.
478pub struct FreeRegionsVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> {
479    pub tcx: TyCtxt<'tcx>,
480    pub param_env: ty::ParamEnv<'tcx>,
481    pub op: OP,
482}
483
484impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP>
485where
486    OP: FnMut(ty::Region<'tcx>),
487{
488    fn visit_region(&mut self, r: ty::Region<'tcx>) {
489        match r.kind() {
490            // ignore bound regions, keep visiting
491            ty::ReBound(_, _) => {}
492            _ => (self.op)(r),
493        }
494    }
495
496    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("visit_ty",
                                    "rustc_trait_selection::traits::outlives_for_liveness",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs"),
                                    ::tracing_core::__macro_support::Option::Some(496u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::outlives_for_liveness"),
                                    ::tracing_core::field::FieldSet::new(&["ty"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
                return;
            }
            match *ty.kind() {
                ty::Alias(_, ty::AliasTy { kind, args, .. }) => {
                    let tcx = self.tcx;
                    let param_env = self.param_env;
                    let def_id =
                        match kind {
                            ty::AliasTyKind::Projection { def_id } |
                                ty::AliasTyKind::Inherent { def_id } |
                                ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free {
                                def_id } => def_id,
                        };
                    let mut capturable:
                            Option<FxIndexSet<ty::EarlyBinder<'tcx,
                            ty::GenericArg<'tcx>>>> = None;
                    let mut restrict =
                        |capturable_args:
                                FxIndexSet<ty::EarlyBinder<'tcx, ty::GenericArg<'tcx>>>|
                            {
                                match &mut capturable {
                                    None => capturable = Some(capturable_args),
                                    Some(prev) => {
                                        *prev =
                                            prev.intersection(&capturable_args).copied().collect()
                                    }
                                };
                            };
                    if let Some(live_args) =
                            tcx.live_args_for_alias_from_outlives_bounds(kind) {
                        restrict(live_args.as_ref().skip_binder().iter().copied().map(|a|
                                        ty::EarlyBinder::bind(tcx, a)).collect());
                    }
                    for clause in param_env.caller_bounds() {
                        let Some(outlives) =
                            clause.as_type_outlives_clause() else { continue; };
                        if let Some(capturable_args) =
                                live_args_for_outlives_clause(tcx, def_id, ty, outlives) {
                            restrict(capturable_args);
                        }
                    }
                    {
                        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/traits/outlives_for_liveness.rs:566",
                                            "rustc_trait_selection::traits::outlives_for_liveness",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs"),
                                            ::tracing_core::__macro_support::Option::Some(566u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::outlives_for_liveness"),
                                            ::tracing_core::field::FieldSet::new(&["capturable"],
                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&capturable)
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    match capturable {
                        Some(capturable_args) => {
                            for arg in capturable_args {
                                let arg = arg.instantiate(tcx, args).skip_norm_wip();
                                arg.visit_with(self);
                            }
                        }
                        None => {
                            let variances = tcx.opt_alias_variances(kind);
                            for (idx, s) in args.iter().enumerate() {
                                if variances.map(|variances| variances[idx]) !=
                                        Some(ty::Bivariant) {
                                    s.visit_with(self);
                                }
                            }
                        }
                    }
                }
                _ => ty.super_visit_with(self),
            }
        }
    }
}#[tracing::instrument(skip(self), level = "debug")]
497    fn visit_ty(&mut self, ty: Ty<'tcx>) {
498        // We're only interested in types involving regions
499        if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
500            return;
501        }
502
503        match *ty.kind() {
504            // We can prove that an alias is live two ways:
505            // 1. All the components are live.
506            // 2. There is a known outlives bound or where-clause, and that
507            //    region is live.
508            //
509            // We search through the item bounds and where clauses for
510            // either `'static` or a unique outlives region, and if one is
511            // found, we just need to prove that that region is still live.
512            // If one is not found, then we continue to walk through the alias.
513            ty::Alias(_, ty::AliasTy { kind, args, .. }) => {
514                let tcx = self.tcx;
515                let param_env = self.param_env;
516
517                // For aliases other than opaques, we have to consider two
518                // sources of information to identity potentially-live args:
519                // - Bounds on alias item itself
520                // - Outlives clauses on the current function that apply to the alias
521                //
522                // Each source of information *restricts* the set of potentially-live
523                // args independently: only the args that can be live for *every*
524                // source of information can be actually live, so we take the intersection.
525                let def_id = match kind {
526                    ty::AliasTyKind::Projection { def_id }
527                    | ty::AliasTyKind::Inherent { def_id }
528                    | ty::AliasTyKind::Opaque { def_id }
529                    | ty::AliasTyKind::Free { def_id } => def_id,
530                };
531                let mut capturable: Option<
532                    FxIndexSet<ty::EarlyBinder<'tcx, ty::GenericArg<'tcx>>>,
533                > = None;
534                let mut restrict =
535                    |capturable_args: FxIndexSet<ty::EarlyBinder<'tcx, ty::GenericArg<'tcx>>>| {
536                        match &mut capturable {
537                            None => capturable = Some(capturable_args),
538                            Some(prev) => {
539                                *prev = prev.intersection(&capturable_args).copied().collect()
540                            }
541                        };
542                    };
543
544                if let Some(live_args) = tcx.live_args_for_alias_from_outlives_bounds(kind) {
545                    restrict(
546                        live_args
547                            .as_ref()
548                            .skip_binder()
549                            .iter()
550                            .copied()
551                            .map(|a| ty::EarlyBinder::bind(tcx, a))
552                            .collect(),
553                    );
554                }
555
556                for clause in param_env.caller_bounds() {
557                    let Some(outlives) = clause.as_type_outlives_clause() else {
558                        continue;
559                    };
560                    if let Some(capturable_args) =
561                        live_args_for_outlives_clause(tcx, def_id, ty, outlives)
562                    {
563                        restrict(capturable_args);
564                    }
565                }
566                tracing::debug!(?capturable);
567
568                match capturable {
569                    Some(capturable_args) => {
570                        for arg in capturable_args {
571                            let arg = arg.instantiate(tcx, args).skip_norm_wip();
572                            arg.visit_with(self);
573                        }
574                    }
575                    None => {
576                        // Skip lifetime parameters that are not captured, since they do
577                        // not need to be live.
578                        let variances = tcx.opt_alias_variances(kind);
579                        for (idx, s) in args.iter().enumerate() {
580                            if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {
581                                s.visit_with(self);
582                            }
583                        }
584                    }
585                }
586            }
587
588            _ => ty.super_visit_with(self),
589        }
590    }
591}