2014-05-28 14:36:05 -05:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-01-06 16:33:42 -06:00
|
|
|
use std::marker;
|
2015-01-20 17:45:07 -06:00
|
|
|
use std::fmt::Debug;
|
2015-02-12 11:41:31 -06:00
|
|
|
use std::marker::PhantomData;
|
2015-04-07 05:12:21 -05:00
|
|
|
use snapshot_vec as sv;
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test;
|
2014-06-20 05:35:06 -05:00
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// 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<IntVarValue>`, representing some
|
|
|
|
/// (possibly not yet known) sort of integer.
|
|
|
|
///
|
2015-04-07 05:12:21 -05:00
|
|
|
/// 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;
|
2015-01-21 19:25:24 -06:00
|
|
|
|
2015-02-16 04:07:22 -06:00
|
|
|
fn index(&self) -> u32;
|
2014-06-20 05:35:06 -05:00
|
|
|
|
2015-02-16 04:07:22 -06:00
|
|
|
fn from_index(u: u32) -> Self;
|
2014-06-20 05:35:06 -05:00
|
|
|
|
|
|
|
fn tag(k: Option<Self>) -> &'static str;
|
|
|
|
}
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// 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
|
|
|
|
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
|
2015-01-28 07:34:18 -06:00
|
|
|
#[derive(PartialEq,Clone,Debug)]
|
2015-04-07 05:12:21 -05:00
|
|
|
pub struct VarValue<K:UnifyKey> {
|
|
|
|
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)
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// Table of unification keys and their values.
|
2015-01-21 19:25:24 -06:00
|
|
|
pub struct UnificationTable<K:UnifyKey> {
|
2014-11-24 19:06:06 -06:00
|
|
|
/// Indicates the current value of each key.
|
2015-01-21 19:25:24 -06:00
|
|
|
values: sv::SnapshotVec<Delegate<K>>,
|
2014-05-28 14:36:05 -05:00
|
|
|
}
|
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// At any time, users may snapshot a unification table. The changes
|
|
|
|
/// made during the snapshot may either be *committed* or *rolled back*.
|
2015-01-21 19:25:24 -06:00
|
|
|
pub struct Snapshot<K:UnifyKey> {
|
2014-07-22 06:40:51 -05:00
|
|
|
// Link snapshot to the key type `K` of the table.
|
2015-02-12 11:41:31 -06:00
|
|
|
marker: marker::PhantomData<K>,
|
2014-07-22 06:40:51 -05:00
|
|
|
snapshot: sv::Snapshot,
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
|
|
|
|
2015-03-30 08:38:44 -05:00
|
|
|
#[derive(Copy, Clone)]
|
2015-04-07 05:12:21 -05:00
|
|
|
struct Delegate<K>(PhantomData<K>);
|
|
|
|
|
|
|
|
impl<K:UnifyKey> VarValue<K> {
|
|
|
|
fn new_var(key: K, value: K::Value) -> VarValue<K> {
|
|
|
|
VarValue::new(key, value, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> {
|
|
|
|
VarValue { parent: parent, // this is a root
|
|
|
|
value: value,
|
|
|
|
rank: rank }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn redirect(self, to: K) -> VarValue<K> {
|
|
|
|
VarValue { parent: to, ..self }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn root(self, rank: u32, value: K::Value) -> VarValue<K> {
|
|
|
|
VarValue { rank: rank, value: 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<K> {
|
|
|
|
self.if_not_self(self.parent, self_key)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn if_not_self(&self, key: K, self_key: K) -> Option<K> {
|
|
|
|
if key == self_key {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-22 06:40:51 -05:00
|
|
|
|
2014-06-20 05:35:06 -05:00
|
|
|
// We can't use V:LatticeValue, much as I would like to,
|
2014-07-22 06:46:36 -05:00
|
|
|
// because frequently the pattern is that V=Option<U> for some
|
2014-06-20 05:35:06 -05:00
|
|
|
// other type parameter U, and we have no way to say
|
2014-07-22 06:46:36 -05:00
|
|
|
// Option<U>:LatticeValue.
|
2014-06-20 05:35:06 -05:00
|
|
|
|
2015-01-21 19:25:24 -06:00
|
|
|
impl<K:UnifyKey> UnificationTable<K> {
|
|
|
|
pub fn new() -> UnificationTable<K> {
|
2014-06-20 05:35:06 -05:00
|
|
|
UnificationTable {
|
2015-04-07 05:12:21 -05:00
|
|
|
values: sv::SnapshotVec::new()
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// Starts a new snapshot. Each snapshot must be either
|
|
|
|
/// rolled back or committed in a "LIFO" (stack) order.
|
2014-06-20 05:35:06 -05:00
|
|
|
pub fn snapshot(&mut self) -> Snapshot<K> {
|
2015-02-12 11:41:31 -06:00
|
|
|
Snapshot { marker: marker::PhantomData::<K>,
|
2014-07-22 06:40:51 -05:00
|
|
|
snapshot: self.values.start_snapshot() }
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// Reverses all changes since the last snapshot. Also
|
|
|
|
/// removes any keys that have been created since then.
|
2014-07-22 06:40:51 -05:00
|
|
|
pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
|
|
|
|
debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
|
|
|
|
self.values.rollback_to(snapshot.snapshot);
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
|
2014-11-24 19:06:06 -06:00
|
|
|
/// Commits all changes since the last snapshot. Of course, they
|
|
|
|
/// can still be undone if there is a snapshot further out.
|
2014-06-20 05:35:06 -05:00
|
|
|
pub fn commit(&mut self, snapshot: Snapshot<K>) {
|
2014-07-22 06:40:51 -05:00
|
|
|
debug!("{}: commit()", UnifyKey::tag(None::<K>));
|
|
|
|
self.values.commit(snapshot.snapshot);
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
|
2015-01-21 19:25:24 -06:00
|
|
|
pub fn new_key(&mut self, value: K::Value) -> K {
|
2015-04-07 05:12:21 -05:00
|
|
|
let len = self.values.len();
|
|
|
|
let key: K = UnifyKey::from_index(len as u32);
|
|
|
|
self.values.push(VarValue::new_var(key, value));
|
2014-12-20 02:09:35 -06:00
|
|
|
debug!("{}: created new key: {:?}",
|
2014-06-20 05:35:06 -05:00
|
|
|
UnifyKey::tag(None::<K>),
|
2015-04-07 05:12:21 -05:00
|
|
|
key);
|
|
|
|
key
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
|
2015-02-15 14:16:45 -06:00
|
|
|
/// Find the root node for `vid`. This uses the standard
|
|
|
|
/// union-find algorithm with path compression:
|
|
|
|
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
|
|
|
|
///
|
|
|
|
/// NB. This is a building-block operation and you would probably
|
|
|
|
/// prefer to call `probe` below.
|
2015-04-07 05:12:21 -05:00
|
|
|
fn get(&mut self, vid: K) -> VarValue<K> {
|
2015-02-16 04:07:22 -06:00
|
|
|
let index = vid.index() as usize;
|
2015-04-07 05:12:21 -05:00
|
|
|
let mut value: VarValue<K> = self.values.get(index).clone();
|
|
|
|
match value.parent(vid) {
|
|
|
|
Some(redirect) => {
|
|
|
|
let root: VarValue<K> = self.get(redirect);
|
|
|
|
if root.key() != redirect {
|
2014-06-20 05:35:06 -05:00
|
|
|
// Path compression
|
2015-04-07 05:12:21 -05:00
|
|
|
value.parent = root.key();
|
|
|
|
self.values.set(index, value);
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
2015-04-07 05:12:21 -05:00
|
|
|
root
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
2015-04-07 05:12:21 -05:00
|
|
|
None => {
|
|
|
|
value
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-07 05:12:21 -05:00
|
|
|
fn is_root(&self, key: K) -> bool {
|
2015-02-16 04:07:22 -06:00
|
|
|
let index = key.index() as usize;
|
2015-04-07 05:12:21 -05:00
|
|
|
self.values.get(index).parent(key).is_none()
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
|
2015-02-15 14:16:45 -06:00
|
|
|
/// 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<K>) {
|
2015-04-07 05:12:21 -05:00
|
|
|
assert!(self.is_root(key));
|
2014-06-20 05:35:06 -05:00
|
|
|
|
2015-01-21 19:25:24 -06:00
|
|
|
debug!("Updating variable {:?} to {:?}",
|
|
|
|
key, new_value);
|
2012-08-13 17:06:13 -05:00
|
|
|
|
2015-02-16 04:07:22 -06:00
|
|
|
let index = key.index() as usize;
|
|
|
|
self.values.set(index, new_value);
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
|
2015-02-15 14:16:45 -06:00
|
|
|
/// 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.
|
2015-04-07 05:12:21 -05:00
|
|
|
fn unify(&mut self, root_a: VarValue<K>, root_b: VarValue<K>, new_value: K::Value) {
|
|
|
|
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 {
|
2012-11-07 20:40:34 -06:00
|
|
|
// a has greater rank, so a should become b's parent,
|
|
|
|
// i.e., b should redirect to a.
|
2015-04-07 05:12:21 -05:00
|
|
|
self.redirect_root(root_a.rank, root_b, root_a, new_value);
|
|
|
|
} else if root_a.rank < root_b.rank {
|
2012-11-07 20:40:34 -06:00
|
|
|
// b has greater rank, so a should redirect to b.
|
2015-04-07 05:12:21 -05:00
|
|
|
self.redirect_root(root_b.rank, root_a, root_b, new_value);
|
2012-11-07 20:40:34 -06:00
|
|
|
} else {
|
2013-01-08 16:00:45 -06:00
|
|
|
// If equal, redirect one to the other and increment the
|
|
|
|
// other's rank.
|
2015-04-07 05:12:21 -05:00
|
|
|
self.redirect_root(root_a.rank + 1, root_a, root_b, new_value);
|
|
|
|
}
|
|
|
|
}
|
2015-02-15 14:16:45 -06:00
|
|
|
|
2015-04-07 05:12:21 -05:00
|
|
|
fn redirect_root(&mut self,
|
|
|
|
new_rank: u32,
|
|
|
|
old_root: VarValue<K>,
|
|
|
|
new_root: VarValue<K>,
|
|
|
|
new_value: K::Value) {
|
|
|
|
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));
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
2012-09-07 20:53:14 -05:00
|
|
|
}
|
2012-11-07 20:40:34 -06:00
|
|
|
|
2015-02-13 18:52:55 -06:00
|
|
|
impl<K:UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
|
2015-01-21 19:25:24 -06:00
|
|
|
type Value = VarValue<K>;
|
|
|
|
type Undo = ();
|
|
|
|
|
2015-04-07 05:12:21 -05:00
|
|
|
fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2015-04-08 18:31:20 -05:00
|
|
|
// Base union-find algorithm, where we are just making sets
|
2015-04-07 05:12:21 -05:00
|
|
|
|
|
|
|
impl<'tcx,K> UnificationTable<K>
|
|
|
|
where K : UnifyKey<Value=()>,
|
|
|
|
{
|
|
|
|
pub fn union(&mut self, a_id: K, b_id: 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 {
|
|
|
|
self.unify(node_a, node_b, ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn find(&mut self, id: K) -> K {
|
|
|
|
self.get(id).key()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unioned(&mut self, a_id: K, b_id: K) -> bool {
|
|
|
|
self.find(a_id) == self.find(b_id)
|
2014-07-22 06:40:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-20 05:35:06 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2015-02-15 14:16:45 -06:00
|
|
|
// Code to handle keys which carry a value, like ints,
|
|
|
|
// floats---anything that doesn't have a subtyping relationship we
|
|
|
|
// need to worry about.
|
2013-01-08 16:00:45 -06:00
|
|
|
|
2015-02-15 14:16:45 -06:00
|
|
|
impl<'tcx,K,V> UnificationTable<K>
|
2015-03-10 14:32:25 -05:00
|
|
|
where K: UnifyKey<Value=Option<V>>,
|
|
|
|
V: Clone+PartialEq,
|
2014-06-20 05:35:06 -05:00
|
|
|
{
|
2015-02-15 14:16:45 -06:00
|
|
|
pub fn unify_var_var(&mut self,
|
|
|
|
a_id: K,
|
|
|
|
b_id: K)
|
2015-03-10 14:32:25 -05:00
|
|
|
-> Result<(),(V,V)>
|
2014-06-20 05:35:06 -05:00
|
|
|
{
|
2015-02-15 14:16:45 -06:00
|
|
|
let node_a = self.get(a_id);
|
|
|
|
let node_b = self.get(b_id);
|
2015-04-07 05:12:21 -05:00
|
|
|
let a_id = node_a.key();
|
|
|
|
let b_id = node_b.key();
|
2012-11-07 20:40:34 -06:00
|
|
|
|
2015-03-09 15:39:50 -05:00
|
|
|
if a_id == b_id { return Ok(()); }
|
2012-11-07 20:40:34 -06:00
|
|
|
|
2014-06-20 05:35:06 -05:00
|
|
|
let combined = {
|
|
|
|
match (&node_a.value, &node_b.value) {
|
|
|
|
(&None, &None) => {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
(&Some(ref v), &None) | (&None, &Some(ref v)) => {
|
2015-03-10 14:32:25 -05:00
|
|
|
Some(v.clone())
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
|
|
|
(&Some(ref v1), &Some(ref v2)) => {
|
|
|
|
if *v1 != *v2 {
|
2015-03-10 14:32:25 -05:00
|
|
|
return Err((v1.clone(), v2.clone()));
|
2014-06-20 05:35:06 -05:00
|
|
|
}
|
2015-03-10 14:32:25 -05:00
|
|
|
Some(v1.clone())
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
2013-01-08 16:00:45 -06:00
|
|
|
}
|
|
|
|
};
|
2012-11-07 20:40:34 -06:00
|
|
|
|
2015-04-07 05:12:21 -05:00
|
|
|
Ok(self.unify(node_a, node_b, combined))
|
2012-11-07 20:40:34 -06:00
|
|
|
}
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
/// 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`.
|
2015-02-15 14:16:45 -06:00
|
|
|
pub fn unify_var_value(&mut self,
|
|
|
|
a_id: K,
|
|
|
|
b: V)
|
2015-03-10 14:32:25 -05:00
|
|
|
-> Result<(),(V,V)>
|
2014-06-20 05:35:06 -05:00
|
|
|
{
|
2015-04-07 05:12:21 -05:00
|
|
|
let mut node_a = self.get(a_id);
|
2013-01-08 16:00:45 -06:00
|
|
|
|
2014-06-20 05:35:06 -05:00
|
|
|
match node_a.value {
|
2013-01-22 09:02:40 -06:00
|
|
|
None => {
|
2015-04-07 05:12:21 -05:00
|
|
|
node_a.value = Some(b);
|
|
|
|
self.set(node_a.key(), node_a);
|
2015-02-15 14:16:45 -06:00
|
|
|
Ok(())
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
2012-11-07 20:40:34 -06:00
|
|
|
|
2013-01-22 09:02:40 -06:00
|
|
|
Some(ref a_t) => {
|
|
|
|
if *a_t == b {
|
2015-02-15 14:16:45 -06:00
|
|
|
Ok(())
|
2013-01-22 09:02:40 -06:00
|
|
|
} else {
|
2015-03-10 14:32:25 -05:00
|
|
|
Err((a_t.clone(), b))
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
|
|
|
}
|
2012-11-07 20:40:34 -06:00
|
|
|
}
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
2014-09-12 09:53:35 -05:00
|
|
|
|
2015-02-16 04:07:22 -06:00
|
|
|
pub fn has_value(&mut self, id: K) -> bool {
|
|
|
|
self.get(id).value.is_some()
|
|
|
|
}
|
|
|
|
|
2015-03-10 14:32:25 -05:00
|
|
|
pub fn probe(&mut self, a_id: K) -> Option<V> {
|
|
|
|
self.get(a_id).value.clone()
|
2014-09-12 09:53:35 -05:00
|
|
|
}
|
2013-01-22 09:02:40 -06:00
|
|
|
}
|
2013-01-08 16:00:45 -06:00
|
|
|
|