apply rustfmt to librustc_data_structures, correcting rust-lang-nursery/rustfmt#836

This commit is contained in:
Niko Matsakis 2016-03-05 08:40:33 -05:00
parent d31d8a9a91
commit 43dc48c7ff
16 changed files with 444 additions and 355 deletions

View File

@ -10,7 +10,7 @@
/// A very simple BitVector type. /// A very simple BitVector type.
pub struct BitVector { pub struct BitVector {
data: Vec<u64> data: Vec<u64>,
} }
impl BitVector { impl BitVector {
@ -40,7 +40,9 @@ impl BitVector {
for (i, j) in self.data.iter_mut().zip(&all.data) { for (i, j) in self.data.iter_mut().zip(&all.data) {
let value = *i; let value = *i;
*i = value | *j; *i = value | *j;
if value != *i { changed = true; } if value != *i {
changed = true;
}
} }
changed changed
} }
@ -56,7 +58,7 @@ impl BitVector {
BitVectorIter { BitVectorIter {
iter: self.data.iter(), iter: self.data.iter(),
current: 0, current: 0,
idx: 0 idx: 0,
} }
} }
} }
@ -64,7 +66,7 @@ impl BitVector {
pub struct BitVectorIter<'a> { pub struct BitVectorIter<'a> {
iter: ::std::slice::Iter<'a, u64>, iter: ::std::slice::Iter<'a, u64>,
current: u64, current: u64,
idx: usize idx: usize,
} }
impl<'a> Iterator for BitVectorIter<'a> { impl<'a> Iterator for BitVectorIter<'a> {
@ -108,7 +110,7 @@ impl BitMatrix {
let u64s_per_elem = u64s(elements); let u64s_per_elem = u64s(elements);
BitMatrix { BitMatrix {
elements: elements, elements: elements,
vector: vec![0; elements * u64s_per_elem] vector: vec![0; elements * u64s_per_elem],
} }
} }
@ -123,9 +125,9 @@ impl BitMatrix {
let (start, _) = self.range(source); let (start, _) = self.range(source);
let (word, mask) = word_mask(target); let (word, mask) = word_mask(target);
let mut vector = &mut self.vector[..]; let mut vector = &mut self.vector[..];
let v1 = vector[start+word]; let v1 = vector[start + word];
let v2 = v1 | mask; let v2 = v1 | mask;
vector[start+word] = v2; vector[start + word] = v2;
v1 != v2 v1 != v2
} }
@ -136,7 +138,7 @@ impl BitMatrix {
pub fn contains(&self, source: usize, target: usize) -> bool { pub fn contains(&self, source: usize, target: usize) -> bool {
let (start, _) = self.range(source); let (start, _) = self.range(source);
let (word, mask) = word_mask(target); let (word, mask) = word_mask(target);
(self.vector[start+word] & mask) != 0 (self.vector[start + word] & mask) != 0
} }
/// Returns those indices that are reachable from both `a` and /// Returns those indices that are reachable from both `a` and
@ -150,8 +152,12 @@ impl BitMatrix {
for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() { for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() {
let mut v = self.vector[i] & self.vector[j]; let mut v = self.vector[i] & self.vector[j];
for bit in 0..64 { for bit in 0..64 {
if v == 0 { break; } if v == 0 {
if v & 0x1 != 0 { result.push(base*64 + bit); } break;
}
if v & 0x1 != 0 {
result.push(base * 64 + bit);
}
v >>= 1; v >>= 1;
} }
} }
@ -170,9 +176,7 @@ impl BitMatrix {
let (write_start, write_end) = self.range(write); let (write_start, write_end) = self.range(write);
let vector = &mut self.vector[..]; let vector = &mut self.vector[..];
let mut changed = false; let mut changed = false;
for (read_index, write_index) in for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) {
(read_start..read_end).zip(write_start..write_end)
{
let v1 = vector[write_index]; let v1 = vector[write_index];
let v2 = v1 | vector[read_index]; let v2 = v1 | vector[read_index];
vector[write_index] = v2; vector[write_index] = v2;
@ -204,7 +208,8 @@ fn bitvec_iter_works() {
bitvec.insert(65); bitvec.insert(65);
bitvec.insert(66); bitvec.insert(66);
bitvec.insert(99); bitvec.insert(99);
assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 63, 64, 65, 66, 99]); assert_eq!(bitvec.iter().collect::<Vec<_>>(),
[1, 10, 19, 62, 63, 64, 65, 66, 99]);
} }
#[test] #[test]
@ -217,7 +222,8 @@ fn bitvec_iter_works_2() {
bitvec.insert(66); bitvec.insert(66);
bitvec.insert(99); bitvec.insert(99);
bitvec.insert(299); bitvec.insert(299);
assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 66, 99, 299]); assert_eq!(bitvec.iter().collect::<Vec<_>>(),
[1, 10, 19, 62, 66, 99, 299]);
} }

View File

@ -36,7 +36,9 @@ pub struct FnvHasher(u64);
impl Default for FnvHasher { impl Default for FnvHasher {
#[inline] #[inline]
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) } fn default() -> FnvHasher {
FnvHasher(0xcbf29ce484222325)
}
} }
impl Hasher for FnvHasher { impl Hasher for FnvHasher {
@ -51,5 +53,7 @@ impl Hasher for FnvHasher {
} }
#[inline] #[inline]
fn finish(&self) -> u64 { self.0 } fn finish(&self) -> u64 {
self.0
}
} }

View File

