mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
apply rustfmt to librustc_data_structures, correcting rust-lang-nursery/rustfmt#836
This commit is contained in:
parent
d31d8a9a91
commit
43dc48c7ff
@ -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],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,12 +101,16 @@ 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> {
|
||||||
@ -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,15 +235,15 @@ 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))
|
||||||
@ -254,7 +259,11 @@ impl<N:Debug,E:Debug> Graph<N,E> {
|
|||||||
|
|
||||||
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> {
|
||||||
@ -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;
|
||||||
@ -301,7 +310,8 @@ 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,
|
||||||
@ -334,7 +344,8 @@ 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>,
|
||||||
}
|
}
|
||||||
@ -348,7 +359,8 @@ 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>,
|
||||||
}
|
}
|
||||||
@ -364,7 +376,7 @@ 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> {
|
||||||
@ -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;
|
||||||
|
@ -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")]);
|
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +56,7 @@ 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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
@ -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)| self.trees[root.tree.get()].root.get() == root_index));
|
.all(|(root, 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,7 +175,10 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,11 +205,16 @@ 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 {
|
{
|
||||||
|
self.nodes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|n| {
|
||||||
|
match n.state {
|
||||||
NodeState::Pending { ref obligation } => Some(obligation),
|
NodeState::Pending { ref obligation } => Some(obligation),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
@ -207,7 +224,8 @@ impl<O: Debug, T: Debug> ObligationForest<O, T> {
|
|||||||
///
|
///
|
||||||
/// 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,16 +457,17 @@ 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| match node.state {
|
.flat_map(|node| {
|
||||||
|
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();
|
||||||
|
|
||||||
@ -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.");
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,9 @@ 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());
|
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"])),
|
||||||
@ -32,8 +33,11 @@ fn push_pop() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
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,8 +65,9 @@ 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());
|
assert_eq!(obligation.chars().next(), tree.chars().next());
|
||||||
match *obligation {
|
match *obligation {
|
||||||
"A.1" => Ok(Some(vec![])),
|
"A.1" => Ok(Some(vec![])),
|
||||||
@ -73,12 +78,16 @@ fn push_pop() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
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());
|
assert_eq!(obligation.chars().next(), tree.chars().next());
|
||||||
match *obligation {
|
match *obligation {
|
||||||
"D.1.i" => Err("D is for dumb"),
|
"D.1.i" => Err("D is for dumb"),
|
||||||
@ -86,8 +95,11 @@ fn push_pop() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
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
|
||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ 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> {
|
||||||
@ -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,10 +126,9 @@ 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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,18 +190,26 @@ 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
@ -47,9 +47,11 @@ struct Edge {
|
|||||||
|
|
||||||
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 {
|
||||||
|
elements: vec![],
|
||||||
edges: vec![],
|
edges: vec![],
|
||||||
closure: RefCell::new(None) }
|
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;
|
||||||
@ -438,7 +443,8 @@ fn pdub_crisscross() {
|
|||||||
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,8 +472,10 @@ fn pdub_crisscross_more() {
|
|||||||
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +85,11 @@ impl<K:UnifyKey> VarValue<K> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
parent: parent, // this is a root
|
||||||
value: value,
|
value: value,
|
||||||
rank: rank }
|
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
|
||||||
@ -124,16 +130,16 @@ impl<K:UnifyKey> VarValue<K> {
|
|||||||
|
|
||||||
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);
|
||||||
@ -287,28 +288,22 @@ impl<'tcx,K:UnifyKey> UnificationTable<K>
|
|||||||
|
|
||||||
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,
|
|
||||||
a_id: K,
|
|
||||||
b_id: K)
|
|
||||||
-> Result<(),(V,V)>
|
|
||||||
{
|
{
|
||||||
|
pub fn unify_var_var(&mut self, 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ 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> {
|
||||||
|
Loading…
Reference in New Issue
Block a user