/// `resolve_regions_and_report_errors` is invoked, this gets set to `None`
/// -- further attempts to perform unification, etc., may fail if new
/// region constraints would've been added.
- region_constraints: Option<RegionConstraintStorage<'tcx>>,
+ region_constraint_storage: Option<RegionConstraintStorage<'tcx>>,
/// A set of constraints that regionck must validate. Each
/// constraint has the form `T:'a`, meaning "some type `T` must
const_unification_storage: ut::UnificationTableStorage::new(),
int_unification_storage: ut::UnificationTableStorage::new(),
float_unification_storage: ut::UnificationTableStorage::new(),
- region_constraints: Some(RegionConstraintStorage::new()),
+ region_constraint_storage: Some(RegionConstraintStorage::new()),
region_obligations: vec![],
}
}
}
pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'tcx, '_> {
- self.region_constraints
+ self.region_constraint_storage
.as_mut()
.expect("region constraints already solved")
.with_log(&mut self.undo_log)
}
}
+/// Extends `CombinedSnapshot` by tracking which variables were added in the snapshot
#[must_use = "once you start a snapshot, you should always consume it"]
-pub struct FullSnapshot<'a, 'tcx> {
+pub struct FudgeSnapshot<'a, 'tcx> {
snapshot: CombinedSnapshot<'a, 'tcx>,
region_constraints_snapshot: RegionSnapshot,
type_snapshot: type_variable::Snapshot<'tcx>,
result
}
- fn start_full_snapshot(&self) -> FullSnapshot<'a, 'tcx> {
+ fn start_fudge_snapshot(&self) -> FudgeSnapshot<'a, 'tcx> {
let snapshot = self.start_snapshot();
let mut inner = self.inner.borrow_mut();
- FullSnapshot {
+ FudgeSnapshot {
snapshot,
type_snapshot: inner.type_variables().snapshot(),
const_var_len: inner.const_unification_table().len(),
r
}
- pub fn probe_full<R, F>(&self, f: F) -> R
+ /// Like `probe` but provides information about which variables were created in the snapshot,
+ /// allowing for inference fudging
+ pub fn probe_fudge<R, F>(&self, f: F) -> R
where
- F: FnOnce(&FullSnapshot<'a, 'tcx>) -> R,
+ F: FnOnce(&FudgeSnapshot<'a, 'tcx>) -> R,
{
debug!("probe()");
- let snapshot = self.start_full_snapshot();
+ let snapshot = self.start_fudge_snapshot();
let r = f(&snapshot);
self.rollback_to("probe", snapshot.snapshot);
r
inner.region_obligations
);
inner
- .region_constraints
+ .region_constraint_storage
.take()
.expect("regions already resolved")
.with_log(&mut inner.undo_log)
pub fn take_region_var_origins(&self) -> VarInfos {
let mut inner = self.inner.borrow_mut();
let (var_infos, data) = inner
- .region_constraints
+ .region_constraint_storage
.take()
.expect("regions already resolved")
.with_log(&mut inner.undo_log)
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
+/// Represents a single undo-able action that affects a type inference variable.
pub(crate) enum UndoLog<'tcx> {
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
Values(sv::UndoLog<Delegate>),
}
+/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
UndoLog::EqRelation(l)
}
}
+/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
UndoLog::SubRelation(l)
}
}
+/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<Delegate>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<Delegate>) -> Self {
UndoLog::Values(l)
}
}
+/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<Instantiate> for UndoLog<'tcx> {
fn from(l: Instantiate) -> Self {
UndoLog::Values(sv::UndoLog::Other(l))
ProjectionCache(traits::UndoLog<'tcx>),
}
+/// The Rollback trait defines how to rollback a particular action.
impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
fn reverse(&mut self, undo: UndoLog<'tcx>) {
match undo {
UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo),
UndoLog::RegionConstraintCollector(undo) => {
- self.region_constraints.as_mut().unwrap().reverse(undo)
+ self.region_constraint_storage.as_mut().unwrap().reverse(undo)
}
UndoLog::RegionUnificationTable(undo) => {
- self.region_constraints.as_mut().unwrap().unification_table.reverse(undo)
+ self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo)
}
UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
UndoLog::PushRegionObligation => {
}
}
+/// The combined undo log for all the various unification tables. For each change to the storage
+/// for any kind of inference variable, we record an UndoLog entry in the vector here.
pub(crate) struct InferCtxtUndoLogs<'tcx> {
logs: Vec<UndoLog<'tcx>>,
num_open_snapshots: usize,
}
}
+/// The UndoLogs trait defines how we undo a particular kind of action (of type T). We can undo any
+/// action that is convertable into a UndoLog (per the From impls above).
impl<'tcx, T> UndoLogs<T> for InferCtxtUndoLogs<'tcx>
where
UndoLog<'tcx>: From<T>,
fn num_open_snapshots(&self) -> usize {
self.num_open_snapshots
}
+
fn push(&mut self, undo: T) {
if self.in_snapshot() {
self.logs.push(undo.into())
}
}
+
fn clear(&mut self) {
self.logs.clear();
self.num_open_snapshots = 0;
}
+
fn extend<J>(&mut self, undos: J)
where
Self: Sized,
impl<'tcx> std::ops::Index<usize> for InferCtxtUndoLogs<'tcx> {
type Output = UndoLog<'tcx>;
+
fn index(&self, key: usize) -> &Self::Output {
&self.logs[key]
}