Move region_constraint to the unified undo log
This commit is contained in:
parent
1506b1fc6a
commit
caacdd2024
7 changed files with 235 additions and 210 deletions
16
Cargo.lock
16
Cargo.lock
|
@ -987,7 +987,17 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ena"
|
name = "ena"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
source = "git+https://github.com/Marwes/ena?branch=detach_undo_log#9b977ea7f209a35f46d65d33cdd74b8f4931fb8a"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ena"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
@ -3234,7 +3244,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
"ena",
|
"ena 0.13.1",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"lazy_static 1.4.0",
|
"lazy_static 1.4.0",
|
||||||
|
@ -3680,7 +3690,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
"ena",
|
"ena 0.14.0",
|
||||||
"graphviz",
|
"graphviz",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
|
|
|
@ -65,7 +65,5 @@ rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }
|
||||||
rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
|
rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
|
||||||
rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
|
rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
|
||||||
|
|
||||||
ena = { version = "0.13.1", git = "https://github.com/Marwes/ena", branch = "detach_undo_log" }
|
|
||||||
|
|
||||||
[patch."https://github.com/rust-lang/rust-clippy"]
|
[patch."https://github.com/rust-lang/rust-clippy"]
|
||||||
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
|
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
|
||||||
|
|
|
@ -10,7 +10,7 @@ path = "lib.rs"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ena = "0.13.1"
|
ena = "0.14"
|
||||||
indexmap = "1"
|
indexmap = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
jobserver_crate = { version = "0.1.13", package = "jobserver" }
|
jobserver_crate = { version = "0.1.13", package = "jobserver" }
|
||||||
|
|
|
@ -45,7 +45,9 @@ use self::free_regions::RegionRelations;
|
||||||
use self::lexical_region_resolve::LexicalRegionResolutions;
|
use self::lexical_region_resolve::LexicalRegionResolutions;
|
||||||
use self::outlives::env::OutlivesEnvironment;
|
use self::outlives::env::OutlivesEnvironment;
|
||||||
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
|
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
|
||||||
use self::region_constraints::{RegionConstraintCollector, RegionSnapshot};
|
use self::region_constraints::{
|
||||||
|
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
|
||||||
|
};
|
||||||
use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
|
|
||||||
pub mod at;
|
pub mod at;
|
||||||
|
@ -161,7 +163,7 @@ pub struct InferCtxtInner<'tcx> {
|
||||||
/// `resolve_regions_and_report_errors` is invoked, this gets set to `None`
|
/// `resolve_regions_and_report_errors` is invoked, this gets set to `None`
|
||||||
/// -- further attempts to perform unification, etc., may fail if new
|
/// -- further attempts to perform unification, etc., may fail if new
|
||||||
/// region constraints would've been added.
|
/// region constraints would've been added.
|
||||||
region_constraints: Option<RegionConstraintCollector<'tcx>>,
|
region_constraints: Option<RegionConstraintStorage<'tcx>>,
|
||||||
|
|
||||||
/// A set of constraints that regionck must validate. Each
|
/// A set of constraints that regionck must validate. Each
|
||||||
/// constraint has the form `T:'a`, meaning "some type `T` must
|
/// constraint has the form `T:'a`, meaning "some type `T` must
|
||||||
|
@ -206,7 +208,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
||||||
const_unification_table: ut::UnificationStorage::new(),
|
const_unification_table: ut::UnificationStorage::new(),
|
||||||
int_unification_table: ut::UnificationStorage::new(),
|
int_unification_table: ut::UnificationStorage::new(),
|
||||||
float_unification_table: ut::UnificationStorage::new(),
|
float_unification_table: ut::UnificationStorage::new(),
|
||||||
region_constraints: Some(RegionConstraintCollector::new()),
|
region_constraints: Some(RegionConstraintStorage::new()),
|
||||||
region_obligations: vec![],
|
region_obligations: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,8 +245,11 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
||||||
ut::UnificationTable::with_log(&mut self.const_unification_table, &mut self.undo_log)
|
ut::UnificationTable::with_log(&mut self.const_unification_table, &mut self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_region_constraints(&mut self) -> &mut RegionConstraintCollector<'tcx> {
|
pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'tcx, '_> {
|
||||||
self.region_constraints.as_mut().expect("region constraints already solved")
|
self.region_constraints
|
||||||
|
.as_mut()
|
||||||
|
.expect("region constraints already solved")
|
||||||
|
.with_log(&mut self.undo_log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +263,14 @@ pub(crate) enum UndoLog<'tcx> {
|
||||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
|
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
|
||||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||||
|
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
|
||||||
|
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<region_constraints::UndoLog<'tcx>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: region_constraints::UndoLog<'tcx>) -> Self {
|
||||||
|
UndoLog::RegionConstraintCollector(l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
||||||
|
@ -308,6 +321,12 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::FloatVid>>> for UndoLog<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::RegionVid>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::RegionVid>>) -> Self {
|
||||||
|
Self::RegionUnificationTable(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) type UnificationTable<'a, 'tcx, T> =
|
pub(crate) type UnificationTable<'a, 'tcx, T> =
|
||||||
ut::UnificationTable<ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut Logs<'tcx>>>;
|
ut::UnificationTable<ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut Logs<'tcx>>>;
|
||||||
|
|
||||||
|
@ -316,6 +335,7 @@ struct RollbackView<'tcx, 'a> {
|
||||||
const_unification_table: &'a mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
const_unification_table: &'a mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
||||||
int_unification_table: &'a mut ut::UnificationStorage<ty::IntVid>,
|
int_unification_table: &'a mut ut::UnificationStorage<ty::IntVid>,
|
||||||
float_unification_table: &'a mut ut::UnificationStorage<ty::FloatVid>,
|
float_unification_table: &'a mut ut::UnificationStorage<ty::FloatVid>,
|
||||||
|
region_constraints: &'a mut RegionConstraintStorage<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
|
impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
|
||||||
|
@ -325,6 +345,10 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
|
||||||
UndoLog::ConstUnificationTable(undo) => self.const_unification_table.reverse(undo),
|
UndoLog::ConstUnificationTable(undo) => self.const_unification_table.reverse(undo),
|
||||||
UndoLog::IntUnificationTable(undo) => self.int_unification_table.reverse(undo),
|
UndoLog::IntUnificationTable(undo) => self.int_unification_table.reverse(undo),
|
||||||
UndoLog::FloatUnificationTable(undo) => self.float_unification_table.reverse(undo),
|
UndoLog::FloatUnificationTable(undo) => self.float_unification_table.reverse(undo),
|
||||||
|
UndoLog::RegionConstraintCollector(undo) => self.region_constraints.reverse(undo),
|
||||||
|
UndoLog::RegionUnificationTable(undo) => {
|
||||||
|
self.region_constraints.unification_table.reverse(undo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,6 +432,16 @@ impl<'tcx> Snapshots<UndoLog<'tcx>> for Logs<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Logs<'tcx> {
|
impl<'tcx> Logs<'tcx> {
|
||||||
|
pub(crate) fn region_constraints(
|
||||||
|
&self,
|
||||||
|
after: usize,
|
||||||
|
) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
|
||||||
|
self.logs[after..].iter().filter_map(|log| match log {
|
||||||
|
UndoLog::RegionConstraintCollector(log) => Some(log),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
|
fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
|
||||||
// Failures here may indicate a failure to follow a stack discipline.
|
// Failures here may indicate a failure to follow a stack discipline.
|
||||||
assert!(self.logs.len() >= snapshot.undo_len);
|
assert!(self.logs.len() >= snapshot.undo_len);
|
||||||
|
@ -1004,7 +1038,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
const_snapshot: _,
|
const_snapshot: _,
|
||||||
int_snapshot: _,
|
int_snapshot: _,
|
||||||
float_snapshot: _,
|
float_snapshot: _,
|
||||||
region_constraints_snapshot,
|
region_constraints_snapshot: _,
|
||||||
region_obligations_snapshot,
|
region_obligations_snapshot,
|
||||||
universe,
|
universe,
|
||||||
was_in_snapshot,
|
was_in_snapshot,
|
||||||
|
@ -1023,6 +1057,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
const_unification_table,
|
const_unification_table,
|
||||||
int_unification_table,
|
int_unification_table,
|
||||||
float_unification_table,
|
float_unification_table,
|
||||||
|
region_constraints,
|
||||||
..
|
..
|
||||||
} = inner;
|
} = inner;
|
||||||
inner.undo_log.rollback_to(
|
inner.undo_log.rollback_to(
|
||||||
|
@ -1031,11 +1066,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
const_unification_table,
|
const_unification_table,
|
||||||
int_unification_table,
|
int_unification_table,
|
||||||
float_unification_table,
|
float_unification_table,
|
||||||
|
region_constraints: region_constraints.as_mut().unwrap(),
|
||||||
},
|
},
|
||||||
undo_snapshot,
|
undo_snapshot,
|
||||||
);
|
);
|
||||||
inner.projection_cache.rollback_to(projection_cache_snapshot);
|
inner.projection_cache.rollback_to(projection_cache_snapshot);
|
||||||
inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
|
|
||||||
inner.region_obligations.truncate(region_obligations_snapshot);
|
inner.region_obligations.truncate(region_obligations_snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,7 +1083,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
const_snapshot: _,
|
const_snapshot: _,
|
||||||
int_snapshot: _,
|
int_snapshot: _,
|
||||||
float_snapshot: _,
|
float_snapshot: _,
|
||||||
region_constraints_snapshot,
|
region_constraints_snapshot: _,
|
||||||
region_obligations_snapshot: _,
|
region_obligations_snapshot: _,
|
||||||
universe: _,
|
universe: _,
|
||||||
was_in_snapshot,
|
was_in_snapshot,
|
||||||
|
@ -1062,7 +1097,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.undo_log.commit(undo_snapshot);
|
inner.undo_log.commit(undo_snapshot);
|
||||||
inner.projection_cache.commit(projection_cache_snapshot);
|
inner.projection_cache.commit(projection_cache_snapshot);
|
||||||
inner.unwrap_region_constraints().commit(region_constraints_snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes `f` and commit the bindings.
|
/// Executes `f` and commit the bindings.
|
||||||
|
@ -1135,7 +1169,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.unwrap_region_constraints()
|
.unwrap_region_constraints()
|
||||||
.region_constraints_added_in_snapshot(&snapshot.region_constraints_snapshot)
|
.region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
|
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
|
||||||
|
@ -1466,6 +1500,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
.region_constraints
|
.region_constraints
|
||||||
.take()
|
.take()
|
||||||
.expect("regions already resolved")
|
.expect("regions already resolved")
|
||||||
|
.with_log(&mut inner.undo_log)
|
||||||
.into_infos_and_data();
|
.into_infos_and_data();
|
||||||
|
|
||||||
let region_rels = &RegionRelations::new(
|
let region_rels = &RegionRelations::new(
|
||||||
|
@ -1527,12 +1562,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
/// called. This is used only during NLL processing to "hand off" ownership
|
/// called. This is used only during NLL processing to "hand off" ownership
|
||||||
/// of the set of region variables into the NLL region context.
|
/// of the set of region variables into the NLL region context.
|
||||||
pub fn take_region_var_origins(&self) -> VarInfos {
|
pub fn take_region_var_origins(&self) -> VarInfos {
|
||||||
let (var_infos, data) = self
|
let mut inner = self.inner.borrow_mut();
|
||||||
.inner
|
let (var_infos, data) = inner
|
||||||
.borrow_mut()
|
|
||||||
.region_constraints
|
.region_constraints
|
||||||
.take()
|
.take()
|
||||||
.expect("regions already resolved")
|
.expect("regions already resolved")
|
||||||
|
.with_log(&mut inner.undo_log)
|
||||||
.into_infos_and_data();
|
.into_infos_and_data();
|
||||||
assert!(data.is_empty());
|
assert!(data.is_empty());
|
||||||
var_infos
|
var_infos
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::infer::{CombinedSnapshot, PlaceholderMap};
|
use crate::infer::{CombinedSnapshot, PlaceholderMap};
|
||||||
|
use rustc_data_structures::undo_log::UndoLogs;
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::relate::RelateResult;
|
use rustc_middle::ty::relate::RelateResult;
|
||||||
|
|
||||||
impl<'tcx> RegionConstraintCollector<'tcx> {
|
impl<'tcx> RegionConstraintCollector<'tcx, '_> {
|
||||||
/// Searches region constraints created since `snapshot` that
|
/// Searches region constraints created since `snapshot` that
|
||||||
/// affect one of the placeholders in `placeholder_map`, returning
|
/// affect one of the placeholders in `placeholder_map`, returning
|
||||||
/// an error if any of the placeholders are related to another
|
/// an error if any of the placeholders are related to another
|
||||||
|
@ -31,7 +32,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
) -> RelateResult<'tcx, ()> {
|
) -> RelateResult<'tcx, ()> {
|
||||||
debug!("leak_check(placeholders={:?})", placeholder_map);
|
debug!("leak_check(placeholders={:?})", placeholder_map);
|
||||||
|
|
||||||
assert!(self.in_snapshot());
|
assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
||||||
|
|
||||||
// Go through each placeholder that we created.
|
// Go through each placeholder that we created.
|
||||||
for &placeholder_region in placeholder_map.values() {
|
for &placeholder_region in placeholder_map.values() {
|
||||||
|
@ -45,7 +46,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
// in some way. This means any region that either outlives
|
// in some way. This means any region that either outlives
|
||||||
// or is outlived by a placeholder.
|
// or is outlived by a placeholder.
|
||||||
let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region);
|
let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region);
|
||||||
taint_set.fixed_point(tcx, &self.undo_log, &self.data.verifys);
|
taint_set.fixed_point(
|
||||||
|
tcx,
|
||||||
|
self.undo_log.region_constraints(0),
|
||||||
|
&self.storage.data.verifys,
|
||||||
|
);
|
||||||
let tainted_regions = taint_set.into_set();
|
let tainted_regions = taint_set.into_set();
|
||||||
|
|
||||||
// Report an error if two placeholders in the same universe
|
// Report an error if two placeholders in the same universe
|
||||||
|
@ -88,19 +93,21 @@ impl<'tcx> TaintSet<'tcx> {
|
||||||
TaintSet { directions, regions }
|
TaintSet { directions, regions }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fixed_point(
|
fn fixed_point<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
undo_log: &[UndoLog<'tcx>],
|
undo_log: impl IntoIterator<Item = &'a UndoLog<'tcx>> + Clone,
|
||||||
verifys: &[Verify<'tcx>],
|
verifys: &[Verify<'tcx>],
|
||||||
) {
|
) where
|
||||||
|
'tcx: 'a,
|
||||||
|
{
|
||||||
let mut prev_len = 0;
|
let mut prev_len = 0;
|
||||||
while prev_len < self.len() {
|
while prev_len < self.len() {
|
||||||
debug!("tainted: prev_len = {:?} new_len = {:?}", prev_len, self.len());
|
debug!("tainted: prev_len = {:?} new_len = {:?}", prev_len, self.len());
|
||||||
|
|
||||||
prev_len = self.len();
|
prev_len = self.len();
|
||||||
|
|
||||||
for undo_entry in undo_log {
|
for undo_entry in undo_log.clone() {
|
||||||
match undo_entry {
|
match undo_entry {
|
||||||
&AddConstraint(Constraint::VarSubVar(a, b)) => {
|
&AddConstraint(Constraint::VarSubVar(a, b)) => {
|
||||||
self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
|
self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
|
||||||
|
|
|
@ -4,11 +4,13 @@ use self::CombineMapType::*;
|
||||||
use self::UndoLog::*;
|
use self::UndoLog::*;
|
||||||
|
|
||||||
use super::unify_key;
|
use super::unify_key;
|
||||||
use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
|
use super::{Logs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin};
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
use rustc_data_structures::undo_log::UndoLogs;
|
||||||
use rustc_data_structures::unify as ut;
|
use rustc_data_structures::unify as ut;
|
||||||
|
use rustc_data_structures::unify::UnifyKey;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::ty::ReStatic;
|
use rustc_middle::ty::ReStatic;
|
||||||
|
@ -26,7 +28,7 @@ mod leak_check;
|
||||||
pub use rustc_middle::infer::MemberConstraint;
|
pub use rustc_middle::infer::MemberConstraint;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RegionConstraintCollector<'tcx> {
|
pub struct RegionConstraintStorage<'tcx> {
|
||||||
/// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
|
/// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
|
||||||
var_infos: IndexVec<RegionVid, RegionVariableInfo>,
|
var_infos: IndexVec<RegionVid, RegionVariableInfo>,
|
||||||
|
|
||||||
|
@ -42,20 +44,6 @@ pub struct RegionConstraintCollector<'tcx> {
|
||||||
/// exist). This prevents us from making many such regions.
|
/// exist). This prevents us from making many such regions.
|
||||||
glbs: CombineMap<'tcx>,
|
glbs: CombineMap<'tcx>,
|
||||||
|
|
||||||
/// The undo log records actions that might later be undone.
|
|
||||||
///
|
|
||||||
/// Note: `num_open_snapshots` is used to track if we are actively
|
|
||||||
/// snapshotting. When the `start_snapshot()` method is called, we
|
|
||||||
/// increment `num_open_snapshots` to indicate that we are now actively
|
|
||||||
/// snapshotting. The reason for this is that otherwise we end up adding
|
|
||||||
/// entries for things like the lower bound on a variable and so forth,
|
|
||||||
/// which can never be rolled back.
|
|
||||||
undo_log: Vec<UndoLog<'tcx>>,
|
|
||||||
|
|
||||||
/// The number of open snapshots, i.e., those that haven't been committed or
|
|
||||||
/// rolled back.
|
|
||||||
num_open_snapshots: usize,
|
|
||||||
|
|
||||||
/// When we add a R1 == R2 constriant, we currently add (a) edges
|
/// When we add a R1 == R2 constriant, we currently add (a) edges
|
||||||
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
|
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
|
||||||
/// table. You can then call `opportunistic_resolve_var` early
|
/// table. You can then call `opportunistic_resolve_var` early
|
||||||
|
@ -64,13 +52,31 @@ pub struct RegionConstraintCollector<'tcx> {
|
||||||
/// is iterating to a fixed point, because otherwise we sometimes
|
/// is iterating to a fixed point, because otherwise we sometimes
|
||||||
/// would wind up with a fresh stream of region variables that
|
/// would wind up with a fresh stream of region variables that
|
||||||
/// have been equated but appear distinct.
|
/// have been equated but appear distinct.
|
||||||
unification_table: ut::UnificationTable<ut::InPlace<ty::RegionVid>>,
|
pub(super) unification_table: ut::UnificationStorage<ty::RegionVid>,
|
||||||
|
|
||||||
/// a flag set to true when we perform any unifications; this is used
|
/// a flag set to true when we perform any unifications; this is used
|
||||||
/// to micro-optimize `take_and_reset_data`
|
/// to micro-optimize `take_and_reset_data`
|
||||||
any_unifications: bool,
|
any_unifications: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RegionConstraintCollector<'tcx, 'a> {
|
||||||
|
storage: &'a mut RegionConstraintStorage<'tcx>,
|
||||||
|
undo_log: &'a mut Logs<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for RegionConstraintCollector<'tcx, '_> {
|
||||||
|
type Target = RegionConstraintStorage<'tcx>;
|
||||||
|
fn deref(&self) -> &RegionConstraintStorage<'tcx> {
|
||||||
|
self.storage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for RegionConstraintCollector<'tcx, '_> {
|
||||||
|
fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> {
|
||||||
|
self.storage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
|
pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
|
||||||
|
|
||||||
/// The full set of region constraints gathered up by the collector.
|
/// The full set of region constraints gathered up by the collector.
|
||||||
|
@ -258,13 +264,13 @@ pub enum VerifyBound<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct TwoRegions<'tcx> {
|
pub(crate) struct TwoRegions<'tcx> {
|
||||||
a: Region<'tcx>,
|
a: Region<'tcx>,
|
||||||
b: Region<'tcx>,
|
b: Region<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum UndoLog<'tcx> {
|
pub(crate) enum UndoLog<'tcx> {
|
||||||
/// We added `RegionVid`.
|
/// We added `RegionVid`.
|
||||||
AddVar(RegionVid),
|
AddVar(RegionVid),
|
||||||
|
|
||||||
|
@ -290,7 +296,7 @@ enum UndoLog<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum CombineMapType {
|
pub(crate) enum CombineMapType {
|
||||||
Lub,
|
Lub,
|
||||||
Glb,
|
Glb,
|
||||||
}
|
}
|
||||||
|
@ -304,8 +310,7 @@ pub struct RegionVariableInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RegionSnapshot {
|
pub struct RegionSnapshot {
|
||||||
length: usize,
|
value_count: usize,
|
||||||
region_snapshot: ut::Snapshot<ut::InPlace<ty::RegionVid>>,
|
|
||||||
any_unifications: bool,
|
any_unifications: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,129 +339,16 @@ impl TaintDirections {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> RegionConstraintCollector<'tcx> {
|
impl<'tcx> RegionConstraintStorage<'tcx> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_region_vars(&self) -> usize {
|
pub(crate) fn with_log<'a>(
|
||||||
self.var_infos.len()
|
&'a mut self,
|
||||||
}
|
undo_log: &'a mut Logs<'tcx>,
|
||||||
|
) -> RegionConstraintCollector<'tcx, 'a> {
|
||||||
pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
|
RegionConstraintCollector { storage: self, undo_log }
|
||||||
&self.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Once all the constraints have been gathered, extract out the final data.
|
|
||||||
///
|
|
||||||
/// Not legal during a snapshot.
|
|
||||||
pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
|
|
||||||
assert!(!self.in_snapshot());
|
|
||||||
(self.var_infos, self.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes (and clears) the current set of constraints. Note that
|
|
||||||
/// the set of variables remains intact, but all relationships
|
|
||||||
/// between them are reset. This is used during NLL checking to
|
|
||||||
/// grab the set of constraints that arose from a particular
|
|
||||||
/// operation.
|
|
||||||
///
|
|
||||||
/// We don't want to leak relationships between variables between
|
|
||||||
/// points because just because (say) `r1 == r2` was true at some
|
|
||||||
/// point P in the graph doesn't imply that it will be true at
|
|
||||||
/// some other point Q, in NLL.
|
|
||||||
///
|
|
||||||
/// Not legal during a snapshot.
|
|
||||||
pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
|
|
||||||
assert!(!self.in_snapshot());
|
|
||||||
|
|
||||||
// If you add a new field to `RegionConstraintCollector`, you
|
|
||||||
// should think carefully about whether it needs to be cleared
|
|
||||||
// or updated in some way.
|
|
||||||
let RegionConstraintCollector {
|
|
||||||
var_infos: _,
|
|
||||||
data,
|
|
||||||
lubs,
|
|
||||||
glbs,
|
|
||||||
undo_log: _,
|
|
||||||
num_open_snapshots: _,
|
|
||||||
unification_table,
|
|
||||||
any_unifications,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
// Clear the tables of (lubs, glbs), so that we will create
|
|
||||||
// fresh regions if we do a LUB operation. As it happens,
|
|
||||||
// LUB/GLB are not performed by the MIR type-checker, which is
|
|
||||||
// the one that uses this method, but it's good to be correct.
|
|
||||||
lubs.clear();
|
|
||||||
glbs.clear();
|
|
||||||
|
|
||||||
// Clear all unifications and recreate the variables a "now
|
|
||||||
// un-unified" state. Note that when we unify `a` and `b`, we
|
|
||||||
// also insert `a <= b` and a `b <= a` edges, so the
|
|
||||||
// `RegionConstraintData` contains the relationship here.
|
|
||||||
if *any_unifications {
|
|
||||||
unification_table.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
|
|
||||||
*any_unifications = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem::take(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data(&self) -> &RegionConstraintData<'tcx> {
|
|
||||||
&self.data
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_snapshot(&self) -> bool {
|
|
||||||
self.num_open_snapshots > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_snapshot(&mut self) -> RegionSnapshot {
|
|
||||||
let length = self.undo_log.len();
|
|
||||||
debug!("RegionConstraintCollector: start_snapshot({})", length);
|
|
||||||
self.num_open_snapshots += 1;
|
|
||||||
RegionSnapshot {
|
|
||||||
length,
|
|
||||||
region_snapshot: self.unification_table.snapshot(),
|
|
||||||
any_unifications: self.any_unifications,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_open_snapshot(&self, snapshot: &RegionSnapshot) {
|
|
||||||
assert!(self.undo_log.len() >= snapshot.length);
|
|
||||||
assert!(self.num_open_snapshots > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn commit(&mut self, snapshot: RegionSnapshot) {
|
|
||||||
debug!("RegionConstraintCollector: commit({})", snapshot.length);
|
|
||||||
self.assert_open_snapshot(&snapshot);
|
|
||||||
|
|
||||||
if self.num_open_snapshots == 1 {
|
|
||||||
// The root snapshot. It's safe to clear the undo log because
|
|
||||||
// there's no snapshot further out that we might need to roll back
|
|
||||||
// to.
|
|
||||||
assert!(snapshot.length == 0);
|
|
||||||
self.undo_log.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.num_open_snapshots -= 1;
|
|
||||||
|
|
||||||
self.unification_table.commit(snapshot.region_snapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
|
|
||||||
debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
|
|
||||||
self.assert_open_snapshot(&snapshot);
|
|
||||||
|
|
||||||
while self.undo_log.len() > snapshot.length {
|
|
||||||
let undo_entry = self.undo_log.pop().unwrap();
|
|
||||||
self.rollback_undo_entry(undo_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.num_open_snapshots -= 1;
|
|
||||||
|
|
||||||
self.unification_table.rollback_to(snapshot.region_snapshot);
|
|
||||||
self.any_unifications = snapshot.any_unifications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
||||||
|
@ -486,6 +378,90 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> RegionConstraintCollector<'tcx, '_> {
|
||||||
|
pub fn num_region_vars(&self) -> usize {
|
||||||
|
self.var_infos.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Once all the constraints have been gathered, extract out the final data.
|
||||||
|
///
|
||||||
|
/// Not legal during a snapshot.
|
||||||
|
pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
|
||||||
|
assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
||||||
|
(mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes (and clears) the current set of constraints. Note that
|
||||||
|
/// the set of variables remains intact, but all relationships
|
||||||
|
/// between them are reset. This is used during NLL checking to
|
||||||
|
/// grab the set of constraints that arose from a particular
|
||||||
|
/// operation.
|
||||||
|
///
|
||||||
|
/// We don't want to leak relationships between variables between
|
||||||
|
/// points because just because (say) `r1 == r2` was true at some
|
||||||
|
/// point P in the graph doesn't imply that it will be true at
|
||||||
|
/// some other point Q, in NLL.
|
||||||
|
///
|
||||||
|
/// Not legal during a snapshot.
|
||||||
|
pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
|
||||||
|
assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
||||||
|
|
||||||
|
// If you add a new field to `RegionConstraintCollector`, you
|
||||||
|
// should think carefully about whether it needs to be cleared
|
||||||
|
// or updated in some way.
|
||||||
|
let RegionConstraintStorage {
|
||||||
|
var_infos: _,
|
||||||
|
data,
|
||||||
|
lubs,
|
||||||
|
glbs,
|
||||||
|
unification_table: _,
|
||||||
|
any_unifications,
|
||||||
|
} = self.storage;
|
||||||
|
|
||||||
|
// Clear the tables of (lubs, glbs), so that we will create
|
||||||
|
// fresh regions if we do a LUB operation. As it happens,
|
||||||
|
// LUB/GLB are not performed by the MIR type-checker, which is
|
||||||
|
// the one that uses this method, but it's good to be correct.
|
||||||
|
lubs.clear();
|
||||||
|
glbs.clear();
|
||||||
|
|
||||||
|
let data = mem::take(data);
|
||||||
|
|
||||||
|
// Clear all unifications and recreate the variables a "now
|
||||||
|
// un-unified" state. Note that when we unify `a` and `b`, we
|
||||||
|
// also insert `a <= b` and a `b <= a` edges, so the
|
||||||
|
// `RegionConstraintData` contains the relationship here.
|
||||||
|
if *any_unifications {
|
||||||
|
*any_unifications = false;
|
||||||
|
self.unification_table()
|
||||||
|
.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
|
||||||
|
}
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data(&self) -> &RegionConstraintData<'tcx> {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_snapshot(&mut self) -> RegionSnapshot {
|
||||||
|
debug!("RegionConstraintCollector: start_snapshot");
|
||||||
|
RegionSnapshot {
|
||||||
|
value_count: self.unification_table.len(),
|
||||||
|
any_unifications: self.any_unifications,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
|
||||||
|
debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
|
||||||
|
self.any_unifications = snapshot.any_unifications;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_region_var(
|
pub fn new_region_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -494,11 +470,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
) -> RegionVid {
|
) -> RegionVid {
|
||||||
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
|
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
|
||||||
|
|
||||||
let u_vid = self.unification_table.new_key(unify_key::RegionVidKey { min_vid: vid });
|
let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid });
|
||||||
assert_eq!(vid, u_vid);
|
assert_eq!(vid, u_vid);
|
||||||
if self.in_snapshot() {
|
self.undo_log.push(AddVar(vid));
|
||||||
self.undo_log.push(AddVar(vid));
|
|
||||||
}
|
|
||||||
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
|
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
|
||||||
vid
|
vid
|
||||||
}
|
}
|
||||||
|
@ -520,19 +494,30 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
|
pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
|
||||||
debug!("pop_placeholders(placeholders={:?})", placeholders);
|
debug!("pop_placeholders(placeholders={:?})", placeholders);
|
||||||
|
|
||||||
assert!(self.in_snapshot());
|
assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
||||||
|
|
||||||
let constraints_to_kill: Vec<usize> = self
|
let constraints_to_kill: Vec<usize> = self
|
||||||
.undo_log
|
.undo_log
|
||||||
|
.logs
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|&(_, undo_entry)| kill_constraint(placeholders, undo_entry))
|
.filter(|&(_, undo_entry)| match undo_entry {
|
||||||
|
super::UndoLog::RegionConstraintCollector(undo_entry) => {
|
||||||
|
kill_constraint(placeholders, undo_entry)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
.map(|(index, _)| index)
|
.map(|(index, _)| index)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for index in constraints_to_kill {
|
for index in constraints_to_kill {
|
||||||
let undo_entry = mem::replace(&mut self.undo_log[index], Purged);
|
let undo_entry = match &mut self.undo_log.logs[index] {
|
||||||
|
super::UndoLog::RegionConstraintCollector(undo_entry) => {
|
||||||
|
mem::replace(undo_entry, Purged)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
self.rollback_undo_entry(undo_entry);
|
self.rollback_undo_entry(undo_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,12 +551,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
// never overwrite an existing (constraint, origin) - only insert one if it isn't
|
// never overwrite an existing (constraint, origin) - only insert one if it isn't
|
||||||
// present in the map yet. This prevents origins from outside the snapshot being
|
// present in the map yet. This prevents origins from outside the snapshot being
|
||||||
// replaced with "less informative" origins e.g., during calls to `can_eq`
|
// replaced with "less informative" origins e.g., during calls to `can_eq`
|
||||||
let in_snapshot = self.in_snapshot();
|
|
||||||
let undo_log = &mut self.undo_log;
|
let undo_log = &mut self.undo_log;
|
||||||
self.data.constraints.entry(constraint).or_insert_with(|| {
|
self.storage.data.constraints.entry(constraint).or_insert_with(|| {
|
||||||
if in_snapshot {
|
undo_log.push(AddConstraint(constraint));
|
||||||
undo_log.push(AddConstraint(constraint));
|
|
||||||
}
|
|
||||||
origin
|
origin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -589,9 +571,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
|
|
||||||
let index = self.data.verifys.len();
|
let index = self.data.verifys.len();
|
||||||
self.data.verifys.push(verify);
|
self.data.verifys.push(verify);
|
||||||
if self.in_snapshot() {
|
self.undo_log.push(AddVerify(index));
|
||||||
self.undo_log.push(AddVerify(index));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
|
pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
|
||||||
|
@ -599,9 +579,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
if self.data.givens.insert((sub, sup)) {
|
if self.data.givens.insert((sub, sup)) {
|
||||||
debug!("add_given({:?} <= {:?})", sub, sup);
|
debug!("add_given({:?} <= {:?})", sub, sup);
|
||||||
|
|
||||||
if self.in_snapshot() {
|
self.undo_log.push(AddGiven(sub, sup));
|
||||||
self.undo_log.push(AddGiven(sub, sup));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +597,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
|
|
||||||
if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
|
if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
|
||||||
debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
|
debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
|
||||||
self.unification_table.union(sub, sup);
|
self.unification_table().union(sub, sup);
|
||||||
self.any_unifications = true;
|
self.any_unifications = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -741,7 +719,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
rid: RegionVid,
|
rid: RegionVid,
|
||||||
) -> ty::Region<'tcx> {
|
) -> ty::Region<'tcx> {
|
||||||
let vid = self.unification_table.probe_value(rid).min_vid;
|
let vid = self.unification_table().probe_value(rid).min_vid;
|
||||||
tcx.mk_region(ty::ReVar(vid))
|
tcx.mk_region(ty::ReVar(vid))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,9 +747,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
let c_universe = cmp::max(a_universe, b_universe);
|
let c_universe = cmp::max(a_universe, b_universe);
|
||||||
let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
|
let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
|
||||||
self.combine_map(t).insert(vars, c);
|
self.combine_map(t).insert(vars, c);
|
||||||
if self.in_snapshot() {
|
self.undo_log.push(AddCombination(t, vars));
|
||||||
self.undo_log.push(AddCombination(t, vars));
|
|
||||||
}
|
|
||||||
let new_r = tcx.mk_region(ReVar(c));
|
let new_r = tcx.mk_region(ReVar(c));
|
||||||
for &old_r in &[a, b] {
|
for &old_r in &[a, b] {
|
||||||
match t {
|
match t {
|
||||||
|
@ -801,7 +777,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
mark: &RegionSnapshot,
|
mark: &RegionSnapshot,
|
||||||
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
|
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
|
||||||
let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot);
|
let range = RegionVid::from_index(mark.value_count as u32)
|
||||||
|
..RegionVid::from_index(self.unification_table.len() as u32);
|
||||||
(
|
(
|
||||||
range.clone(),
|
range.clone(),
|
||||||
(range.start.index()..range.end.index())
|
(range.start.index()..range.end.index())
|
||||||
|
@ -810,10 +787,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See `InferCtxt::region_constraints_added_in_snapshot`.
|
/// See [`RegionInference::region_constraints_added_in_snapshot`].
|
||||||
pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> Option<bool> {
|
pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'_>) -> Option<bool> {
|
||||||
self.undo_log[mark.length..]
|
self.undo_log
|
||||||
.iter()
|
.region_constraints(mark.undo_len)
|
||||||
.map(|&elt| match elt {
|
.map(|&elt| match elt {
|
||||||
AddConstraint(constraint) => Some(constraint.involves_placeholders()),
|
AddConstraint(constraint) => Some(constraint.involves_placeholders()),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -821,11 +798,15 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> {
|
||||||
|
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for RegionSnapshot {
|
impl fmt::Debug for RegionSnapshot {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "RegionSnapshot(length={})", self.length)
|
write!(f, "RegionSnapshot")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -910,3 +891,9 @@ impl<'tcx> RegionConstraintData<'tcx> {
|
||||||
&& givens.is_empty()
|
&& givens.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Rollback<UndoLog<'tcx>> for RegionConstraintStorage<'tcx> {
|
||||||
|
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||||
|
self.rollback_undo_entry(undo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -344,23 +344,11 @@ impl<'tcx> TypeVariableTable<'tcx, '_> {
|
||||||
sv::SnapshotVec::with_log(self.values, self.undo_log)
|
sv::SnapshotVec::with_log(self.values, self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_relations(
|
fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> {
|
||||||
&mut self,
|
|
||||||
) -> ut::UnificationTable<
|
|
||||||
ut::InPlace<
|
|
||||||
TyVidEqKey<'tcx>,
|
|
||||||
&mut ut::UnificationStorage<TyVidEqKey<'tcx>>,
|
|
||||||
&mut Logs<'tcx>,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
ut::UnificationTable::with_log(self.eq_relations, self.undo_log)
|
ut::UnificationTable::with_log(self.eq_relations, self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_relations(
|
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
|
||||||
&mut self,
|
|
||||||
) -> ut::UnificationTable<
|
|
||||||
ut::InPlace<ty::TyVid, &mut ut::UnificationStorage<ty::TyVid>, &mut Logs<'tcx>>,
|
|
||||||
> {
|
|
||||||
ut::UnificationTable::with_log(self.sub_relations, self.undo_log)
|
ut::UnificationTable::with_log(self.sub_relations, self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue