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

    #[warn(clippy :: suspicious_else_formatting)]
    {

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