rustc_infer/infer/outlives/
mod.rs

1//! Various code related to computing outlives relations.
2
3use rustc_data_structures::undo_log::UndoLogs;
4use rustc_middle::traits::query::{NoSolution, OutlivesBound};
5use rustc_middle::ty;
6use tracing::instrument;
7
8use self::env::OutlivesEnvironment;
9use super::region_constraints::{RegionConstraintData, UndoLog};
10use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
11use crate::infer::free_regions::RegionRelations;
12use crate::infer::lexical_region_resolve;
13
14pub mod env;
15pub mod for_liveness;
16pub mod obligations;
17pub mod test_type_match;
18pub(crate) mod verify;
19
20#[instrument(level = "debug", skip(param_env), ret)]
21pub fn explicit_outlives_bounds<'tcx>(
22    param_env: ty::ParamEnv<'tcx>,
23) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
24    param_env
25        .caller_bounds()
26        .into_iter()
27        .filter_map(ty::Clause::as_region_outlives_clause)
28        .filter_map(ty::Binder::no_bound_vars)
29        .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
30}
31
32impl<'tcx> InferCtxt<'tcx> {
33    /// Process the region constraints and return any errors that
34    /// result. After this, no more unification operations should be
35    /// done -- or the compiler will panic -- but it is legal to use
36    /// `resolve_vars_if_possible` as well as `fully_resolve`.
37    ///
38    /// If you are in a crate that has access to `rustc_trait_selection`,
39    /// then it's probably better to use `resolve_regions`,
40    /// which knows how to normalize registered region obligations.
41    #[must_use]
42    pub fn resolve_regions_with_normalize(
43        &self,
44        outlives_env: &OutlivesEnvironment<'tcx>,
45        deeply_normalize_ty: impl Fn(
46            ty::PolyTypeOutlivesPredicate<'tcx>,
47            SubregionOrigin<'tcx>,
48        ) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
49    ) -> Vec<RegionResolutionError<'tcx>> {
50        match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
51            Ok(()) => {}
52            Err((clause, origin)) => {
53                return vec![RegionResolutionError::CannotNormalize(clause, origin)];
54            }
55        };
56
57        let storage = {
58            let mut inner = self.inner.borrow_mut();
59            let inner = &mut *inner;
60            assert!(
61                self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
62                "region_obligations not empty: {:#?}",
63                inner.region_obligations
64            );
65            assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
66            inner.region_constraint_storage.take().expect("regions already resolved")
67        };
68
69        let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
70
71        let (lexical_region_resolutions, errors) =
72            lexical_region_resolve::resolve(region_rels, storage.var_infos, storage.data);
73
74        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
75        assert!(old_value.is_none());
76
77        errors
78    }
79
80    /// Obtains (and clears) the current set of region
81    /// constraints. The inference context is still usable: further
82    /// unifications will simply add new constraints.
83    ///
84    /// This method is not meant to be used with normal lexical region
85    /// resolution. Rather, it is used in the NLL mode as a kind of
86    /// interim hack: basically we run normal type-check and generate
87    /// region constraints as normal, but then we take them and
88    /// translate them into the form that the NLL solver
89    /// understands. See the NLL module for mode details.
90    pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
91        assert!(
92            self.inner.borrow().region_obligations.is_empty(),
93            "region_obligations not empty: {:#?}",
94            self.inner.borrow().region_obligations
95        );
96
97        self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
98    }
99
100    /// Gives temporary access to the region constraint data.
101    pub fn with_region_constraints<R>(
102        &self,
103        op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
104    ) -> R {
105        let mut inner = self.inner.borrow_mut();
106        op(inner.unwrap_region_constraints().data())
107    }
108}