1//! Various code related to computing outlives relations.
23use rustc_data_structures::undo_log::UndoLogs;
4use rustc_middle::traits::query::{NoSolution, OutlivesBound};
5use rustc_middle::ty;
6use tracing::instrument;
78use 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;
13use crate::infer::region_constraints::ConstraintKind;
1415pub mod env;
16pub mod for_liveness;
17pub mod obligations;
18pub mod test_type_match;
19pub(crate) mod verify;
2021x;#[instrument(level = "debug", skip(param_env), ret)]22pub fn explicit_outlives_bounds<'tcx>(
23 param_env: ty::ParamEnv<'tcx>,
24) -> impl Iterator<Item = OutlivesBound<'tcx>> {
25 param_env
26 .caller_bounds()
27 .into_iter()
28 .filter_map(ty::Clause::as_region_outlives_clause)
29 .filter_map(ty::Binder::no_bound_vars)
30 .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
31}
3233impl<'tcx> InferCtxt<'tcx> {
34/// Process the region constraints and return any errors that
35 /// result. After this, no more unification operations should be
36 /// done -- or the compiler will panic -- but it is legal to use
37 /// `resolve_vars_if_possible` as well as `fully_resolve`.
38 ///
39 /// If you are in a crate that has access to `rustc_trait_selection`,
40 /// then it's probably better to use `resolve_regions`,
41 /// which knows how to normalize registered region obligations.
42#[must_use]
43pub fn resolve_regions_with_normalize(
44&self,
45 outlives_env: &OutlivesEnvironment<'tcx>,
46 deeply_normalize_ty: impl Fn(
47 ty::PolyTypeOutlivesPredicate<'tcx>,
48SubregionOrigin<'tcx>,
49 ) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
50 ) -> Vec<RegionResolutionError<'tcx>> {
51match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
52Ok(()) => {}
53Err((clause, origin)) => {
54return <[_]>::into_vec(::alloc::boxed::box_new([RegionResolutionError::CannotNormalize(clause,
origin)]))vec![RegionResolutionError::CannotNormalize(clause, origin)];
55 }
56 };
5758let mut storage = {
59let mut inner = self.inner.borrow_mut();
60let inner = &mut *inner;
61if !(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!(
62self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
63"region_obligations not empty: {:#?}",
64 inner.region_obligations,
65 );
66if !!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));
67inner.region_constraint_storage.take().expect("regions already resolved")
68 };
6970// Filter out any region-region outlives assumptions that are implied by
71 // coroutine well-formedness.
72if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
73storage.data.constraints.retain(|(c, _)| match c.kind {
74 ConstraintKind::RegSubReg => !outlives_env75 .higher_ranked_assumptions()
76 .contains(&ty::OutlivesPredicate(c.sup.into(), c.sub)),
77_ => true,
78 });
79 }
8081let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
8283let (lexical_region_resolutions, errors) =
84 lexical_region_resolve::resolve(region_rels, storage.var_infos, storage.data);
8586let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
87if !old_value.is_none() {
::core::panicking::panic("assertion failed: old_value.is_none()")
};assert!(old_value.is_none());
8889errors90 }
9192/// Obtains (and clears) the current set of region
93 /// constraints. The inference context is still usable: further
94 /// unifications will simply add new constraints.
95 ///
96 /// This method is not meant to be used with normal lexical region
97 /// resolution. Rather, it is used in the NLL mode as a kind of
98 /// interim hack: basically we run normal type-check and generate
99 /// region constraints as normal, but then we take them and
100 /// translate them into the form that the NLL solver
101 /// understands. See the NLL module for mode details.
102pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
103if !self.inner.borrow().region_obligations.is_empty() {
{
::core::panicking::panic_fmt(format_args!("region_obligations not empty: {0:#?}",
self.inner.borrow().region_obligations));
}
};assert!(
104self.inner.borrow().region_obligations.is_empty(),
105"region_obligations not empty: {:#?}",
106self.inner.borrow().region_obligations
107 );
108if !self.inner.borrow().region_assumptions.is_empty() {
{
::core::panicking::panic_fmt(format_args!("region_assumptions not empty: {0:#?}",
self.inner.borrow().region_assumptions));
}
};assert!(
109self.inner.borrow().region_assumptions.is_empty(),
110"region_assumptions not empty: {:#?}",
111self.inner.borrow().region_assumptions
112 );
113114self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
115 }
116117/// Gives temporary access to the region constraint data.
118pub fn with_region_constraints<R>(
119&self,
120 op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
121 ) -> R {
122let mut inner = self.inner.borrow_mut();
123op(inner.unwrap_region_constraints().data())
124 }
125}