diff --git a/src/librustc_data_structures/snapshot_vec.rs b/src/librustc_data_structures/snapshot_vec.rs deleted file mode 100644 index 2da91918288bab77ff8266086a662ea150fc4aad..0000000000000000000000000000000000000000 --- a/src/librustc_data_structures/snapshot_vec.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A utility class for implementing "snapshottable" things; a snapshottable data structure permits -//! you to take a snapshot (via `start_snapshot`) and then, after making some changes, elect either -//! to rollback to the start of the snapshot or commit those changes. -//! -//! This vector is intended to be used as part of an abstraction, not serve as a complete -//! abstraction on its own. As such, while it will roll back most changes on its own, it also -//! supports a `get_mut` operation that gives you an arbitrary mutable pointer into the vector. To -//! ensure that any changes you make this with this pointer are rolled back, you must invoke -//! `record` to record any changes you make and also supplying a delegate capable of reversing -//! those changes. -use self::UndoLog::*; - -use std::mem; -use std::ops; - -pub enum UndoLog { - /// Indicates where a snapshot started. - OpenSnapshot, - - /// Indicates a snapshot that has been committed. - CommittedSnapshot, - - /// New variable with given index was created. - NewElem(usize), - - /// Variable with given index was changed *from* the given value. - SetElem(usize, D::Value), - - /// Extensible set of actions - Other(D::Undo), -} - -pub struct SnapshotVec { - values: Vec, - undo_log: Vec>, -} - -// Snapshots are tokens that should be created/consumed linearly. -pub struct Snapshot { - // Length of the undo log at the time the snapshot was taken. - length: usize, -} - -pub trait SnapshotVecDelegate { - type Value; - type Undo; - - fn reverse(values: &mut Vec, action: Self::Undo); -} - -impl SnapshotVec { - pub fn new() -> SnapshotVec { - SnapshotVec { - values: Vec::new(), - undo_log: Vec::new(), - } - } - - pub fn with_capacity(n: usize) -> SnapshotVec { - SnapshotVec { - values: Vec::with_capacity(n), - undo_log: Vec::new(), - } - } - - fn in_snapshot(&self) -> bool { - !self.undo_log.is_empty() - } - - pub fn record(&mut self, action: D::Undo) { - if self.in_snapshot() { - self.undo_log.push(Other(action)); - } - } - - pub fn len(&self) -> usize { - self.values.len() - } - - pub fn push(&mut self, elem: D::Value) -> usize { - let len = self.values.len(); - self.values.push(elem); - - if self.in_snapshot() { - self.undo_log.push(NewElem(len)); - } - - len - } - - pub fn get(&self, index: usize) -> &D::Value { - &self.values[index] - } - - /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone - /// automatically, so you should be sure call `record()` with some sort of suitable undo - /// action. - pub fn get_mut(&mut self, index: usize) -> &mut D::Value { - &mut self.values[index] - } - - /// Updates the element at the given index. The old value will saved (and perhaps restored) if - /// a snapshot is active. - pub fn set(&mut self, index: usize, new_elem: D::Value) { - let old_elem = mem::replace(&mut self.values[index], new_elem); - if self.in_snapshot() { - self.undo_log.push(SetElem(index, old_elem)); - } - } - - pub fn start_snapshot(&mut self) -> Snapshot { - let length = self.undo_log.len(); - self.undo_log.push(OpenSnapshot); - Snapshot { length: length } - } - - pub fn actions_since_snapshot(&self, snapshot: &Snapshot) -> &[UndoLog] { - &self.undo_log[snapshot.length..] - } - - fn assert_open_snapshot(&self, snapshot: &Snapshot) { - // Or else there was a failure to follow a stack discipline: - assert!(self.undo_log.len() > snapshot.length); - - // Invariant established by start_snapshot(): - assert!(match self.undo_log[snapshot.length] { - OpenSnapshot => true, - _ => false, - }); - } - - pub fn rollback_to(&mut self, snapshot: Snapshot) { - debug!("rollback_to({})", snapshot.length); - - self.assert_open_snapshot(&snapshot); - - while self.undo_log.len() > snapshot.length + 1 { - match self.undo_log.pop().unwrap() { - OpenSnapshot => { - // This indicates a failure to obey the stack discipline. - panic!("Cannot rollback an uncommitted snapshot"); - } - - CommittedSnapshot => { - // This occurs when there are nested snapshots and - // the inner is committed but outer is rolled back. - } - - NewElem(i) => { - self.values.pop(); - assert!(self.values.len() == i); - } - - SetElem(i, v) => { - self.values[i] = v; - } - - Other(u) => { - D::reverse(&mut self.values, u); - } - } - } - - let v = self.undo_log.pop().unwrap(); - assert!(match v { - OpenSnapshot => true, - _ => false, - }); - assert!(self.undo_log.len() == snapshot.length); - } - - /// Commits all changes since the last snapshot. Of course, they - /// can still be undone if there is a snapshot further out. - pub fn commit(&mut self, snapshot: Snapshot) { - debug!("commit({})", snapshot.length); - - self.assert_open_snapshot(&snapshot); - - if snapshot.length == 0 { - // The root snapshot. - self.undo_log.truncate(0); - } else { - self.undo_log[snapshot.length] = CommittedSnapshot; - } - } -} - -impl ops::Deref for SnapshotVec { - type Target = [D::Value]; - fn deref(&self) -> &[D::Value] { - &*self.values - } -} - -impl ops::DerefMut for SnapshotVec { - fn deref_mut(&mut self) -> &mut [D::Value] { - &mut *self.values - } -} - -impl ops::Index for SnapshotVec { - type Output = D::Value; - fn index(&self, index: usize) -> &D::Value { - self.get(index) - } -} - -impl ops::IndexMut for SnapshotVec { - fn index_mut(&mut self, index: usize) -> &mut D::Value { - self.get_mut(index) - } -} - -impl Extend for SnapshotVec { - fn extend(&mut self, iterable: T) where T: IntoIterator { - for item in iterable { - self.push(item); - } - } -} diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs deleted file mode 100644 index 5411ae0257a4b050be7a05cf9b0b19189808eb86..0000000000000000000000000000000000000000 --- a/src/librustc_data_structures/unify/mod.rs +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::marker; -use std::fmt::Debug; -use std::marker::PhantomData; -use snapshot_vec as sv; - -#[cfg(test)] -mod tests; - -/// This trait is implemented by any type that can serve as a type -/// variable. We call such variables *unification keys*. For example, -/// this trait is implemented by `IntVid`, which represents integral -/// variables. -/// -/// Each key type has an associated value type `V`. For example, for -/// `IntVid`, this is `Option`, representing some -/// (possibly not yet known) sort of integer. -/// -/// Clients are expected to provide implementations of this trait; you -/// can see some examples in the `test` module. -pub trait UnifyKey: Copy + Clone + Debug + PartialEq { - type Value: Clone + PartialEq + Debug; - - fn index(&self) -> u32; - - fn from_index(u: u32) -> Self; - - fn tag(k: Option) -> &'static str; -} - -/// This trait is implemented for unify values that can be -/// combined. This relation should be a monoid. -pub trait Combine { - fn combine(&self, other: &Self) -> Self; -} - -impl Combine for () { - fn combine(&self, _other: &()) {} -} - -/// Value of a unification key. We implement Tarjan's union-find -/// algorithm: when two keys are unified, one of them is converted -/// into a "redirect" pointing at the other. These redirects form a -/// DAG: the roots of the DAG (nodes that are not redirected) are each -/// associated with a value of type `V` and a rank. The rank is used -/// to keep the DAG relatively balanced, which helps keep the running -/// time of the algorithm under control. For more information, see -/// . -#[derive(PartialEq,Clone,Debug)] -pub struct VarValue { - parent: K, // if equal to self, this is a root - value: K::Value, // value assigned (only relevant to root) - rank: u32, // max depth (only relevant to root) -} - -/// Table of unification keys and their values. -pub struct UnificationTable { - /// Indicates the current value of each key. - values: sv::SnapshotVec>, -} - -/// At any time, users may snapshot a unification table. The changes -/// made during the snapshot may either be *committed* or *rolled back*. -pub struct Snapshot { - // Link snapshot to the key type `K` of the table. - marker: marker::PhantomData, - snapshot: sv::Snapshot, -} - -#[derive(Copy, Clone)] -struct Delegate(PhantomData); - -impl VarValue { - fn new_var(key: K, value: K::Value) -> VarValue { - VarValue::new(key, value, 0) - } - - fn new(parent: K, value: K::Value, rank: u32) -> VarValue { - VarValue { - parent: parent, // this is a root - value, - rank, - } - } - - fn redirect(self, to: K) -> VarValue { - VarValue { parent: to, ..self } - } - - fn root(self, rank: u32, value: K::Value) -> VarValue { - VarValue { - rank, - value, - ..self - } - } - - /// Returns the key of this node. Only valid if this is a root - /// node, which you yourself must ensure. - fn key(&self) -> K { - self.parent - } - - fn parent(&self, self_key: K) -> Option { - self.if_not_self(self.parent, self_key) - } - - fn if_not_self(&self, key: K, self_key: K) -> Option { - if key == self_key { None } else { Some(key) } - } -} - -/// We can't use V:LatticeValue, much as I would like to, -/// because frequently the pattern is that V=Option for some -/// other type parameter U, and we have no way to say -/// Option:LatticeValue. - -impl UnificationTable { - pub fn new() -> UnificationTable { - UnificationTable { values: sv::SnapshotVec::new() } - } - - /// Starts a new snapshot. Each snapshot must be either - /// rolled back or committed in a "LIFO" (stack) order. - pub fn snapshot(&mut self) -> Snapshot { - Snapshot { - marker: marker::PhantomData::, - snapshot: self.values.start_snapshot(), - } - } - - /// Reverses all changes since the last snapshot. Also - /// removes any keys that have been created since then. - pub fn rollback_to(&mut self, snapshot: Snapshot) { - debug!("{}: rollback_to()", UnifyKey::tag(None::)); - self.values.rollback_to(snapshot.snapshot); - } - - /// Commits all changes since the last snapshot. Of course, they - /// can still be undone if there is a snapshot further out. - pub fn commit(&mut self, snapshot: Snapshot) { - debug!("{}: commit()", UnifyKey::tag(None::)); - self.values.commit(snapshot.snapshot); - } - - pub fn new_key(&mut self, value: K::Value) -> K { - let len = self.values.len(); - let key: K = UnifyKey::from_index(len as u32); - self.values.push(VarValue::new_var(key, value)); - debug!("{}: created new key: {:?}", UnifyKey::tag(None::), key); - key - } - - /// Find the root node for `vid`. This uses the standard - /// union-find algorithm with path compression: - /// . - /// - /// NB. This is a building-block operation and you would probably - /// prefer to call `probe` below. - fn get(&mut self, vid: K) -> VarValue { - let index = vid.index() as usize; - let mut value: VarValue = self.values.get(index).clone(); - match value.parent(vid) { - Some(redirect) => { - let root: VarValue = self.get(redirect); - if root.key() != redirect { - // Path compression - value.parent = root.key(); - self.values.set(index, value); - } - root - } - None => value, - } - } - - fn is_root(&self, key: K) -> bool { - let index = key.index() as usize; - self.values.get(index).parent(key).is_none() - } - - /// Sets the value for `vid` to `new_value`. `vid` MUST be a root - /// node! This is an internal operation used to impl other things. - fn set(&mut self, key: K, new_value: VarValue) { - assert!(self.is_root(key)); - - debug!("Updating variable {:?} to {:?}", key, new_value); - - let index = key.index() as usize; - self.values.set(index, new_value); - } - - /// Either redirects `node_a` to `node_b` or vice versa, depending - /// on the relative rank. The value associated with the new root - /// will be `new_value`. - /// - /// NB: This is the "union" operation of "union-find". It is - /// really more of a building block. If the values associated with - /// your key are non-trivial, you would probably prefer to call - /// `unify_var_var` below. - fn unify(&mut self, root_a: VarValue, root_b: VarValue, new_value: K::Value) -> K { - debug!("unify(root_a(id={:?}, rank={:?}), root_b(id={:?}, rank={:?}))", - root_a.key(), - root_a.rank, - root_b.key(), - root_b.rank); - - if root_a.rank > root_b.rank { - // a has greater rank, so a should become b's parent, - // i.e., b should redirect to a. - self.redirect_root(root_a.rank, root_b, root_a, new_value) - } else if root_a.rank < root_b.rank { - // b has greater rank, so a should redirect to b. - self.redirect_root(root_b.rank, root_a, root_b, new_value) - } else { - // If equal, redirect one to the other and increment the - // other's rank. - self.redirect_root(root_a.rank + 1, root_a, root_b, new_value) - } - } - - fn redirect_root(&mut self, - new_rank: u32, - old_root: VarValue, - new_root: VarValue, - new_value: K::Value) - -> K { - let old_root_key = old_root.key(); - let new_root_key = new_root.key(); - self.set(old_root_key, old_root.redirect(new_root_key)); - self.set(new_root_key, new_root.root(new_rank, new_value)); - new_root_key - } -} - -impl sv::SnapshotVecDelegate for Delegate { - type Value = VarValue; - type Undo = (); - - fn reverse(_: &mut Vec>, _: ()) {} -} - -/// # Base union-find algorithm, where we are just making sets - -impl<'tcx, K: UnifyKey> UnificationTable - where K::Value: Combine -{ - pub fn union(&mut self, a_id: K, b_id: K) -> K { - let node_a = self.get(a_id); - let node_b = self.get(b_id); - let a_id = node_a.key(); - let b_id = node_b.key(); - if a_id != b_id { - let new_value = node_a.value.combine(&node_b.value); - self.unify(node_a, node_b, new_value) - } else { - a_id - } - } - - pub fn find(&mut self, id: K) -> K { - self.get(id).key() - } - - pub fn find_value(&mut self, id: K) -> K::Value { - self.get(id).value - } - - #[cfg(test)] - fn unioned(&mut self, a_id: K, b_id: K) -> bool { - self.find(a_id) == self.find(b_id) - } -} - -/// # Non-subtyping unification -/// -/// Code to handle keys which carry a value, like ints, -/// floats---anything that doesn't have a subtyping relationship we -/// need to worry about. - -impl<'tcx, K, V> UnificationTable - where K: UnifyKey>, - V: Clone + PartialEq + Debug -{ - pub fn unify_var_var(&mut self, a_id: K, b_id: K) -> Result { - let node_a = self.get(a_id); - let node_b = self.get(b_id); - let a_id = node_a.key(); - let b_id = node_b.key(); - - if a_id == b_id { - return Ok(a_id); - } - - let combined = { - match (&node_a.value, &node_b.value) { - (&None, &None) => None, - (&Some(ref v), &None) | - (&None, &Some(ref v)) => Some(v.clone()), - (&Some(ref v1), &Some(ref v2)) => { - if *v1 != *v2 { - return Err((v1.clone(), v2.clone())); - } - Some(v1.clone()) - } - } - }; - - Ok(self.unify(node_a, node_b, combined)) - } - - /// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping - /// relationships, if `a_id` already has a value, it must be the same as `b`. - pub fn unify_var_value(&mut self, a_id: K, b: V) -> Result<(), (V, V)> { - let mut node_a = self.get(a_id); - - match node_a.value { - None => { - node_a.value = Some(b); - self.set(node_a.key(), node_a); - Ok(()) - } - - Some(ref a_t) => { - if *a_t == b { - Ok(()) - } else { - Err((a_t.clone(), b)) - } - } - } - } - - pub fn has_value(&mut self, id: K) -> bool { - self.get(id).value.is_some() - } - - pub fn probe(&mut self, a_id: K) -> Option { - self.get(a_id).value - } - - pub fn unsolved_variables(&mut self) -> Vec { - self.values - .iter() - .filter_map(|vv| { - if vv.value.is_some() { - None - } else { - Some(vv.key()) - } - }) - .collect() - } -} diff --git a/src/librustc_data_structures/unify/tests.rs b/src/librustc_data_structures/unify/tests.rs deleted file mode 100644 index f29a7132e831b3f0e926968ce0d4fc6d843200fe..0000000000000000000000000000000000000000 --- a/src/librustc_data_structures/unify/tests.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(non_snake_case)] - -extern crate test; -use self::test::Bencher; -use unify::{UnifyKey, UnificationTable}; - -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -struct UnitKey(u32); - -impl UnifyKey for UnitKey { - type Value = (); - fn index(&self) -> u32 { - self.0 - } - fn from_index(u: u32) -> UnitKey { - UnitKey(u) - } - fn tag(_: Option) -> &'static str { - "UnitKey" - } -} - -#[test] -fn basic() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(()); - let k2 = ut.new_key(()); - assert_eq!(ut.unioned(k1, k2), false); - ut.union(k1, k2); - assert_eq!(ut.unioned(k1, k2), true); -} - -#[test] -fn big_array() { - let mut ut: UnificationTable = UnificationTable::new(); - let mut keys = Vec::new(); - const MAX: usize = 1 << 15; - - for _ in 0..MAX { - keys.push(ut.new_key(())); - } - - for i in 1..MAX { - let l = keys[i - 1]; - let r = keys[i]; - ut.union(l, r); - } - - for i in 0..MAX { - assert!(ut.unioned(keys[0], keys[i])); - } -} - -#[bench] -fn big_array_bench(b: &mut Bencher) { - let mut ut: UnificationTable = UnificationTable::new(); - let mut keys = Vec::new(); - const MAX: usize = 1 << 15; - - for _ in 0..MAX { - keys.push(ut.new_key(())); - } - - - b.iter(|| { - for i in 1..MAX { - let l = keys[i - 1]; - let r = keys[i]; - ut.union(l, r); - } - - for i in 0..MAX { - assert!(ut.unioned(keys[0], keys[i])); - } - }) -} - -#[test] -fn even_odd() { - let mut ut: UnificationTable = UnificationTable::new(); - let mut keys = Vec::new(); - const MAX: usize = 1 << 10; - - for i in 0..MAX { - let key = ut.new_key(()); - keys.push(key); - - if i >= 2 { - ut.union(key, keys[i - 2]); - } - } - - for i in 1..MAX { - assert!(!ut.unioned(keys[i - 1], keys[i])); - } - - for i in 2..MAX { - assert!(ut.unioned(keys[i - 2], keys[i])); - } -} - -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -struct IntKey(u32); - -impl UnifyKey for IntKey { - type Value = Option; - fn index(&self) -> u32 { - self.0 - } - fn from_index(u: u32) -> IntKey { - IntKey(u) - } - fn tag(_: Option) -> &'static str { - "IntKey" - } -} - -/// Test unifying a key whose value is `Some(_)` with a key whose value is `None`. -/// Afterwards both should be `Some(_)`. -#[test] -fn unify_key_Some_key_None() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - let k2 = ut.new_key(None); - assert!(ut.unify_var_var(k1, k2).is_ok()); - assert_eq!(ut.probe(k2), Some(22)); - assert_eq!(ut.probe(k1), Some(22)); -} - -/// Test unifying a key whose value is `None` with a key whose value is `Some(_)`. -/// Afterwards both should be `Some(_)`. -#[test] -fn unify_key_None_key_Some() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - let k2 = ut.new_key(None); - assert!(ut.unify_var_var(k2, k1).is_ok()); - assert_eq!(ut.probe(k2), Some(22)); - assert_eq!(ut.probe(k1), Some(22)); -} - -/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(y)`. -/// This should yield an error. -#[test] -fn unify_key_Some_x_key_Some_y() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - let k2 = ut.new_key(Some(23)); - assert_eq!(ut.unify_var_var(k1, k2), Err((22, 23))); - assert_eq!(ut.unify_var_var(k2, k1), Err((23, 22))); - assert_eq!(ut.probe(k1), Some(22)); - assert_eq!(ut.probe(k2), Some(23)); -} - -/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(x)`. -/// This should be ok. -#[test] -fn unify_key_Some_x_key_Some_x() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - let k2 = ut.new_key(Some(22)); - assert!(ut.unify_var_var(k1, k2).is_ok()); - assert_eq!(ut.probe(k1), Some(22)); - assert_eq!(ut.probe(k2), Some(22)); -} - -/// Test unifying a key whose value is `None` with a value is `x`. -/// Afterwards key should be `x`. -#[test] -fn unify_key_None_val() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(None); - assert!(ut.unify_var_value(k1, 22).is_ok()); - assert_eq!(ut.probe(k1), Some(22)); -} - -/// Test unifying a key whose value is `Some(x)` with the value `y`. -/// This should yield an error. -#[test] -fn unify_key_Some_x_val_y() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - assert_eq!(ut.unify_var_value(k1, 23), Err((22, 23))); - assert_eq!(ut.probe(k1), Some(22)); -} - -/// Test unifying a key whose value is `Some(x)` with the value `x`. -/// This should be ok. -#[test] -fn unify_key_Some_x_val_x() { - let mut ut: UnificationTable = UnificationTable::new(); - let k1 = ut.new_key(Some(22)); - assert!(ut.unify_var_value(k1, 22).is_ok()); - assert_eq!(ut.probe(k1), Some(22)); -}