@ -38,9 +38,9 @@ use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub struct Graph<N,E> { pub struct Graph<N, E> {
nodes: SnapshotVec<Node<N>> , nodes: SnapshotVec<Node<N>>,
edges: SnapshotVec<Edge<E>> , edges: SnapshotVec<Edge<E>>,
} }
pub struct Node<N> { pub struct Node<N> {
@ -71,9 +71,13 @@ impl<N> SnapshotVecDelegate for Edge<N> {
impl<E: Debug> Debug for Edge<E> { impl<E: Debug> Debug for Edge<E> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}", write!(f,
self.next_edge[0], self.next_edge[1], self.source, "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
self.target, self.data) self.next_edge[0],
self.next_edge[1],
self.source,
self.target,
self.data)
} }
} }
@ -87,7 +91,9 @@ pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);
// Use a private field here to guarantee no more instances are created: // Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction { repr: usize } pub struct Direction {
repr: usize,
}
pub const OUTGOING: Direction = Direction { repr: 0 }; pub const OUTGOING: Direction = Direction { repr: 0 };
@ -95,16 +101,20 @@ pub const INCOMING: Direction = Direction { repr: 1 };
impl NodeIndex { impl NodeIndex {
/// Returns unique id (unique with respect to the graph holding associated node). /// Returns unique id (unique with respect to the graph holding associated node).
pub fn node_id(&self) -> usize { self.0 } pub fn node_id(&self) -> usize {
self.0
}
} }
impl EdgeIndex { impl EdgeIndex {
/// Returns unique id (unique with respect to the graph holding associated edge). /// Returns unique id (unique with respect to the graph holding associated edge).
pub fn edge_id(&self) -> usize { self.0 } pub fn edge_id(&self) -> usize {
self.0
}
} }
impl<N:Debug,E:Debug> Graph<N,E> { impl<N: Debug, E: Debug> Graph<N, E> {
pub fn new() -> Graph<N,E> { pub fn new() -> Graph<N, E> {
Graph { Graph {
nodes: SnapshotVec::new(), nodes: SnapshotVec::new(),
edges: SnapshotVec::new(), edges: SnapshotVec::new(),
@ -145,7 +155,7 @@ impl<N:Debug,E:Debug> Graph<N,E> {
let idx = self.next_node_index(); let idx = self.next_node_index();
self.nodes.push(Node { self.nodes.push(Node {
first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
data: data data: data,
}); });
idx idx
} }
@ -169,19 +179,14 @@ impl<N:Debug,E:Debug> Graph<N,E> {
EdgeIndex(self.edges.len()) EdgeIndex(self.edges.len())
} }
pub fn add_edge(&mut self, pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
source: NodeIndex,
target: NodeIndex,
data: E) -> EdgeIndex {
debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data); debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);
let idx = self.next_edge_index(); let idx = self.next_edge_index();
// read current first of the list of edges from each node // read current first of the list of edges from each node
let source_first = self.nodes[source.0] let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
.first_edge[OUTGOING.repr]; let target_first = self.nodes[target.0].first_edge[INCOMING.repr];
let target_first = self.nodes[target.0]
.first_edge[INCOMING.repr];
// create the new edge, with the previous firsts from each node // create the new edge, with the previous firsts from each node
// as the next pointers // as the next pointers
@ -189,7 +194,7 @@ impl<N:Debug,E:Debug> Graph<N,E> {
next_edge: [source_first, target_first], next_edge: [source_first, target_first],
source: source, source: source,
target: target, target: target,
data: data data: data,
}); });
// adjust the firsts for each node target be the next object. // adjust the firsts for each node target be the next object.
@ -230,38 +235,42 @@ impl<N:Debug,E:Debug> Graph<N,E> {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Iterating over nodes, edges // Iterating over nodes, edges
pub fn each_node<'a, F>(&'a self, mut f: F) -> bool where pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
F: FnMut(NodeIndex, &'a Node<N>) -> bool, where F: FnMut(NodeIndex, &'a Node<N>) -> bool
{ {
//! Iterates over all edges defined in the graph. //! Iterates over all edges defined in the graph.
self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node)) self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
} }
pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool where pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
F: FnMut(EdgeIndex, &'a Edge<E>) -> bool, where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
{ {
//! Iterates over all edges defined in the graph //! Iterates over all edges defined in the graph
self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge)) self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
} }
pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N,E> { pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
self.adjacent_edges(source, OUTGOING) self.adjacent_edges(source, OUTGOING)
} }
pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N,E> { pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
self.adjacent_edges(source, INCOMING) self.adjacent_edges(source, INCOMING)
} }
pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N,E> { pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
let first_edge = self.node(source).first_edge[direction.repr]; let first_edge = self.node(source).first_edge[direction.repr];
AdjacentEdges { graph: self, direction: direction, next: first_edge } AdjacentEdges {
graph: self,
direction: direction,
next: first_edge,
}
} }
pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N,E> { pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
self.outgoing_edges(source).targets() self.outgoing_edges(source).targets()
} }
pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N,E> { pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
self.incoming_edges(target).sources() self.incoming_edges(target).sources()
} }
@ -274,8 +283,8 @@ impl<N:Debug,E:Debug> Graph<N,E> {
// variables or other bitsets. This method facilitates such a // variables or other bitsets. This method facilitates such a
// computation. // computation.
pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F) where pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool, where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
{ {
let mut iteration = 0; let mut iteration = 0;
let mut changed = true; let mut changed = true;
@ -288,7 +297,7 @@ impl<N:Debug,E:Debug> Graph<N,E> {
} }
} }
pub fn depth_traverse<'a>(&'a self, start: NodeIndex) -> DepthFirstTraversal<'a, N, E> { pub fn depth_traverse<'a>(&'a self, start: NodeIndex) -> DepthFirstTraversal<'a, N, E> {
DepthFirstTraversal { DepthFirstTraversal {
graph: self, graph: self,
stack: vec![start], stack: vec![start],
@ -300,25 +309,26 @@ impl<N:Debug,E:Debug> Graph<N,E> {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Iterators // Iterators
pub struct AdjacentEdges<'g,N,E> pub struct AdjacentEdges<'g, N, E>
where N:'g, E:'g where N: 'g,
E: 'g
{ {
graph: &'g Graph<N, E>, graph: &'g Graph<N, E>,
direction: Direction, direction: Direction,
next: EdgeIndex, next: EdgeIndex,
} }
impl<'g,N,E> AdjacentEdges<'g,N,E> { impl<'g, N, E> AdjacentEdges<'g, N, E> {
fn targets(self) -> AdjacentTargets<'g,N,E> { fn targets(self) -> AdjacentTargets<'g, N, E> {
AdjacentTargets { edges: self } AdjacentTargets { edges: self }
} }
fn sources(self) -> AdjacentSources<'g,N,E> { fn sources(self) -> AdjacentSources<'g, N, E> {
AdjacentSources { edges: self } AdjacentSources { edges: self }
} }
} }
impl<'g, N:Debug, E:Debug> Iterator for AdjacentEdges<'g, N, E> { impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
type Item = (EdgeIndex, &'g Edge<E>); type Item = (EdgeIndex, &'g Edge<E>);
fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> { fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
@ -333,13 +343,14 @@ impl<'g, N:Debug, E:Debug> Iterator for AdjacentEdges<'g, N, E> {
} }
} }
pub struct AdjacentTargets<'g,N:'g,E:'g> pub struct AdjacentTargets<'g, N: 'g, E: 'g>
where N:'g, E:'g where N: 'g,
E: 'g
{ {
edges: AdjacentEdges<'g,N,E>, edges: AdjacentEdges<'g, N, E>,
} }
impl<'g, N:Debug, E:Debug> Iterator for AdjacentTargets<'g, N, E> { impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
type Item = NodeIndex; type Item = NodeIndex;
fn next(&mut self) -> Option<NodeIndex> { fn next(&mut self) -> Option<NodeIndex> {
@ -347,13 +358,14 @@ impl<'g, N:Debug, E:Debug> Iterator for AdjacentTargets<'g, N, E> {
} }
} }
pub struct AdjacentSources<'g,N:'g,E:'g> pub struct AdjacentSources<'g, N: 'g, E: 'g>
where N:'g, E:'g where N: 'g,
E: 'g
{ {
edges: AdjacentEdges<'g,N,E>, edges: AdjacentEdges<'g, N, E>,
} }
impl<'g, N:Debug, E:Debug> Iterator for AdjacentSources<'g, N, E> { impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
type Item = NodeIndex; type Item = NodeIndex;
fn next(&mut self) -> Option<NodeIndex> { fn next(&mut self) -> Option<NodeIndex> {
@ -361,13 +373,13 @@ impl<'g, N:Debug, E:Debug> Iterator for AdjacentSources<'g, N, E> {
} }
} }
pub struct DepthFirstTraversal<'g, N:'g, E:'g> { pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
graph: &'g Graph<N, E>, graph: &'g Graph<N, E>,
stack: Vec<NodeIndex>, stack: Vec<NodeIndex>,
visited: BitVector visited: BitVector,
} }
impl<'g, N:Debug, E:Debug> Iterator for DepthFirstTraversal<'g, N, E> { impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
type Item = NodeIndex; type Item = NodeIndex;
fn next(&mut self) -> Option<NodeIndex> { fn next(&mut self) -> Option<NodeIndex> {
@ -389,8 +401,8 @@ impl<'g, N:Debug, E:Debug> Iterator for DepthFirstTraversal<'g, N, E> {
} }
} }
pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F) where pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
F: FnMut(EdgeIndex) -> bool, where F: FnMut(EdgeIndex) -> bool
{ {
let mut i = 0; let mut i = 0;
let n = max_edge_index.0; let n = max_edge_index.0;

View File

@ -64,11 +64,11 @@ fn each_edge() {
}); });
} }
fn test_adjacent_edges<N:PartialEq+Debug,E:PartialEq+Debug>(graph: &Graph<N,E>, fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(graph: &Graph<N, E>,
start_index: NodeIndex, start_index: NodeIndex,
start_data: N, start_data: N,
expected_incoming: &[(E,N)], expected_incoming: &[(E, N)],
expected_outgoing: &[(E,N)]) { expected_outgoing: &[(E, N)]) {
assert!(graph.node_data(start_index) == &start_data); assert!(graph.node_data(start_index) == &start_data);
let mut counter = 0; let mut counter = 0;
@ -76,7 +76,10 @@ fn test_adjacent_edges<N:PartialEq+Debug,E:PartialEq+Debug>(graph: &Graph<N,E>,
assert!(graph.edge_data(edge_index) == &edge.data); assert!(graph.edge_data(edge_index) == &edge.data);
assert!(counter < expected_incoming.len()); assert!(counter < expected_incoming.len());
debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
counter, expected_incoming[counter], edge_index, edge); counter,
expected_incoming[counter],
edge_index,
edge);
match expected_incoming[counter] { match expected_incoming[counter] {
(ref e, ref n) => { (ref e, ref n) => {
assert!(e == &edge.data); assert!(e == &edge.data);
@ -93,7 +96,10 @@ fn test_adjacent_edges<N:PartialEq+Debug,E:PartialEq+Debug>(graph: &Graph<N,E>,
assert!(graph.edge_data(edge_index) == &edge.data); assert!(graph.edge_data(edge_index) == &edge.data);
assert!(counter < expected_outgoing.len()); assert!(counter < expected_outgoing.len());
debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
counter, expected_outgoing[counter], edge_index, edge); counter,
expected_outgoing[counter],
edge_index,
edge);
match expected_outgoing[counter] { match expected_outgoing[counter] {
(ref e, ref n) => { (ref e, ref n) => {
assert!(e == &edge.data); assert!(e == &edge.data);
@ -109,31 +115,27 @@ fn test_adjacent_edges<N:PartialEq+Debug,E:PartialEq+Debug>(graph: &Graph<N,E>,
#[test] #[test]
fn each_adjacent_from_a() { fn each_adjacent_from_a() {
let graph = create_graph(); let graph = create_graph();
test_adjacent_edges(&graph, NodeIndex(0), "A", test_adjacent_edges(&graph, NodeIndex(0), "A", &[], &[("AB", "B")]);
&[],
&[("AB", "B")]);
} }
#[test] #[test]
fn each_adjacent_from_b() { fn each_adjacent_from_b() {
let graph = create_graph(); let graph = create_graph();
test_adjacent_edges(&graph, NodeIndex(1), "B", test_adjacent_edges(&graph,
&[("FB", "F"), ("AB", "A"),], NodeIndex(1),
&[("BD", "D"), ("BC", "C"),]); "B",
&[("FB", "F"), ("AB", "A")],
&[("BD", "D"), ("BC", "C")]);
} }
#[test] #[test]
fn each_adjacent_from_c() { fn each_adjacent_from_c() {
let graph = create_graph(); let graph = create_graph();
test_adjacent_edges(&graph, NodeIndex(2), "C", test_adjacent_edges(&graph, NodeIndex(2), "C", &[("EC", "E"), ("BC", "B")], &[]);
&[("EC", "E"), ("BC", "B")],
&[]);
} }
#[test] #[test]
fn each_adjacent_from_d() { fn each_adjacent_from_d() {
let graph = create_graph(); let graph = create_graph();
test_adjacent_edges(&graph, NodeIndex(3), "D", test_adjacent_edges(&graph, NodeIndex(3), "D", &[("BD", "B")], &[("DE", "E")]);
&[("BD", "B")],
&[("DE", "E")]);
} }

View File

@ -26,14 +26,12 @@ use std::cell::Cell;
/// suffices for the current purposes. /// suffices for the current purposes.
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Ivar<T: Copy> { pub struct Ivar<T: Copy> {
data: Cell<Option<T>> data: Cell<Option<T>>,
} }
impl<T: Copy> Ivar<T> { impl<T: Copy> Ivar<T> {
pub fn new() -> Ivar<T> { pub fn new() -> Ivar<T> {
Ivar { Ivar { data: Cell::new(None) }
data: Cell::new(None)
}
} }
pub fn get(&self) -> Option<T> { pub fn get(&self) -> Option<T> {
@ -41,8 +39,7 @@ impl<T: Copy> Ivar<T> {
} }
pub fn fulfill(&self, value: T) { pub fn fulfill(&self, value: T) {
assert!(self.data.get().is_none(), assert!(self.data.get().is_none(), "Value already set!");
"Value already set!");
self.data.set(Some(value)); self.data.set(Some(value));
} }
@ -55,11 +52,11 @@ impl<T: Copy> Ivar<T> {
} }
} }
impl<T: Copy+fmt::Debug> fmt::Debug for Ivar<T> { impl<T: Copy + fmt::Debug> fmt::Debug for Ivar<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.get() { match self.get() {
Some(val) => write!(f, "Ivar({:?})", val), Some(val) => write!(f, "Ivar({:?})", val),
None => f.write_str("Ivar(<unfulfilled>)") None => f.write_str("Ivar(<unfulfilled>)"),
} }
} }
} }
@ -68,7 +65,7 @@ impl<T: Copy> Clone for Ivar<T> {
fn clone(&self) -> Ivar<T> { fn clone(&self) -> Ivar<T> {
match self.get() { match self.get() {
Some(val) => Ivar { data: Cell::new(Some(val)) }, Some(val) => Ivar { data: Cell::new(Some(val)) },
None => Ivar::new() None => Ivar::new(),
} }
} }
} }

View File

@ -32,7 +32,8 @@
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]
extern crate core; extern crate core;
#[macro_use] extern crate log; #[macro_use]
extern crate log;
extern crate serialize as rustc_serialize; // used by deriving extern crate serialize as rustc_serialize; // used by deriving
pub mod bitvec; pub mod bitvec;

View File

@ -28,7 +28,7 @@ use self::tree_index::TreeIndex;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
pub struct ObligationForest<O,T> { pub struct ObligationForest<O, T> {
/// The list of obligations. In between calls to /// The list of obligations. In between calls to
/// `process_obligations`, this list only contains nodes in the /// `process_obligations`, this list only contains nodes in the
/// `Pending` or `Success` state (with a non-zero number of /// `Pending` or `Success` state (with a non-zero number of
@ -43,7 +43,7 @@ pub struct ObligationForest<O,T> {
/// backtrace iterator (which uses `split_at`). /// backtrace iterator (which uses `split_at`).
nodes: Vec<Node<O>>, nodes: Vec<Node<O>>,
trees: Vec<Tree<T>>, trees: Vec<Tree<T>>,
snapshots: Vec<usize> snapshots: Vec<usize>,
} }
pub struct Snapshot { pub struct Snapshot {
@ -67,7 +67,9 @@ struct Node<O> {
#[derive(Debug)] #[derive(Debug)]
enum NodeState<O> { enum NodeState<O> {
/// Obligation not yet resolved to success or error. /// Obligation not yet resolved to success or error.
Pending { obligation: O }, Pending {
obligation: O,
},
/// Obligation resolved to success; `num_incomplete_children` /// Obligation resolved to success; `num_incomplete_children`
/// indicates the number of children still in an "incomplete" /// indicates the number of children still in an "incomplete"
@ -77,7 +79,10 @@ enum NodeState<O> {
/// ///
/// Once all children have completed, success nodes are removed /// Once all children have completed, success nodes are removed
/// from the vector by the compression step. /// from the vector by the compression step.
Success { obligation: O, num_incomplete_children: usize }, Success {
obligation: O,
num_incomplete_children: usize,
},
/// This obligation was resolved to an error. Error nodes are /// This obligation was resolved to an error. Error nodes are
/// removed from the vector by the compression step. /// removed from the vector by the compression step.
@ -85,13 +90,13 @@ enum NodeState<O> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Outcome<O,E> { pub struct Outcome<O, E> {
/// Obligations that were completely evaluated, including all /// Obligations that were completely evaluated, including all
/// (transitive) subobligations. /// (transitive) subobligations.
pub completed: Vec<O>, pub completed: Vec<O>,
/// Backtrace of obligations that were found to be in error. /// Backtrace of obligations that were found to be in error.
pub errors: Vec<Error<O,E>>, pub errors: Vec<Error<O, E>>,
/// If true, then we saw no successful obligations, which means /// If true, then we saw no successful obligations, which means
/// there is no point in further iteration. This is based on the /// there is no point in further iteration. This is based on the
@ -103,7 +108,7 @@ pub struct Outcome<O,E> {
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Error<O,E> { pub struct Error<O, E> {
pub error: E, pub error: E,
pub backtrace: Vec<O>, pub backtrace: Vec<O>,
} }
@ -113,7 +118,7 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
ObligationForest { ObligationForest {
trees: vec![], trees: vec![],
nodes: vec![], nodes: vec![],
snapshots: vec![] snapshots: vec![],
} }
} }
@ -148,11 +153,12 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
// snapshot but pushing trees, all nodes after that should be // snapshot but pushing trees, all nodes after that should be
// roots of other trees as well // roots of other trees as well
let first_root_index = self.trees[trees_len].root.get(); let first_root_index = self.trees[trees_len].root.get();
debug_assert!( debug_assert!(self.nodes[first_root_index..]
self.nodes[first_root_index..] .iter()
.iter() .zip(first_root_index..)
.zip(first_root_index..) .all(|(root, root_index)| {
.all(|(root, root_index)| self.trees[root.tree.get()].root.get() == root_index)); self.trees[root.tree.get()].root.get() == root_index
}));
// Pop off tree/root pairs pushed during snapshot. // Pop off tree/root pairs pushed during snapshot.
self.trees.truncate(trees_len); self.trees.truncate(trees_len);
@ -169,14 +175,17 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
pub fn push_tree(&mut self, obligation: O, tree_state: T) { pub fn push_tree(&mut self, obligation: O, tree_state: T) {
let index = NodeIndex::new(self.nodes.len()); let index = NodeIndex::new(self.nodes.len());
let tree = TreeIndex::new(self.trees.len()); let tree = TreeIndex::new(self.trees.len());
self.trees.push(Tree { root: index, state: tree_state }); self.trees.push(Tree {
root: index,
state: tree_state,
});
self.nodes.push(Node::new(tree, None, obligation)); self.nodes.push(Node::new(tree, None, obligation));
} }
/// Convert all remaining obligations to the given error. /// Convert all remaining obligations to the given error.
/// ///
/// This cannot be done during a snapshot. /// This cannot be done during a snapshot.
pub fn to_errors<E:Clone>(&mut self, error: E) -> Vec<Error<O,E>> { pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
assert!(!self.in_snapshot()); assert!(!self.in_snapshot());
let mut errors = vec![]; let mut errors = vec![];
for index in 0..self.nodes.len() { for index in 0..self.nodes.len() {
@ -184,7 +193,10 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
self.inherit_error(index); self.inherit_error(index);
if let NodeState::Pending { .. } = self.nodes[index].state { if let NodeState::Pending { .. } = self.nodes[index].state {
let backtrace = self.backtrace(index); let backtrace = self.backtrace(index);
errors.push(Error { error: error.clone(), backtrace: backtrace }); errors.push(Error {
error: error.clone(),
backtrace: backtrace,
});
} }
} }
let successful_obligations = self.compress(); let successful_obligations = self.compress();
@ -193,21 +205,27 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
} }
/// Returns the set of obligations that are in a pending state. /// Returns the set of obligations that are in a pending state.
pub fn pending_obligations(&self) -> Vec<O> where O: Clone { pub fn pending_obligations(&self) -> Vec<O>
self.nodes.iter() where O: Clone
.filter_map(|n| match n.state { {
NodeState::Pending { ref obligation } => Some(obligation), self.nodes
_ => None, .iter()
}) .filter_map(|n| {
.cloned() match n.state {
.collect() NodeState::Pending { ref obligation } => Some(obligation),
_ => None,
}
})
.cloned()
.collect()
} }
/// Process the obligations. /// Process the obligations.
/// ///
/// This CANNOT be unrolled (presently, at least). /// This CANNOT be unrolled (presently, at least).
pub fn process_obligations<E,F>(&mut self, mut action: F) -> Outcome<O,E> pub fn process_obligations<E, F>(&mut self, mut action: F) -> Outcome<O, E>
where E: Debug, F: FnMut(&mut O, &mut T, Backtrace<O>) -> Result<Option<Vec<O>>, E> where E: Debug,
F: FnMut(&mut O, &mut T, Backtrace<O>) -> Result<Option<Vec<O>>, E>
{ {
debug!("process_obligations(len={})", self.nodes.len()); debug!("process_obligations(len={})", self.nodes.len());
assert!(!self.in_snapshot()); // cannot unroll this action assert!(!self.in_snapshot()); // cannot unroll this action
@ -228,7 +246,8 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
self.inherit_error(index); self.inherit_error(index);
debug!("process_obligations: node {} == {:?}", debug!("process_obligations: node {} == {:?}",
index, self.nodes[index].state); index,
self.nodes[index].state);
let result = { let result = {
let Node { tree, parent, .. } = self.nodes[index]; let Node { tree, parent, .. } = self.nodes[index];
@ -236,14 +255,16 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
let backtrace = Backtrace::new(prefix, parent); let backtrace = Backtrace::new(prefix, parent);
match suffix[0].state { match suffix[0].state {
NodeState::Error | NodeState::Error |
NodeState::Success { .. } => NodeState::Success { .. } => continue,
continue, NodeState::Pending { ref mut obligation } => {
NodeState::Pending { ref mut obligation } => action(obligation, &mut self.trees[tree.get()].state, backtrace)
action(obligation, &mut self.trees[tree.get()].state, backtrace), }
} }
}; };
debug!("process_obligations: node {} got result {:?}", index, result); debug!("process_obligations: node {} got result {:?}",
index,
result);
match result { match result {
Ok(None) => { Ok(None) => {
@ -256,7 +277,10 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
} }
Err(err) => { Err(err) => {
let backtrace = self.backtrace(index); let backtrace = self.backtrace(index);
errors.push(Error { error: err, backtrace: backtrace }); errors.push(Error {
error: err,
backtrace: backtrace,
});
} }
} }
} }
@ -291,20 +315,21 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
// create child work // create child work
let tree_index = self.nodes[index].tree; let tree_index = self.nodes[index].tree;
let node_index = NodeIndex::new(index); let node_index = NodeIndex::new(index);
self.nodes.extend( self.nodes.extend(children.into_iter()
children.into_iter() .map(|o| Node::new(tree_index, Some(node_index), o)));
.map(|o| Node::new(tree_index, Some(node_index), o)));
} }
// change state from `Pending` to `Success`, temporarily swapping in `Error` // change state from `Pending` to `Success`, temporarily swapping in `Error`
let state = mem::replace(&mut self.nodes[index].state, NodeState::Error); let state = mem::replace(&mut self.nodes[index].state, NodeState::Error);
self.nodes[index].state = match state { self.nodes[index].state = match state {
NodeState::Pending { obligation } => NodeState::Pending { obligation } => {
NodeState::Success { obligation: obligation, NodeState::Success {
num_incomplete_children: num_incomplete_children }, obligation: obligation,
num_incomplete_children: num_incomplete_children,
}
}
NodeState::Success { .. } | NodeState::Success { .. } |
NodeState::Error => NodeState::Error => unreachable!(),
unreachable!()
}; };
} }
@ -358,14 +383,19 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
// there was an error in the ancestors, it should // there was an error in the ancestors, it should
// have been propagated down and we should never // have been propagated down and we should never
// have tried to process this obligation // have tried to process this obligation
panic!("encountered error in node {:?} when collecting stack trace", p); panic!("encountered error in node {:?} when collecting stack trace",
p);
} }
} }
// loop to the parent // loop to the parent
match self.nodes[p].parent { match self.nodes[p].parent {
Some(q) => { p = q.get(); } Some(q) => {
None => { return trace; } p = q.get();
}
None => {
return trace;
}
} }
} }
} }
@ -427,18 +457,19 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
// Pop off all the nodes we killed and extract the success // Pop off all the nodes we killed and extract the success
// stories. // stories.
let successful = let successful = (0..dead_nodes)
(0 .. dead_nodes) .map(|_| self.nodes.pop().unwrap())
.map(|_| self.nodes.pop().unwrap()) .flat_map(|node| {
.flat_map(|node| match node.state { match node.state {
NodeState::Error => None, NodeState::Error => None,
NodeState::Pending { .. } => unreachable!(), NodeState::Pending { .. } => unreachable!(),
NodeState::Success { obligation, num_incomplete_children } => { NodeState::Success { obligation, num_incomplete_children } => {
assert_eq!(num_incomplete_children, 0); assert_eq!(num_incomplete_children, 0);
Some(obligation) Some(obligation)
} }
}) }
.collect(); })
.collect();
// Adjust the various indices, since we compressed things. // Adjust the various indices, since we compressed things.
for tree in &mut self.trees { for tree in &mut self.trees {
@ -484,7 +515,10 @@ pub struct Backtrace<'b, O: 'b> {
impl<'b, O> Backtrace<'b, O> { impl<'b, O> Backtrace<'b, O> {
fn new(nodes: &'b [Node<O>], pointer: Option<NodeIndex>) -> Backtrace<'b, O> { fn new(nodes: &'b [Node<O>], pointer: Option<NodeIndex>) -> Backtrace<'b, O> {
Backtrace { nodes: nodes, pointer: pointer } Backtrace {
nodes: nodes,
pointer: pointer,
}
} }
} }
@ -497,9 +531,7 @@ impl<'b, O> Iterator for Backtrace<'b, O> {
self.pointer = self.nodes[p.get()].parent; self.pointer = self.nodes[p.get()].parent;
match self.nodes[p.get()].state { match self.nodes[p.get()].state {
NodeState::Pending { ref obligation } | NodeState::Pending { ref obligation } |
NodeState::Success { ref obligation, .. } => { NodeState::Success { ref obligation, .. } => Some(obligation),
Some(obligation)
}
NodeState::Error => { NodeState::Error => {
panic!("Backtrace encountered an error."); panic!("Backtrace encountered an error.");
} }

View File

@ -13,19 +13,16 @@ use std::u32;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct NodeIndex { pub struct NodeIndex {
index: NonZero<u32> index: NonZero<u32>,
} }
impl NodeIndex { impl NodeIndex {
pub fn new(value: usize) -> NodeIndex { pub fn new(value: usize) -> NodeIndex {
assert!(value < (u32::MAX as usize)); assert!(value < (u32::MAX as usize));
unsafe { unsafe { NodeIndex { index: NonZero::new((value as u32) + 1) } }
NodeIndex { index: NonZero::new((value as u32) + 1) }
}
} }
pub fn get(self) -> usize { pub fn get(self) -> usize {
(*self.index - 1) as usize (*self.index - 1) as usize
} }
} }

View File

@ -21,19 +21,23 @@ fn push_pop() {
// A |-> A.1 // A |-> A.1
// |-> A.2 // |-> A.2
// |-> A.3 // |-> A.3
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
forest.process_obligations(|obligation, tree, _| { tree,
assert_eq!(obligation.chars().next(), tree.chars().next()); _| {
match *obligation { assert_eq!(obligation.chars().next(), tree.chars().next());
"A" => Ok(Some(vec!["A.1", "A.2", "A.3"])), match *obligation {
"B" => Err("B is for broken"), "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
"C" => Ok(Some(vec![])), "B" => Err("B is for broken"),
_ => unreachable!(), "C" => Ok(Some(vec![])),
} _ => unreachable!(),
}); }
});
assert_eq!(ok, vec!["C"]); assert_eq!(ok, vec!["C"]);
assert_eq!(err, vec![Error {error: "B is for broken", assert_eq!(err,
backtrace: vec!["B"]}]); vec![Error {
error: "B is for broken",
backtrace: vec!["B"],
}]);
// second round: two delays, one success, creating an uneven set of subtasks: // second round: two delays, one success, creating an uneven set of subtasks:
// A |-> A.1 // A |-> A.1
@ -61,33 +65,41 @@ fn push_pop() {
// propagates to A.3.i, but not D.1 or D.2. // propagates to A.3.i, but not D.1 or D.2.
// D |-> D.1 |-> D.1.i // D |-> D.1 |-> D.1.i
// |-> D.2 |-> D.2.i // |-> D.2 |-> D.2.i
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
forest.process_obligations(|obligation, tree, _| { tree,
assert_eq!(obligation.chars().next(), tree.chars().next()); _| {
match *obligation { assert_eq!(obligation.chars().next(), tree.chars().next());
"A.1" => Ok(Some(vec![])), match *obligation {
"A.2" => Err("A is for apple"), "A.1" => Ok(Some(vec![])),
"D.1" => Ok(Some(vec!["D.1.i"])), "A.2" => Err("A is for apple"),
"D.2" => Ok(Some(vec!["D.2.i"])), "D.1" => Ok(Some(vec!["D.1.i"])),
_ => unreachable!(), "D.2" => Ok(Some(vec!["D.2.i"])),
} _ => unreachable!(),
}); }
});
assert_eq!(ok, vec!["A.1"]); assert_eq!(ok, vec!["A.1"]);
assert_eq!(err, vec![Error { error: "A is for apple", assert_eq!(err,
backtrace: vec!["A.2", "A"] }]); vec![Error {
error: "A is for apple",
backtrace: vec!["A.2", "A"],
}]);
// fourth round: error in D.1.i that should propagate to D.2.i // fourth round: error in D.1.i that should propagate to D.2.i
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
forest.process_obligations(|obligation, tree, _| { tree,
assert_eq!(obligation.chars().next(), tree.chars().next()); _| {
match *obligation { assert_eq!(obligation.chars().next(), tree.chars().next());
"D.1.i" => Err("D is for dumb"), match *obligation {
_ => panic!("unexpected obligation {:?}", obligation), "D.1.i" => Err("D is for dumb"),
} _ => panic!("unexpected obligation {:?}", obligation),
}); }
});
assert_eq!(ok, Vec::<&'static str>::new()); assert_eq!(ok, Vec::<&'static str>::new());
assert_eq!(err, vec![Error { error: "D is for dumb", assert_eq!(err,
backtrace: vec!["D.1.i", "D.1", "D"] }]); vec![Error {
error: "D is for dumb",
backtrace: vec!["D.1.i", "D.1", "D"],
}]);
} }
// Test that if a tree with grandchildren succeeds, everything is // Test that if a tree with grandchildren succeeds, everything is
@ -104,7 +116,7 @@ fn success_in_grandchildren() {
forest.push_tree("A", "A"); forest.push_tree("A", "A");
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, _| { forest.process_obligations::<(), _>(|obligation, tree, _| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
match *obligation { match *obligation {
"A" => Ok(Some(vec!["A.1", "A.2", "A.3"])), "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
@ -115,7 +127,7 @@ fn success_in_grandchildren() {
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, _| { forest.process_obligations::<(), _>(|obligation, tree, _| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
match *obligation { match *obligation {
"A.1" => Ok(Some(vec![])), "A.1" => Ok(Some(vec![])),
@ -128,7 +140,7 @@ fn success_in_grandchildren() {
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, _| { forest.process_obligations::<(), _>(|obligation, tree, _| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
match *obligation { match *obligation {
"A.2.i" => Ok(Some(vec!["A.2.i.a"])), "A.2.i" => Ok(Some(vec!["A.2.i.a"])),
@ -140,7 +152,7 @@ fn success_in_grandchildren() {
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, _| { forest.process_obligations::<(), _>(|obligation, tree, _| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
match *obligation { match *obligation {
"A.2.i.a" => Ok(Some(vec![])), "A.2.i.a" => Ok(Some(vec![])),
@ -150,8 +162,11 @@ fn success_in_grandchildren() {
assert_eq!(ok, vec!["A.2.i.a", "A.2.i", "A.2", "A"]); assert_eq!(ok, vec!["A.2.i.a", "A.2.i", "A.2", "A"]);
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } = forest.process_obligations::<(), _>(|_,
forest.process_obligations::<(),_>(|_, _, _| unreachable!()); _,
_| {
unreachable!()
});
assert!(ok.is_empty()); assert!(ok.is_empty());
assert!(err.is_empty()); assert!(err.is_empty());
} }
@ -163,7 +178,7 @@ fn to_errors_no_throw() {
let mut forest = ObligationForest::new(); let mut forest = ObligationForest::new();
forest.push_tree("A", "A"); forest.push_tree("A", "A");
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, _| { forest.process_obligations::<(), _>(|obligation, tree, _| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
match *obligation { match *obligation {
"A" => Ok(Some(vec!["A.1", "A.2", "A.3"])), "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
@ -183,7 +198,7 @@ fn backtrace() {
let mut forest = ObligationForest::new(); let mut forest = ObligationForest::new();
forest.push_tree("A", "A"); forest.push_tree("A", "A");
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, mut backtrace| { forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
assert!(backtrace.next().is_none()); assert!(backtrace.next().is_none());
match *obligation { match *obligation {
@ -194,7 +209,7 @@ fn backtrace() {
assert!(ok.is_empty()); assert!(ok.is_empty());
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, mut backtrace| { forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
assert!(backtrace.next().unwrap() == &"A"); assert!(backtrace.next().unwrap() == &"A");
assert!(backtrace.next().is_none()); assert!(backtrace.next().is_none());
@ -206,7 +221,7 @@ fn backtrace() {
assert!(ok.is_empty()); assert!(ok.is_empty());
assert!(err.is_empty()); assert!(err.is_empty());
let Outcome { completed: ok, errors: err, .. } = let Outcome { completed: ok, errors: err, .. } =
forest.process_obligations::<(),_>(|obligation, tree, mut backtrace| { forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
assert_eq!(obligation.chars().next(), tree.chars().next()); assert_eq!(obligation.chars().next(), tree.chars().next());
assert!(backtrace.next().unwrap() == &"A.1"); assert!(backtrace.next().unwrap() == &"A.1");
assert!(backtrace.next().unwrap() == &"A"); assert!(backtrace.next().unwrap() == &"A");

View File

@ -12,7 +12,7 @@ use std::u32;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct TreeIndex { pub struct TreeIndex {
index: u32 index: u32,
} }
impl TreeIndex { impl TreeIndex {
@ -25,4 +25,3 @@ impl TreeIndex {
self.index as usize self.index as usize
} }
} }

View File

@ -23,7 +23,7 @@ use self::UndoLog::*;
use std::mem; use std::mem;
use std::ops; use std::ops;
pub enum UndoLog<D:SnapshotVecDelegate> { pub enum UndoLog<D: SnapshotVecDelegate> {
/// Indicates where a snapshot started. /// Indicates where a snapshot started.
OpenSnapshot, OpenSnapshot,
@ -37,10 +37,10 @@ pub enum UndoLog<D:SnapshotVecDelegate> {
SetElem(usize, D::Value), SetElem(usize, D::Value),
/// Extensible set of actions /// Extensible set of actions
Other(D::Undo) Other(D::Undo),
} }
pub struct SnapshotVec<D:SnapshotVecDelegate> { pub struct SnapshotVec<D: SnapshotVecDelegate> {
values: Vec<D::Value>, values: Vec<D::Value>,
undo_log: Vec<UndoLog<D>>, undo_log: Vec<UndoLog<D>>,
} }
@ -58,7 +58,7 @@ pub trait SnapshotVecDelegate {
fn reverse(values: &mut Vec<Self::Value>, action: Self::Undo); fn reverse(values: &mut Vec<Self::Value>, action: Self::Undo);
} }
impl<D:SnapshotVecDelegate> SnapshotVec<D> { impl<D: SnapshotVecDelegate> SnapshotVec<D> {
pub fn new() -> SnapshotVec<D> { pub fn new() -> SnapshotVec<D> {
SnapshotVec { SnapshotVec {
values: Vec::new(), values: Vec::new(),
@ -117,9 +117,7 @@ impl<D:SnapshotVecDelegate> SnapshotVec<D> {
Snapshot { length: length } Snapshot { length: length }
} }
pub fn actions_since_snapshot(&self, pub fn actions_since_snapshot(&self, snapshot: &Snapshot) -> &[UndoLog<D>] {
snapshot: &Snapshot)
-> &[UndoLog<D>] {
&self.undo_log[snapshot.length..] &self.undo_log[snapshot.length..]
} }
@ -128,11 +126,10 @@ impl<D:SnapshotVecDelegate> SnapshotVec<D> {
assert!(self.undo_log.len() > snapshot.length); assert!(self.undo_log.len() > snapshot.length);
// Invariant established by start_snapshot(): // Invariant established by start_snapshot():
assert!( assert!(match self.undo_log[snapshot.length] {
match self.undo_log[snapshot.length] { OpenSnapshot => true,
OpenSnapshot => true, _ => false,
_ => false });
});
} }
pub fn rollback_to(&mut self, snapshot: Snapshot) { pub fn rollback_to(&mut self, snapshot: Snapshot) {
@ -168,7 +165,10 @@ impl<D:SnapshotVecDelegate> SnapshotVec<D> {
} }
let v = self.undo_log.pop().unwrap(); let v = self.undo_log.pop().unwrap();
assert!(match v { OpenSnapshot => true, _ => false }); assert!(match v {
OpenSnapshot => true,
_ => false,
});
assert!(self.undo_log.len() == snapshot.length); assert!(self.undo_log.len() == snapshot.length);
} }
@ -188,20 +188,28 @@ impl<D:SnapshotVecDelegate> SnapshotVec<D> {
} }
} }
impl<D:SnapshotVecDelegate> ops::Deref for SnapshotVec<D> { impl<D: SnapshotVecDelegate> ops::Deref for SnapshotVec<D> {
type Target = [D::Value]; type Target = [D::Value];
fn deref(&self) -> &[D::Value] { &*self.values } fn deref(&self) -> &[D::Value] {
&*self.values
}
} }
impl<D:SnapshotVecDelegate> ops::DerefMut for SnapshotVec<D> { impl<D: SnapshotVecDelegate> ops::DerefMut for SnapshotVec<D> {
fn deref_mut(&mut self) -> &mut [D::Value] { &mut *self.values } fn deref_mut(&mut self) -> &mut [D::Value] {
&mut *self.values
}
} }
impl<D:SnapshotVecDelegate> ops::Index<usize> for SnapshotVec<D> { impl<D: SnapshotVecDelegate> ops::Index<usize> for SnapshotVec<D> {
type Output = D::Value; type Output = D::Value;
fn index(&self, index: usize) -> &D::Value { self.get(index) } fn index(&self, index: usize) -> &D::Value {
self.get(index)
}
} }
impl<D:SnapshotVecDelegate> ops::IndexMut<usize> for SnapshotVec<D> { impl<D: SnapshotVecDelegate> ops::IndexMut<usize> for SnapshotVec<D> {
fn index_mut(&mut self, index: usize) -> &mut D::Value { self.get_mut(index) } fn index_mut(&mut self, index: usize) -> &mut D::Value {
self.get_mut(index)
}
} }

View File

@ -14,7 +14,7 @@ use std::fmt::Debug;
use std::mem; use std::mem;
#[derive(Clone)] #[derive(Clone)]
pub struct TransitiveRelation<T:Debug+PartialEq> { pub struct TransitiveRelation<T: Debug + PartialEq> {
// List of elements. This is used to map from a T to a usize. We // List of elements. This is used to map from a T to a usize. We
// expect domain to be small so just use a linear list versus a // expect domain to be small so just use a linear list versus a
// hashmap or something. // hashmap or something.
@ -33,7 +33,7 @@ pub struct TransitiveRelation<T:Debug+PartialEq> {
// are added with new elements. Perhaps better would be to ask the // are added with new elements. Perhaps better would be to ask the
// user for a batch of edges to minimize this effect, but I // user for a batch of edges to minimize this effect, but I
// already wrote the code this way. :P -nmatsakis // already wrote the code this way. :P -nmatsakis
closure: RefCell<Option<BitMatrix>> closure: RefCell<Option<BitMatrix>>,
} }
#[derive(Clone, PartialEq, PartialOrd)] #[derive(Clone, PartialEq, PartialOrd)]
@ -45,11 +45,13 @@ struct Edge {
target: Index, target: Index,
} }
impl<T:Debug+PartialEq> TransitiveRelation<T> { impl<T: Debug + PartialEq> TransitiveRelation<T> {
pub fn new() -> TransitiveRelation<T> { pub fn new() -> TransitiveRelation<T> {
TransitiveRelation { elements: vec![], TransitiveRelation {
edges: vec![], elements: vec![],
closure: RefCell::new(None) } edges: vec![],
closure: RefCell::new(None),
}
} }
fn index(&self, a: &T) -> Option<Index> { fn index(&self, a: &T) -> Option<Index> {
@ -74,7 +76,10 @@ impl<T:Debug+PartialEq> TransitiveRelation<T> {
pub fn add(&mut self, a: T, b: T) { pub fn add(&mut self, a: T, b: T) {
let a = self.add_index(a); let a = self.add_index(a);
let b = self.add_index(b); let b = self.add_index(b);
let edge = Edge { source: a, target: b }; let edge = Edge {
source: a,
target: b,
};
if !self.edges.contains(&edge) { if !self.edges.contains(&edge) {
self.edges.push(edge); self.edges.push(edge);
@ -86,10 +91,8 @@ impl<T:Debug+PartialEq> TransitiveRelation<T> {
/// Check whether `a < target` (transitively) /// Check whether `a < target` (transitively)
pub fn contains(&self, a: &T, b: &T) -> bool { pub fn contains(&self, a: &T, b: &T) -> bool {
match (self.index(a), self.index(b)) { match (self.index(a), self.index(b)) {
(Some(a), Some(b)) => (Some(a), Some(b)) => self.with_closure(|closure| closure.contains(a.0, b.0)),
self.with_closure(|closure| closure.contains(a.0, b.0)), (None, _) | (_, None) => false,
(None, _) | (_, None) =>
false,
} }
} }
@ -156,7 +159,9 @@ impl<T:Debug+PartialEq> TransitiveRelation<T> {
pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> { pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> {
let (mut a, mut b) = match (self.index(a), self.index(b)) { let (mut a, mut b) = match (self.index(a), self.index(b)) {
(Some(a), Some(b)) => (a, b), (Some(a), Some(b)) => (a, b),
(None, _) | (_, None) => { return vec![]; } (None, _) | (_, None) => {
return vec![];
}
}; };
// in some cases, there are some arbitrary choices to be made; // in some cases, there are some arbitrary choices to be made;
@ -233,7 +238,7 @@ impl<T:Debug+PartialEq> TransitiveRelation<T> {
.collect() .collect()
} }
fn with_closure<OP,R>(&self, op: OP) -> R fn with_closure<OP, R>(&self, op: OP) -> R
where OP: FnOnce(&BitMatrix) -> R where OP: FnOnce(&BitMatrix) -> R
{ {
let mut closure_cell = self.closure.borrow_mut(); let mut closure_cell = self.closure.borrow_mut();
@ -431,14 +436,15 @@ fn pdub_crisscross() {
// b -> b1 ---+ // b -> b1 ---+
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "a1"); relation.add("a", "a1");
relation.add("a", "b1"); relation.add("a", "b1");
relation.add("b", "a1"); relation.add("b", "a1");
relation.add("b", "b1"); relation.add("b", "b1");
relation.add("a1", "x"); relation.add("a1", "x");
relation.add("b1", "x"); relation.add("b1", "x");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"a1", &"b1"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"),
vec![&"a1", &"b1"]);
assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x")); assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x"));
} }
@ -451,23 +457,25 @@ fn pdub_crisscross_more() {
// b -> b1 -> b2 ---------+ // b -> b1 -> b2 ---------+
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "a1"); relation.add("a", "a1");
relation.add("a", "b1"); relation.add("a", "b1");
relation.add("b", "a1"); relation.add("b", "a1");
relation.add("b", "b1"); relation.add("b", "b1");
relation.add("a1", "a2"); relation.add("a1", "a2");
relation.add("a1", "b2"); relation.add("a1", "b2");
relation.add("b1", "a2"); relation.add("b1", "a2");
relation.add("b1", "b2"); relation.add("b1", "b2");
relation.add("a2", "a3"); relation.add("a2", "a3");
relation.add("a3", "x"); relation.add("a3", "x");
relation.add("b2", "x"); relation.add("b2", "x");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"a1", &"b1"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"),
assert_eq!(relation.minimal_upper_bounds(&"a1", &"b1"), vec![&"a2", &"b2"]); vec![&"a1", &"b1"]);
assert_eq!(relation.minimal_upper_bounds(&"a1", &"b1"),
vec![&"a2", &"b2"]);
assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x")); assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x"));
} }
@ -479,8 +487,8 @@ fn pdub_lub() {
// b -> b1 ---+ // b -> b1 ---+
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "a1"); relation.add("a", "a1");
relation.add("b", "b1"); relation.add("b", "b1");
relation.add("a1", "x"); relation.add("a1", "x");
relation.add("b1", "x"); relation.add("b1", "x");
@ -497,9 +505,9 @@ fn mubs_intermediate_node_on_one_side_only() {
// "digraph { a -> c -> d; b -> d; }", // "digraph { a -> c -> d; b -> d; }",
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "c"); relation.add("a", "c");
relation.add("c", "d"); relation.add("c", "d");
relation.add("b", "d"); relation.add("b", "d");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"d"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"d"]);
} }
@ -516,11 +524,11 @@ fn mubs_scc_1() {
// "digraph { a -> c -> d; d -> c; a -> d; b -> d; }", // "digraph { a -> c -> d; d -> c; a -> d; b -> d; }",
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "c"); relation.add("a", "c");
relation.add("c", "d"); relation.add("c", "d");
relation.add("d", "c"); relation.add("d", "c");
relation.add("a", "d"); relation.add("a", "d");
relation.add("b", "d"); relation.add("b", "d");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]);
} }
@ -536,11 +544,11 @@ fn mubs_scc_2() {
// "digraph { a -> c -> d; d -> c; b -> d; b -> c; }", // "digraph { a -> c -> d; d -> c; b -> d; b -> c; }",
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "c"); relation.add("a", "c");
relation.add("c", "d"); relation.add("c", "d");
relation.add("d", "c"); relation.add("d", "c");
relation.add("b", "d"); relation.add("b", "d");
relation.add("b", "c"); relation.add("b", "c");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]);
} }
@ -556,12 +564,12 @@ fn mubs_scc_3() {
// "digraph { a -> c -> d -> e -> c; b -> d; b -> e; }", // "digraph { a -> c -> d -> e -> c; b -> d; b -> e; }",
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "c"); relation.add("a", "c");
relation.add("c", "d"); relation.add("c", "d");
relation.add("d", "e"); relation.add("d", "e");
relation.add("e", "c"); relation.add("e", "c");
relation.add("b", "d"); relation.add("b", "d");
relation.add("b", "e"); relation.add("b", "e");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]);
} }
@ -578,12 +586,12 @@ fn mubs_scc_4() {
// "digraph { a -> c -> d -> e -> c; a -> d; b -> e; }" // "digraph { a -> c -> d -> e -> c; a -> d; b -> e; }"
let mut relation = TransitiveRelation::new(); let mut relation = TransitiveRelation::new();
relation.add("a", "c"); relation.add("a", "c");
relation.add("c", "d"); relation.add("c", "d");
relation.add("d", "e"); relation.add("d", "e");
relation.add("e", "c"); relation.add("e", "c");
relation.add("a", "d"); relation.add("a", "d");
relation.add("b", "e"); relation.add("b", "e");
assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]);
} }

View File

@ -36,13 +36,13 @@ macro_rules! impl_tuple_slice {
} }
} }
impl_tuple_slice!((T,T), 2); impl_tuple_slice!((T, T), 2);
impl_tuple_slice!((T,T,T), 3); impl_tuple_slice!((T, T, T), 3);
impl_tuple_slice!((T,T,T,T), 4); impl_tuple_slice!((T, T, T, T), 4);
impl_tuple_slice!((T,T,T,T,T), 5); impl_tuple_slice!((T, T, T, T, T), 5);
impl_tuple_slice!((T,T,T,T,T,T), 6); impl_tuple_slice!((T, T, T, T, T, T), 6);
impl_tuple_slice!((T,T,T,T,T,T,T), 7); impl_tuple_slice!((T, T, T, T, T, T, T), 7);
impl_tuple_slice!((T,T,T,T,T,T,T,T), 8); impl_tuple_slice!((T, T, T, T, T, T, T, T), 8);
#[test] #[test]
fn test_sliced_tuples() { fn test_sliced_tuples() {

View File

@ -56,21 +56,21 @@ impl Combine for () {
/// time of the algorithm under control. For more information, see /// time of the algorithm under control. For more information, see
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>. /// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
#[derive(PartialEq,Clone,Debug)] #[derive(PartialEq,Clone,Debug)]
pub struct VarValue<K:UnifyKey> { pub struct VarValue<K: UnifyKey> {
parent: K, // if equal to self, this is a root parent: K, // if equal to self, this is a root
value: K::Value, // value assigned (only relevant to root) value: K::Value, // value assigned (only relevant to root)
rank: u32, // max depth (only relevant to root) rank: u32, // max depth (only relevant to root)
} }
/// Table of unification keys and their values. /// Table of unification keys and their values.
pub struct UnificationTable<K:UnifyKey> { pub struct UnificationTable<K: UnifyKey> {
/// Indicates the current value of each key. /// Indicates the current value of each key.
values: sv::SnapshotVec<Delegate<K>>, values: sv::SnapshotVec<Delegate<K>>,
} }
/// At any time, users may snapshot a unification table. The changes /// At any time, users may snapshot a unification table. The changes
/// made during the snapshot may either be *committed* or *rolled back*. /// made during the snapshot may either be *committed* or *rolled back*.
pub struct Snapshot<K:UnifyKey> { pub struct Snapshot<K: UnifyKey> {
// Link snapshot to the key type `K` of the table. // Link snapshot to the key type `K` of the table.
marker: marker::PhantomData<K>, marker: marker::PhantomData<K>,
snapshot: sv::Snapshot, snapshot: sv::Snapshot,
@ -79,15 +79,17 @@ pub struct Snapshot<K:UnifyKey> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Delegate<K>(PhantomData<K>); struct Delegate<K>(PhantomData<K>);
impl<K:UnifyKey> VarValue<K> { impl<K: UnifyKey> VarValue<K> {
fn new_var(key: K, value: K::Value) -> VarValue<K> { fn new_var(key: K, value: K::Value) -> VarValue<K> {
VarValue::new(key, value, 0) VarValue::new(key, value, 0)
} }
fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> { fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> {
VarValue { parent: parent, // this is a root VarValue {
value: value, parent: parent, // this is a root
rank: rank } value: value,
rank: rank,
}
} }
fn redirect(self, to: K) -> VarValue<K> { fn redirect(self, to: K) -> VarValue<K> {
@ -95,7 +97,11 @@ impl<K:UnifyKey> VarValue<K> {
} }
fn root(self, rank: u32, value: K::Value) -> VarValue<K> { fn root(self, rank: u32, value: K::Value) -> VarValue<K> {
VarValue { rank: rank, value: value, ..self } VarValue {
rank: rank,
value: value,
..self
}
} }
/// Returns the key of this node. Only valid if this is a root /// Returns the key of this node. Only valid if this is a root
@ -122,18 +128,18 @@ impl<K:UnifyKey> VarValue<K> {
// other type parameter U, and we have no way to say // other type parameter U, and we have no way to say
// Option<U>:LatticeValue. // Option<U>:LatticeValue.
impl<K:UnifyKey> UnificationTable<K> { impl<K: UnifyKey> UnificationTable<K> {
pub fn new() -> UnificationTable<K> { pub fn new() -> UnificationTable<K> {
UnificationTable { UnificationTable { values: sv::SnapshotVec::new() }
values: sv::SnapshotVec::new()
}
} }
/// Starts a new snapshot. Each snapshot must be either /// Starts a new snapshot. Each snapshot must be either
/// rolled back or committed in a "LIFO" (stack) order. /// rolled back or committed in a "LIFO" (stack) order.
pub fn snapshot(&mut self) -> Snapshot<K> { pub fn snapshot(&mut self) -> Snapshot<K> {
Snapshot { marker: marker::PhantomData::<K>, Snapshot {
snapshot: self.values.start_snapshot() } marker: marker::PhantomData::<K>,
snapshot: self.values.start_snapshot(),
}
} }
/// Reverses all changes since the last snapshot. Also /// Reverses all changes since the last snapshot. Also
@ -154,9 +160,7 @@ impl<K:UnifyKey> UnificationTable<K> {
let len = self.values.len(); let len = self.values.len();
let key: K = UnifyKey::from_index(len as u32); let key: K = UnifyKey::from_index(len as u32);
self.values.push(VarValue::new_var(key, value)); self.values.push(VarValue::new_var(key, value));
debug!("{}: created new key: {:?}", debug!("{}: created new key: {:?}", UnifyKey::tag(None::<K>), key);
UnifyKey::tag(None::<K>),
key);
key key
} }
@ -179,9 +183,7 @@ impl<K:UnifyKey> UnificationTable<K> {
} }
root root
} }
None => { None => value,
value
}
} }
} }
@ -195,8 +197,7 @@ impl<K:UnifyKey> UnificationTable<K> {
fn set(&mut self, key: K, new_value: VarValue<K>) { fn set(&mut self, key: K, new_value: VarValue<K>) {
assert!(self.is_root(key)); assert!(self.is_root(key));
debug!("Updating variable {:?} to {:?}", debug!("Updating variable {:?} to {:?}", key, new_value);
key, new_value);
let index = key.index() as usize; let index = key.index() as usize;
self.values.set(index, new_value); self.values.set(index, new_value);
@ -243,7 +244,7 @@ impl<K:UnifyKey> UnificationTable<K> {
} }
} }
impl<K:UnifyKey> sv::SnapshotVecDelegate for Delegate<K> { impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
type Value = VarValue<K>; type Value = VarValue<K>;
type Undo = (); type Undo = ();
@ -253,7 +254,7 @@ impl<K:UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Base union-find algorithm, where we are just making sets // Base union-find algorithm, where we are just making sets
impl<'tcx,K:UnifyKey> UnificationTable<K> impl<'tcx, K: UnifyKey> UnificationTable<K>
where K::Value: Combine where K::Value: Combine
{ {
pub fn union(&mut self, a_id: K, b_id: K) { pub fn union(&mut self, a_id: K, b_id: K) {
@ -285,30 +286,24 @@ impl<'tcx,K:UnifyKey> UnificationTable<K>
// floats---anything that doesn't have a subtyping relationship we // floats---anything that doesn't have a subtyping relationship we
// need to worry about. // need to worry about.
impl<'tcx,K,V> UnificationTable<K> impl<'tcx, K, V> UnificationTable<K>
where K: UnifyKey<Value=Option<V>>, where K: UnifyKey<Value = Option<V>>,
V: Clone+PartialEq+Debug, V: Clone + PartialEq + Debug
{ {
pub fn unify_var_var(&mut self, pub fn unify_var_var(&mut self, a_id: K, b_id: K) -> Result<(), (V, V)> {
a_id: K,
b_id: K)
-> Result<(),(V,V)>
{
let node_a = self.get(a_id); let node_a = self.get(a_id);
let node_b = self.get(b_id); let node_b = self.get(b_id);
let a_id = node_a.key(); let a_id = node_a.key();
let b_id = node_b.key(); let b_id = node_b.key();
if a_id == b_id { return Ok(()); } if a_id == b_id {
return Ok(());
}
let combined = { let combined = {
match (&node_a.value, &node_b.value) { match (&node_a.value, &node_b.value) {
(&None, &None) => { (&None, &None) => None,
None (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(v.clone()),
}
(&Some(ref v), &None) | (&None, &Some(ref v)) => {
Some(v.clone())
}
(&Some(ref v1), &Some(ref v2)) => { (&Some(ref v1), &Some(ref v2)) => {
if *v1 != *v2 { if *v1 != *v2 {
return Err((v1.clone(), v2.clone())); return Err((v1.clone(), v2.clone()));
@ -323,11 +318,7 @@ impl<'tcx,K,V> UnificationTable<K>
/// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping /// 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`. /// relationships, if `a_id` already has a value, it must be the same as `b`.
pub fn unify_var_value(&mut self, pub fn unify_var_value(&mut self, a_id: K, b: V) -> Result<(), (V, V)> {
a_id: K,
b: V)
-> Result<(),(V,V)>
{
let mut node_a = self.get(a_id); let mut node_a = self.get(a_id);
match node_a.value { match node_a.value {
@ -358,7 +349,13 @@ impl<'tcx,K,V> UnificationTable<K>
pub fn unsolved_variables(&mut self) -> Vec<K> { pub fn unsolved_variables(&mut self) -> Vec<K> {
self.values self.values
.iter() .iter()
.filter_map(|vv| if vv.value.is_some() { None } else { Some(vv.key()) }) .filter_map(|vv| {
if vv.value.is_some() {
None
} else {
Some(vv.key())
}
})
.collect() .collect()
} }
} }

View File

@ -19,9 +19,15 @@ struct UnitKey(u32);
impl UnifyKey for UnitKey { impl UnifyKey for UnitKey {
type Value = (); type Value = ();
fn index(&self) -> u32 { self.0 } fn index(&self) -> u32 {
fn from_index(u: u32) -> UnitKey { UnitKey(u) } self.0
fn tag(_: Option<UnitKey>) -> &'static str { "UnitKey" } }
fn from_index(u: u32) -> UnitKey {
UnitKey(u)
}
fn tag(_: Option<UnitKey>) -> &'static str {
"UnitKey"
}
} }
#[test] #[test]
@ -45,7 +51,7 @@ fn big_array() {
} }
for i in 1..MAX { for i in 1..MAX {
let l = keys[i-1]; let l = keys[i - 1];
let r = keys[i]; let r = keys[i];
ut.union(l, r); ut.union(l, r);
} }
@ -68,7 +74,7 @@ fn big_array_bench(b: &mut Bencher) {
b.iter(|| { b.iter(|| {
for i in 1..MAX { for i in 1..MAX {
let l = keys[i-1]; let l = keys[i - 1];
let r = keys[i]; let r = keys[i];
ut.union(l, r); ut.union(l, r);
} }
@ -90,16 +96,16 @@ fn even_odd() {
keys.push(key); keys.push(key);
if i >= 2 { if i >= 2 {
ut.union(key, keys[i-2]); ut.union(key, keys[i - 2]);
} }
} }
for i in 1..MAX { for i in 1..MAX {
assert!(!ut.unioned(keys[i-1], keys[i])); assert!(!ut.unioned(keys[i - 1], keys[i]));
} }
for i in 2..MAX { for i in 2..MAX {
assert!(ut.unioned(keys[i-2], keys[i])); assert!(ut.unioned(keys[i - 2], keys[i]));
} }
} }
@ -108,9 +114,15 @@ struct IntKey(u32);
impl UnifyKey for IntKey { impl UnifyKey for IntKey {
type Value = Option<i32>; type Value = Option<i32>;
fn index(&self) -> u32 { self.0 } fn index(&self) -> u32 {
fn from_index(u: u32) -> IntKey { IntKey(u) } self.0
fn tag(_: Option<IntKey>) -> &'static str { "IntKey" } }
fn from_index(u: u32) -> IntKey {
IntKey(u)
}
fn tag(_: Option<IntKey>) -> &'static str {
"IntKey"
}
} }
/// Test unifying a key whose value is `Some(_)` with a key whose value is `None`. /// Test unifying a key whose value is `Some(_)` with a key whose value is `None`.
@ -191,4 +203,3 @@ fn unify_key_Some_x_val_x() {
assert!(ut.unify_var_value(k1, 22).is_ok()); assert!(ut.unify_var_value(k1, 22).is_ok());
assert_eq!(ut.probe(k1), Some(22)); assert_eq!(ut.probe(k1), Some(22));
} }

View File

@ -12,11 +12,11 @@ use std::cell::UnsafeCell;
use std::mem; use std::mem;
pub struct VecCell<T> { pub struct VecCell<T> {
data: UnsafeCell<Vec<T>> data: UnsafeCell<Vec<T>>,
} }
impl<T> VecCell<T> { impl<T> VecCell<T> {
pub fn with_capacity(capacity: usize) -> VecCell<T>{ pub fn with_capacity(capacity: usize) -> VecCell<T> {
VecCell { data: UnsafeCell::new(Vec::with_capacity(capacity)) } VecCell { data: UnsafeCell::new(Vec::with_capacity(capacity)) }
} }