]> git.proxmox.com Git - rustc.git/blame - src/librustc_data_structures/unify/mod.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_data_structures / unify / mod.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
1a4d82fc 11use std::marker;
85aaf69f
SL
12use std::fmt::Debug;
13use std::marker::PhantomData;
d9579d0f
AL
14use snapshot_vec as sv;
15
16#[cfg(test)]
17mod tests;
1a4d82fc
JJ
18
19/// This trait is implemented by any type that can serve as a type
20/// variable. We call such variables *unification keys*. For example,
21/// this trait is implemented by `IntVid`, which represents integral
22/// variables.
23///
24/// Each key type has an associated value type `V`. For example, for
25/// `IntVid`, this is `Option<IntVarValue>`, representing some
26/// (possibly not yet known) sort of integer.
27///
d9579d0f
AL
28/// Clients are expected to provide implementations of this trait; you
29/// can see some examples in the `test` module.
30pub trait UnifyKey : Copy + Clone + Debug + PartialEq {
31 type Value: Clone + PartialEq + Debug;
85aaf69f 32
c34b1796 33 fn index(&self) -> u32;
1a4d82fc 34
c34b1796 35 fn from_index(u: u32) -> Self;
1a4d82fc
JJ
36
37 fn tag(k: Option<Self>) -> &'static str;
38}
39
9cc50fc6
SL
40/// This trait is implemented for unify values that can be
41/// combined. This relation should be a monoid.
42pub trait Combine {
43 fn combine(&self, other: &Self) -> Self;
44}
45
46impl Combine for () {
47 fn combine(&self, _other: &()) {}
48}
49
1a4d82fc
JJ
50/// Value of a unification key. We implement Tarjan's union-find
51/// algorithm: when two keys are unified, one of them is converted
52/// into a "redirect" pointing at the other. These redirects form a
53/// DAG: the roots of the DAG (nodes that are not redirected) are each
54/// associated with a value of type `V` and a rank. The rank is used
55/// to keep the DAG relatively balanced, which helps keep the running
56/// time of the algorithm under control. For more information, see
57/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
85aaf69f 58#[derive(PartialEq,Clone,Debug)]
54a0048b
SL
59pub struct VarValue<K: UnifyKey> {
60 parent: K, // if equal to self, this is a root
d9579d0f 61 value: K::Value, // value assigned (only relevant to root)
54a0048b 62 rank: u32, // max depth (only relevant to root)
1a4d82fc
JJ
63}
64
65/// Table of unification keys and their values.
54a0048b 66pub struct UnificationTable<K: UnifyKey> {
1a4d82fc 67 /// Indicates the current value of each key.
85aaf69f 68 values: sv::SnapshotVec<Delegate<K>>,
1a4d82fc
JJ
69}
70
71/// At any time, users may snapshot a unification table. The changes
72/// made during the snapshot may either be *committed* or *rolled back*.
54a0048b 73pub struct Snapshot<K: UnifyKey> {
1a4d82fc 74 // Link snapshot to the key type `K` of the table.
85aaf69f 75 marker: marker::PhantomData<K>,
1a4d82fc
JJ
76 snapshot: sv::Snapshot,
77}
78
c34b1796 79#[derive(Copy, Clone)]
d9579d0f
AL
80struct Delegate<K>(PhantomData<K>);
81
54a0048b 82impl<K: UnifyKey> VarValue<K> {
d9579d0f
AL
83 fn new_var(key: K, value: K::Value) -> VarValue<K> {
84 VarValue::new(key, value, 0)
85 }
86
87 fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> {
54a0048b
SL
88 VarValue {
89 parent: parent, // this is a root
90 value: value,
91 rank: rank,
92 }
d9579d0f
AL
93 }
94
95 fn redirect(self, to: K) -> VarValue<K> {
96 VarValue { parent: to, ..self }
97 }
98
99 fn root(self, rank: u32, value: K::Value) -> VarValue<K> {
54a0048b
SL
100 VarValue {
101 rank: rank,
102 value: value,
103 ..self
104 }
d9579d0f
AL
105 }
106
107 /// Returns the key of this node. Only valid if this is a root
108 /// node, which you yourself must ensure.
109 fn key(&self) -> K {
110 self.parent
111 }
112
113 fn parent(&self, self_key: K) -> Option<K> {
114 self.if_not_self(self.parent, self_key)
115 }
116
117 fn if_not_self(&self, key: K, self_key: K) -> Option<K> {
118 if key == self_key {
119 None
120 } else {
121 Some(key)
122 }
123 }
124}
1a4d82fc
JJ
125
126// We can't use V:LatticeValue, much as I would like to,
127// because frequently the pattern is that V=Option<U> for some
128// other type parameter U, and we have no way to say
129// Option<U>:LatticeValue.
130
54a0048b 131impl<K: UnifyKey> UnificationTable<K> {
85aaf69f 132 pub fn new() -> UnificationTable<K> {
54a0048b 133 UnificationTable { values: sv::SnapshotVec::new() }
1a4d82fc
JJ
134 }
135
136 /// Starts a new snapshot. Each snapshot must be either
137 /// rolled back or committed in a "LIFO" (stack) order.
138 pub fn snapshot(&mut self) -> Snapshot<K> {
54a0048b
SL
139 Snapshot {
140 marker: marker::PhantomData::<K>,
141 snapshot: self.values.start_snapshot(),
142 }
1a4d82fc
JJ
143 }
144
145 /// Reverses all changes since the last snapshot. Also
146 /// removes any keys that have been created since then.
147 pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
148 debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
149 self.values.rollback_to(snapshot.snapshot);
150 }
151
152 /// Commits all changes since the last snapshot. Of course, they
153 /// can still be undone if there is a snapshot further out.
154 pub fn commit(&mut self, snapshot: Snapshot<K>) {
155 debug!("{}: commit()", UnifyKey::tag(None::<K>));
156 self.values.commit(snapshot.snapshot);
157 }
158
85aaf69f 159 pub fn new_key(&mut self, value: K::Value) -> K {
d9579d0f
AL
160 let len = self.values.len();
161 let key: K = UnifyKey::from_index(len as u32);
162 self.values.push(VarValue::new_var(key, value));
54a0048b 163 debug!("{}: created new key: {:?}", UnifyKey::tag(None::<K>), key);
d9579d0f 164 key
1a4d82fc
JJ
165 }
166
c34b1796
AL
167 /// Find the root node for `vid`. This uses the standard
168 /// union-find algorithm with path compression:
169 /// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
170 ///
171 /// NB. This is a building-block operation and you would probably
172 /// prefer to call `probe` below.
d9579d0f 173 fn get(&mut self, vid: K) -> VarValue<K> {
c34b1796 174 let index = vid.index() as usize;
d9579d0f
AL
175 let mut value: VarValue<K> = self.values.get(index).clone();
176 match value.parent(vid) {
177 Some(redirect) => {
178 let root: VarValue<K> = self.get(redirect);
179 if root.key() != redirect {
1a4d82fc 180 // Path compression
d9579d0f
AL
181 value.parent = root.key();
182 self.values.set(index, value);
1a4d82fc 183 }
d9579d0f 184 root
1a4d82fc 185 }
54a0048b 186 None => value,
1a4d82fc
JJ
187 }
188 }
189
d9579d0f 190 fn is_root(&self, key: K) -> bool {
c34b1796 191 let index = key.index() as usize;
d9579d0f 192 self.values.get(index).parent(key).is_none()
1a4d82fc
JJ
193 }
194
c34b1796
AL
195 /// Sets the value for `vid` to `new_value`. `vid` MUST be a root
196 /// node! This is an internal operation used to impl other things.
197 fn set(&mut self, key: K, new_value: VarValue<K>) {
d9579d0f 198 assert!(self.is_root(key));
1a4d82fc 199
54a0048b 200 debug!("Updating variable {:?} to {:?}", key, new_value);
1a4d82fc 201
c34b1796
AL
202 let index = key.index() as usize;
203 self.values.set(index, new_value);
1a4d82fc
JJ
204 }
205
c34b1796
AL
206 /// Either redirects `node_a` to `node_b` or vice versa, depending
207 /// on the relative rank. The value associated with the new root
208 /// will be `new_value`.
209 ///
210 /// NB: This is the "union" operation of "union-find". It is
211 /// really more of a building block. If the values associated with
212 /// your key are non-trivial, you would probably prefer to call
213 /// `unify_var_var` below.
54a0048b 214 fn unify(&mut self, root_a: VarValue<K>, root_b: VarValue<K>, new_value: K::Value) -> K {
d9579d0f
AL
215 debug!("unify(root_a(id={:?}, rank={:?}), root_b(id={:?}, rank={:?}))",
216 root_a.key(),
217 root_a.rank,
218 root_b.key(),
219 root_b.rank);
220
221 if root_a.rank > root_b.rank {
1a4d82fc
JJ
222 // a has greater rank, so a should become b's parent,
223 // i.e., b should redirect to a.
54a0048b 224 self.redirect_root(root_a.rank, root_b, root_a, new_value)
d9579d0f 225 } else if root_a.rank < root_b.rank {
1a4d82fc 226 // b has greater rank, so a should redirect to b.
54a0048b 227 self.redirect_root(root_b.rank, root_a, root_b, new_value)
1a4d82fc
JJ
228 } else {
229 // If equal, redirect one to the other and increment the
230 // other's rank.
54a0048b 231 self.redirect_root(root_a.rank + 1, root_a, root_b, new_value)
d9579d0f
AL
232 }
233 }
c34b1796 234
d9579d0f
AL
235 fn redirect_root(&mut self,
236 new_rank: u32,
237 old_root: VarValue<K>,
238 new_root: VarValue<K>,
54a0048b 239 new_value: K::Value) -> K {
d9579d0f
AL
240 let old_root_key = old_root.key();
241 let new_root_key = new_root.key();
242 self.set(old_root_key, old_root.redirect(new_root_key));
243 self.set(new_root_key, new_root.root(new_rank, new_value));
54a0048b 244 new_root_key
1a4d82fc
JJ
245 }
246}
247
54a0048b 248impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
85aaf69f
SL
249 type Value = VarValue<K>;
250 type Undo = ();
251
d9579d0f
AL
252 fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
253}
254
54a0048b 255// # Base union-find algorithm, where we are just making sets
d9579d0f 256
54a0048b 257impl<'tcx, K: UnifyKey> UnificationTable<K>
9cc50fc6 258 where K::Value: Combine
d9579d0f 259{
54a0048b 260 pub fn union(&mut self, a_id: K, b_id: K) -> K {
d9579d0f
AL
261 let node_a = self.get(a_id);
262 let node_b = self.get(b_id);
263 let a_id = node_a.key();
264 let b_id = node_b.key();
265 if a_id != b_id {
9cc50fc6 266 let new_value = node_a.value.combine(&node_b.value);
54a0048b
SL
267 self.unify(node_a, node_b, new_value)
268 } else {
269 a_id
d9579d0f
AL
270 }
271 }
272
273 pub fn find(&mut self, id: K) -> K {
274 self.get(id).key()
275 }
276
9cc50fc6
SL
277 pub fn find_value(&mut self, id: K) -> K::Value {
278 self.get(id).value
279 }
280
d9579d0f
AL
281 pub fn unioned(&mut self, a_id: K, b_id: K) -> bool {
282 self.find(a_id) == self.find(b_id)
1a4d82fc
JJ
283 }
284}
285
54a0048b
SL
286// # Non-subtyping unification
287//
c34b1796
AL
288// Code to handle keys which carry a value, like ints,
289// floats---anything that doesn't have a subtyping relationship we
290// need to worry about.
291
54a0048b
SL
292impl<'tcx, K, V> UnificationTable<K>
293 where K: UnifyKey<Value = Option<V>>,
294 V: Clone + PartialEq + Debug
1a4d82fc 295{
54a0048b 296 pub fn unify_var_var(&mut self, a_id: K, b_id: K) -> Result<K, (V, V)> {
c34b1796
AL
297 let node_a = self.get(a_id);
298 let node_b = self.get(b_id);
d9579d0f
AL
299 let a_id = node_a.key();
300 let b_id = node_b.key();
1a4d82fc 301
54a0048b
SL
302 if a_id == b_id {
303 return Ok(a_id);
304 }
1a4d82fc
JJ
305
306 let combined = {
307 match (&node_a.value, &node_b.value) {
54a0048b
SL
308 (&None, &None) => None,
309 (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(v.clone()),
1a4d82fc
JJ
310 (&Some(ref v1), &Some(ref v2)) => {
311 if *v1 != *v2 {
c34b1796 312 return Err((v1.clone(), v2.clone()));
1a4d82fc 313 }
c34b1796 314 Some(v1.clone())
1a4d82fc
JJ
315 }
316 }
317 };
318
d9579d0f 319 Ok(self.unify(node_a, node_b, combined))
1a4d82fc
JJ
320 }
321
322 /// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping
323 /// relationships, if `a_id` already has a value, it must be the same as `b`.
54a0048b 324 pub fn unify_var_value(&mut self, a_id: K, b: V) -> Result<(), (V, V)> {
d9579d0f 325 let mut node_a = self.get(a_id);
1a4d82fc
JJ
326
327 match node_a.value {
328 None => {
d9579d0f
AL
329 node_a.value = Some(b);
330 self.set(node_a.key(), node_a);
c34b1796 331 Ok(())
1a4d82fc
JJ
332 }
333
334 Some(ref a_t) => {
335 if *a_t == b {
c34b1796 336 Ok(())
1a4d82fc 337 } else {
c34b1796 338 Err((a_t.clone(), b))
1a4d82fc
JJ
339 }
340 }
341 }
342 }
343
c34b1796
AL
344 pub fn has_value(&mut self, id: K) -> bool {
345 self.get(id).value.is_some()
346 }
347
348 pub fn probe(&mut self, a_id: K) -> Option<V> {
349 self.get(a_id).value.clone()
1a4d82fc 350 }
1a4d82fc 351
c1a9b12d
SL
352 pub fn unsolved_variables(&mut self) -> Vec<K> {
353 self.values
354 .iter()
54a0048b
SL
355 .filter_map(|vv| {
356 if vv.value.is_some() {
357 None
358 } else {
359 Some(vv.key())
360 }
361 })
c1a9b12d
SL
362 .collect()
363 }
364}