summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/outlives/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer/outlives/mod.rs')
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs107
1 files changed, 103 insertions, 4 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 83f3d5a74..9a9a1696b 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -1,4 +1,11 @@
//! Various code related to computing outlives relations.
+use self::env::OutlivesEnvironment;
+use super::region_constraints::RegionConstraintData;
+use super::{InferCtxt, RegionResolutionError};
+use crate::infer::free_regions::RegionRelations;
+use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
+use rustc_middle::traits::query::OutlivesBound;
+use rustc_middle::ty;
pub mod components;
pub mod env;
@@ -6,9 +13,6 @@ pub mod obligations;
pub mod test_type_match;
pub mod verify;
-use rustc_middle::traits::query::OutlivesBound;
-use rustc_middle::ty;
-
#[instrument(level = "debug", skip(param_env), ret)]
pub fn explicit_outlives_bounds<'tcx>(
param_env: ty::ParamEnv<'tcx>,
@@ -22,7 +26,7 @@ pub fn explicit_outlives_bounds<'tcx>(
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::AliasEq(..)
+ | ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)
@@ -39,3 +43,98 @@ pub fn explicit_outlives_bounds<'tcx>(
))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
})
}
+
+impl<'tcx> InferCtxt<'tcx> {
+ pub fn skip_region_resolution(&self) {
+ let (var_infos, _) = {
+ let mut inner = self.inner.borrow_mut();
+ let inner = &mut *inner;
+ // Note: `inner.region_obligations` may not be empty, because we
+ // didn't necessarily call `process_registered_region_obligations`.
+ // This is okay, because that doesn't introduce new vars.
+ inner
+ .region_constraint_storage
+ .take()
+ .expect("regions already resolved")
+ .with_log(&mut inner.undo_log)
+ .into_infos_and_data()
+ };
+
+ let lexical_region_resolutions = LexicalRegionResolutions {
+ values: rustc_index::vec::IndexVec::from_elem_n(
+ crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
+ var_infos.len(),
+ ),
+ };
+
+ let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+ assert!(old_value.is_none());
+ }
+
+ /// Process the region constraints and return any errors that
+ /// result. After this, no more unification operations should be
+ /// done -- or the compiler will panic -- but it is legal to use
+ /// `resolve_vars_if_possible` as well as `fully_resolve`.
+ #[must_use]
+ pub fn resolve_regions(
+ &self,
+ outlives_env: &OutlivesEnvironment<'tcx>,
+ ) -> Vec<RegionResolutionError<'tcx>> {
+ self.process_registered_region_obligations(outlives_env);
+
+ let (var_infos, data) = {
+ let mut inner = self.inner.borrow_mut();
+ let inner = &mut *inner;
+ assert!(
+ self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
+ "region_obligations not empty: {:#?}",
+ inner.region_obligations
+ );
+ inner
+ .region_constraint_storage
+ .take()
+ .expect("regions already resolved")
+ .with_log(&mut inner.undo_log)
+ .into_infos_and_data()
+ };
+
+ let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
+
+ let (lexical_region_resolutions, errors) =
+ lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
+
+ let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+ assert!(old_value.is_none());
+
+ errors
+ }
+
+ /// Obtains (and clears) the current set of region
+ /// constraints. The inference context is still usable: further
+ /// unifications will simply add new constraints.
+ ///
+ /// This method is not meant to be used with normal lexical region
+ /// resolution. Rather, it is used in the NLL mode as a kind of
+ /// interim hack: basically we run normal type-check and generate
+ /// region constraints as normal, but then we take them and
+ /// translate them into the form that the NLL solver
+ /// understands. See the NLL module for mode details.
+ pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
+ assert!(
+ self.inner.borrow().region_obligations.is_empty(),
+ "region_obligations not empty: {:#?}",
+ self.inner.borrow().region_obligations
+ );
+
+ self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
+ }
+
+ /// Gives temporary access to the region constraint data.
+ pub fn with_region_constraints<R>(
+ &self,
+ op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
+ ) -> R {
+ let mut inner = self.inner.borrow_mut();
+ op(inner.unwrap_region_constraints().data())
+ }
+}