Skip to main content

rustc_infer/infer/outlives/
mod.rs

1//! Various code related to computing outlives relations.
2
3use std::iter;
4
5use rustc_data_structures::undo_log::UndoLogs;
6use rustc_middle::traits::query::OutlivesBound;
7use rustc_middle::ty;
8use tracing::instrument;
9
10use self::env::OutlivesEnvironment;
11use super::region_constraints::{RegionConstraintData, UndoLog};
12use super::{InferCtxt, RegionResolutionError};
13use crate::infer::free_regions::RegionRelations;
14use crate::infer::lexical_region_resolve;
15use crate::infer::region_constraints::ConstraintKind;
16
17pub mod env;
18pub mod obligations;
19pub mod test_type_match;
20pub(crate) mod verify;
21
22{}
#[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("explicit_outlives_bounds",
                                    "rustc_infer::infer::outlives", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_infer/src/infer/outlives/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(22u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set_all(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: _ = loop {};
            return __tracing_attr_fake_return;
        }
        {
            param_env.caller_bounds().into_iter().filter_map(ty::Clause::as_region_outlives_clause).filter_map(ty::Binder::no_bound_vars).map(|ty::OutlivesClause(r_a,
                        r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
        }
    }
}#[instrument(level = "debug", skip(param_env))]
23pub fn explicit_outlives_bounds<'tcx>(
24    param_env: ty::ParamEnv<'tcx>,
25) -> impl Iterator<Item = OutlivesBound<'tcx>> {
26    param_env
27        .caller_bounds()
28        .into_iter()
29        .filter_map(ty::Clause::as_region_outlives_clause)
30        .filter_map(ty::Binder::no_bound_vars)
31        .map(|ty::OutlivesClause(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
32}
33
34impl<'tcx> InferCtxt<'tcx> {
35    /// Process the region constraints and return any errors that
36    /// result. After this, no more unification operations should be
37    /// done -- or the compiler will panic -- but it is legal to use
38    /// `deeply_resolve_ignoring_regions` as well as `fully_resolve`.
39    ///
40    /// Don't call this directly unless you know what you're doing.
41    /// You probably want to use `resolve_regions` instead.
42    #[must_use]
43    pub fn resolve_regions_with_outlives_env(
44        &self,
45        outlives_env: &OutlivesEnvironment<'tcx>,
46    ) -> Vec<RegionResolutionError<'tcx>> {
47        self.process_registered_region_obligations(outlives_env);
48
49        let mut storage = {
50            let mut inner = self.inner.borrow_mut();
51            let inner = &mut *inner;
52            if !(self.tainted_by_errors().is_some() ||
            inner.region_obligations.is_empty()) {
    {
        ::core::panicking::panic_fmt(format_args!("region_obligations not empty: {0:#?}",
                inner.region_obligations));
    }
};assert!(
53                self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
54                "region_obligations not empty: {:#?}",
55                inner.region_obligations,
56            );
57            if !!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log) {
    ::core::panicking::panic("assertion failed: !UndoLogs::<UndoLog<\'_>>::in_snapshot(&inner.undo_log)")
};assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
58            inner.region_constraint_storage.take().expect("regions already resolved")
59        };
60
61        // FIXME(-Zassumptions-in-binders): Handle solver_data
62        storage.legacy_data.constraints = storage
63            .legacy_data
64            .constraints
65            .iter()
66            .flat_map(|(constraint, origin)| {
67                constraint.iter_outlives().zip(iter::repeat_with(|| origin.clone()))
68            })
69            .collect();
70
71        // Filter out any region-region outlives assumptions that are implied by
72        // coroutine well-formedness.
73        if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
74            storage.legacy_data.constraints.retain(|(c, _)| match c.kind {
75                ConstraintKind::RegSubReg => !outlives_env
76                    .higher_ranked_assumptions()
77                    .contains(&ty::OutlivesClause(c.sup.into(), c.sub)),
78
79                ConstraintKind::VarSubVar
80                | ConstraintKind::RegSubVar
81                | ConstraintKind::VarSubReg => true,
82
83                ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
84                    ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
85                }
86            });
87        }
88
89        let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
90
91        let (lexical_region_resolutions, errors) =
92            lexical_region_resolve::resolve(region_rels, storage.var_infos, storage.legacy_data);
93
94        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
95        if !old_value.is_none() {
    ::core::panicking::panic("assertion failed: old_value.is_none()")
};assert!(old_value.is_none());
96
97        errors
98    }
99
100    /// Obtains (and clears) the current set of region
101    /// constraints. The inference context is still usable: further
102    /// unifications will simply add new constraints.
103    ///
104    /// This method is not meant to be used with normal lexical region
105    /// resolution. Rather, it is used in the NLL mode as a kind of
106    /// interim hack: basically we run normal type-check and generate
107    /// region constraints as normal, but then we take them and
108    /// translate them into the form that the NLL solver
109    /// understands. See the NLL module for mode details.
110    pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
111        if !self.inner.borrow().region_obligations.is_empty() {
    {
        ::core::panicking::panic_fmt(format_args!("region_obligations not empty: {0:#?}",
                self.inner.borrow().region_obligations));
    }
};assert!(
112            self.inner.borrow().region_obligations.is_empty(),
113            "region_obligations not empty: {:#?}",
114            self.inner.borrow().region_obligations
115        );
116        if !self.inner.borrow().region_assumptions.is_empty() {
    {
        ::core::panicking::panic_fmt(format_args!("region_assumptions not empty: {0:#?}",
                self.inner.borrow().region_assumptions));
    }
};assert!(
117            self.inner.borrow().region_assumptions.is_empty(),
118            "region_assumptions not empty: {:#?}",
119            self.inner.borrow().region_assumptions
120        );
121
122        self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
123    }
124
125    /// Gives temporary access to the region constraint data.
126    pub fn with_region_constraints<R>(
127        &self,
128        op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
129    ) -> R {
130        let mut inner = self.inner.borrow_mut();
131        // FIXME(-Zassumptions-on-binders): Handle solver_data
132        op(inner.unwrap_region_constraints().legacy_data())
133    }
134}