From 755fcae75e9634e6a11651f46d17d7b1310f821b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 13 Sep 2018 13:27:56 +1000 Subject: [PATCH 1/3] Reorder bitvec.rs. So that the `BitArray` code is all together and before the `BitVector` code, instead of being awkwardly interleaved. --- src/librustc_data_structures/bitvec.rs | 77 +++++++++++++------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 642d24f48313a..acf33697f58b5 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -23,46 +23,6 @@ pub struct BitArray { marker: PhantomData, } -#[derive(Clone, Debug, PartialEq)] -pub struct BitVector { - data: BitArray, -} - -impl BitVector { - pub fn grow(&mut self, num_bits: C) { - self.data.grow(num_bits) - } - - pub fn new() -> BitVector { - BitVector { - data: BitArray::new(0), - } - } - - pub fn with_capacity(bits: usize) -> BitVector { - BitVector { - data: BitArray::new(bits), - } - } - - /// Returns true if the bit has changed. - #[inline] - pub fn insert(&mut self, bit: C) -> bool { - self.grow(bit); - self.data.insert(bit) - } - - #[inline] - pub fn contains(&self, bit: C) -> bool { - let (word, mask) = word_mask(bit); - if let Some(word) = self.data.data.get(word) { - (word & mask) != 0 - } else { - false - } - } -} - impl BitArray { // Do not make this method public, instead switch your use case to BitVector. #[inline] @@ -206,6 +166,43 @@ impl<'a, C: Idx> Iterator for BitIter<'a, C> { } } +/// A resizable BitVector type. +#[derive(Clone, Debug, PartialEq)] +pub struct BitVector { + data: BitArray, +} + +impl BitVector { + pub fn grow(&mut self, num_bits: C) { + self.data.grow(num_bits) + } + + pub fn new() -> BitVector { + BitVector { data: BitArray::new(0) } + } + + pub fn with_capacity(bits: usize) -> BitVector { + BitVector { data: BitArray::new(bits) } + } + + /// Returns true if the bit has changed. + #[inline] + pub fn insert(&mut self, bit: C) -> bool { + self.grow(bit); + self.data.insert(bit) + } + + #[inline] + pub fn contains(&self, bit: C) -> bool { + let (word, mask) = word_mask(bit); + if let Some(word) = self.data.data.get(word) { + (word & mask) != 0 + } else { + false + } + } +} + /// A "bit matrix" is basically a matrix of booleans represented as /// one gigantic bitvector. In other words, it is as if you have /// `rows` bitvectors, each of length `columns`. From b697409f10e70558ef72d39eee4a5f7af60cf16b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 13 Sep 2018 14:19:01 +1000 Subject: [PATCH 2/3] Remove bitslice.rs. This requires the following changes. - It moves parts of bitslice.rs into bitvec.rs: `bitwise()`, `BitwiseOperator`, `bits_to_string()`. - It changes `IdxSet` to just be a wrapper around `BitArray`. - It changes `BitArray` and `BitVec` to use `usize` words instead of `u128` words. (`BitSlice` and `IdxSet` already use `usize`.) Local profiling showed `usize` was better. - It moves some operations from `IdxSet` into `BitArray`: `new_filled()`, `clear()`, `set_up_to()`, `trim_to()` (renamed `clear_above()`), `words()` and `words_mut()`, `encode()` and `decode(). The `IdxSet` operations now just call the `BitArray` operations. - It replaces `BitArray`'s iterator implementation with `IdxSet`'s, because the latter is more concise. It also removes the buggy `size_hint` function from `BitArray`'s iterator, which counted the number of *words* rather than the number of *bits*. `IdxSet`'s iterator is now just a thin wrapper around `BitArray`'s iterator. - It moves some unit tests from `indexed_set.rs` to `bitvec.rs`. --- src/librustc_data_structures/bitslice.rs | 146 ------------ src/librustc_data_structures/bitvec.rs | 237 +++++++++++++++++--- src/librustc_data_structures/indexed_set.rs | 154 ++----------- src/librustc_data_structures/lib.rs | 1 - src/librustc_mir/dataflow/graphviz.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 2 +- src/librustc_mir/dataflow/impls/mod.rs | 2 +- src/librustc_mir/dataflow/mod.rs | 2 +- 8 files changed, 225 insertions(+), 321 deletions(-) delete mode 100644 src/librustc_data_structures/bitslice.rs diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs deleted file mode 100644 index a63033c436528..0000000000000 --- a/src/librustc_data_structures/bitslice.rs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: merge with `bitvec` - -use std::mem; - -pub type Word = usize; - -/// `BitSlice` provides helper methods for treating a `[Word]` -/// as a bitvector. -pub trait BitSlice { - fn clear_bit(&mut self, idx: usize) -> bool; - fn set_bit(&mut self, idx: usize) -> bool; - fn get_bit(&self, idx: usize) -> bool; -} - -impl BitSlice for [Word] { - /// Clears bit at `idx` to 0; returns true iff this changed `self.` - #[inline] - fn clear_bit(&mut self, idx: usize) -> bool { - let words = self; - debug!("clear_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::() * 8), idx); - let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); - debug!("word={} bit_in_word={} bit_mask=0x{:x}", word, bit_in_word, bit_mask); - let oldv = words[word]; - let newv = oldv & !bit_mask; - words[word] = newv; - oldv != newv - } - - /// Sets bit at `idx` to 1; returns true iff this changed `self.` - #[inline] - fn set_bit(&mut self, idx: usize) -> bool { - let words = self; - debug!("set_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::() * 8), idx); - let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); - debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); - let oldv = words[word]; - let newv = oldv | bit_mask; - words[word] = newv; - oldv != newv - } - - /// Extracts value of bit at `idx` in `self`. - #[inline] - fn get_bit(&self, idx: usize) -> bool { - let words = self; - let BitLookup { word, bit_mask, .. } = bit_lookup(idx); - (words[word] & bit_mask) != 0 - } -} - -struct BitLookup { - /// An index of the word holding the bit in original `[Word]` of query. - word: usize, - /// Index of the particular bit within the word holding the bit. - bit_in_word: usize, - /// Word with single 1-bit set corresponding to where the bit is located. - bit_mask: Word, -} - -#[inline] -fn bit_lookup(bit: usize) -> BitLookup { - let word_bits = mem::size_of::() * 8; - let word = bit / word_bits; - let bit_in_word = bit % word_bits; - let bit_mask = 1 << bit_in_word; - BitLookup { word, bit_in_word, bit_mask } -} - -pub fn bits_to_string(words: &[Word], bits: usize) -> String { - let mut result = String::new(); - let mut sep = '['; - - // Note: this is a little endian printout of bytes. - - // i tracks how many bits we have printed so far. - let mut i = 0; - for &word in words.iter() { - let mut v = word; - for _ in 0..mem::size_of::() { // for each byte in `v`: - let remain = bits - i; - // If less than a byte remains, then mask just that many bits. - let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; - assert!(mask <= 0xFF); - let byte = v & mask; - - result.push_str(&format!("{}{:02x}", sep, byte)); - - if remain <= 8 { break; } - v >>= 8; - i += 8; - sep = '-'; - } - sep = '|'; - } - result.push(']'); - - result -} - -#[inline] -pub fn bitwise(out_vec: &mut [Word], - in_vec: &[Word], - op: &Op) -> bool { - assert_eq!(out_vec.len(), in_vec.len()); - let mut changed = false; - for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) { - let old_val = *out_elt; - let new_val = op.join(old_val, *in_elt); - *out_elt = new_val; - changed |= old_val != new_val; - } - changed -} - -pub trait BitwiseOperator { - /// Applies some bit-operation pointwise to each of the bits in the two inputs. - fn join(&self, pred1: Word, pred2: Word) -> Word; -} - -pub struct Intersect; -impl BitwiseOperator for Intersect { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & b } -} -pub struct Union; -impl BitwiseOperator for Union { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a | b } -} -pub struct Subtract; -impl BitwiseOperator for Subtract { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & !b } -} diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index acf33697f58b5..52cc347f8e771 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -9,15 +9,19 @@ // except according to those terms. use indexed_vec::{Idx, IndexVec}; +use rustc_serialize; +use std::iter; use std::marker::PhantomData; +use std::slice; -type Word = u128; -const WORD_BITS: usize = 128; +pub type Word = u64; +pub const WORD_BYTES: usize = ::std::mem::size_of::(); +pub const WORD_BITS: usize = WORD_BYTES * 8; /// A very simple BitArray type. /// /// It does not support resizing after creation; use `BitVector` for that. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct BitArray { data: Vec, marker: PhantomData, @@ -27,7 +31,7 @@ impl BitArray { // Do not make this method public, instead switch your use case to BitVector. #[inline] fn grow(&mut self, num_bits: C) { - let num_words = words(num_bits); + let num_words = num_words(num_bits); if self.data.len() <= num_words { self.data.resize(num_words + 1, 0) } @@ -35,13 +39,29 @@ impl BitArray { #[inline] pub fn new(num_bits: usize) -> BitArray { - let num_words = words(num_bits); + BitArray::new_empty(num_bits) + } + + #[inline] + pub fn new_empty(num_bits: usize) -> BitArray { + let num_words = num_words(num_bits); BitArray { data: vec![0; num_words], marker: PhantomData, } } + #[inline] + pub fn new_filled(num_bits: usize) -> BitArray { + let num_words = num_words(num_bits); + let mut result = BitArray { + data: vec![!0; num_words], + marker: PhantomData, + }; + result.clear_above(num_bits); + result + } + #[inline] pub fn clear(&mut self) { for p in &mut self.data { @@ -49,6 +69,31 @@ impl BitArray { } } + /// Sets all elements up to `num_bits`. + pub fn set_up_to(&mut self, num_bits: usize) { + for p in &mut self.data { + *p = !0; + } + self.clear_above(num_bits); + } + + /// Clear all elements above `num_bits`. + fn clear_above(&mut self, num_bits: usize) { + let first_clear_block = num_bits / WORD_BITS; + + if first_clear_block < self.data.len() { + // Within `first_clear_block`, the `num_bits % WORD_BITS` LSBs + // should remain. + let mask = (1 << (num_bits % WORD_BITS)) - 1; + self.data[first_clear_block] &= mask; + + // All the blocks above `first_clear_block` are fully cleared. + for b in &mut self.data[first_clear_block + 1..] { + *b = 0; + } + } + } + pub fn count(&self) -> usize { self.data.iter().map(|e| e.count_ones() as usize).sum() } @@ -88,7 +133,7 @@ impl BitArray { /// Sets all bits to true. pub fn insert_all(&mut self) { for data in &mut self.data { - *data = u128::max_value(); + *data = !0; } } @@ -117,53 +162,132 @@ impl BitArray { changed } + pub fn words(&self) -> &[Word] { + &self.data + } + + pub fn words_mut(&mut self) -> &mut [Word] { + &mut self.data + } + /// Iterates over indexes of set bits in a sorted order #[inline] pub fn iter<'a>(&'a self) -> BitIter<'a, C> { BitIter { - iter: self.data.iter(), - current: 0, - idx: 0, + cur: None, + iter: self.data.iter().enumerate(), marker: PhantomData, } } } +impl rustc_serialize::Encodable for BitArray { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { + self.data.encode(encoder) + } +} + +impl rustc_serialize::Decodable for BitArray { + fn decode(d: &mut D) -> Result, D::Error> { + let words: Vec = rustc_serialize::Decodable::decode(d)?; + Ok(BitArray { + data: words, + marker: PhantomData, + }) + } +} + pub struct BitIter<'a, C: Idx> { - iter: ::std::slice::Iter<'a, Word>, - current: Word, - idx: usize, + cur: Option<(Word, usize)>, + iter: iter::Enumerate>, marker: PhantomData } impl<'a, C: Idx> Iterator for BitIter<'a, C> { type Item = C; fn next(&mut self) -> Option { - while self.current == 0 { - self.current = if let Some(&i) = self.iter.next() { - if i == 0 { - self.idx += WORD_BITS; - continue; - } else { - self.idx = words(self.idx) * WORD_BITS; - i + loop { + if let Some((ref mut word, offset)) = self.cur { + let bit_pos = word.trailing_zeros() as usize; + if bit_pos != WORD_BITS { + let bit = 1 << bit_pos; + *word ^= bit; + return Some(C::new(bit_pos + offset)) } - } else { - return None; } - } - let offset = self.current.trailing_zeros() as usize; - self.current >>= offset; - self.current >>= 1; // shift otherwise overflows for 0b1000_0000_…_0000 - self.idx += offset + 1; - Some(C::new(self.idx - 1)) + let (i, word) = self.iter.next()?; + self.cur = Some((*word, WORD_BITS * i)); + } } +} - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) +pub trait BitwiseOperator { + /// Applies some bit-operation pointwise to each of the bits in the two inputs. + fn join(&self, pred1: Word, pred2: Word) -> Word; +} + +#[inline] +pub fn bitwise(out_vec: &mut [Word], in_vec: &[Word], op: &Op) -> bool +{ + assert_eq!(out_vec.len(), in_vec.len()); + let mut changed = false; + for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + let old_val = *out_elem; + let new_val = op.join(old_val, *in_elem); + *out_elem = new_val; + changed |= old_val != new_val; + } + changed +} + +pub struct Intersect; +impl BitwiseOperator for Intersect { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a & b } +} + +pub struct Union; +impl BitwiseOperator for Union { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a | b } +} + +pub struct Subtract; +impl BitwiseOperator for Subtract { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a & !b } +} + +pub fn bits_to_string(words: &[Word], bits: usize) -> String { + let mut result = String::new(); + let mut sep = '['; + + // Note: this is a little endian printout of bytes. + + // i tracks how many bits we have printed so far. + let mut i = 0; + for &word in words.iter() { + let mut v = word; + for _ in 0..WORD_BYTES { // for each byte in `v`: + let remain = bits - i; + // If less than a byte remains, then mask just that many bits. + let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; + assert!(mask <= 0xFF); + let byte = v & mask; + + result.push_str(&format!("{}{:02x}", sep, byte)); + + if remain <= 8 { break; } + v >>= 8; + i += 8; + sep = '-'; + } + sep = '|'; } + result.push(']'); + + result } /// A resizable BitVector type. @@ -218,7 +342,7 @@ impl BitMatrix { pub fn new(rows: usize, columns: usize) -> BitMatrix { // For every element, we need one bit for every other // element. Round up to an even number of words. - let words_per_row = words(columns); + let words_per_row = num_words(columns); BitMatrix { columns, vector: vec![0; rows * words_per_row], @@ -229,7 +353,7 @@ impl BitMatrix { /// The range of bits for a given row. fn range(&self, row: R) -> (usize, usize) { let row = row.index(); - let words_per_row = words(self.columns); + let words_per_row = num_words(self.columns); let start = row * words_per_row; (start, start + words_per_row) } @@ -307,9 +431,8 @@ impl BitMatrix { pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { let (start, end) = self.range(row); BitIter { - iter: self.vector[start..end].iter(), - current: 0, - idx: 0, + cur: None, + iter: self.vector[start..end].iter().enumerate(), marker: PhantomData, } } @@ -418,7 +541,7 @@ impl SparseBitMatrix { } #[inline] -fn words(elements: C) -> usize { +fn num_words(elements: C) -> usize { (elements.index() + WORD_BITS - 1) / WORD_BITS } @@ -430,6 +553,46 @@ fn word_mask(index: C) -> (usize, Word) { (word, mask) } +#[test] +fn test_clear_above() { + use std::cmp; + + for i in 0..256 { + let mut idx_buf: BitArray = BitArray::new_filled(128); + idx_buf.clear_above(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..cmp::min(i, 128)).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn test_set_up_to() { + for i in 0..128 { + for mut idx_buf in + vec![BitArray::new_empty(128), BitArray::new_filled(128)] + .into_iter() + { + idx_buf.set_up_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } + } +} + +#[test] +fn test_new_filled() { + for i in 0..128 { + let idx_buf = BitArray::new_filled(i); + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } +} + #[test] fn bitvec_iter_works() { let mut bitvec: BitArray = BitArray::new(100); diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index 65fdf10a86d13..be519e7bbdeb7 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -10,12 +10,9 @@ use array_vec::ArrayVec; use std::fmt; -use std::iter; -use std::marker::PhantomData; use std::mem; use std::slice; -use bitslice::{BitSlice, Word}; -use bitslice::{bitwise, Union, Subtract, Intersect}; +use bitvec::{bitwise, BitArray, BitIter, Intersect, Subtract, Union, Word, WORD_BITS}; use indexed_vec::Idx; use rustc_serialize; @@ -40,39 +37,21 @@ pub trait SubtractFromIdxSet { /// this type uses to represent the set of object it holds. /// /// The representation is dense, using one bit per possible element. -#[derive(Eq, PartialEq)] -pub struct IdxSet { - _pd: PhantomData, - bits: Vec, -} - -impl Clone for IdxSet { - fn clone(&self) -> Self { - IdxSet { _pd: PhantomData, bits: self.bits.clone() } - } -} +#[derive(Clone, Eq, PartialEq)] +pub struct IdxSet(BitArray); impl rustc_serialize::Encodable for IdxSet { - fn encode(&self, - encoder: &mut E) - -> Result<(), E::Error> { - self.bits.encode(encoder) + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { + self.0.encode(encoder) } } impl rustc_serialize::Decodable for IdxSet { fn decode(d: &mut D) -> Result, D::Error> { - let words: Vec = rustc_serialize::Decodable::decode(d)?; - - Ok(IdxSet { - _pd: PhantomData, - bits: words, - }) + Ok(IdxSet(rustc_serialize::Decodable::decode(d)?)) } } -const BITS_PER_WORD: usize = mem::size_of::() * 8; - impl fmt::Debug for IdxSet { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { w.debug_list() @@ -82,31 +61,21 @@ impl fmt::Debug for IdxSet { } impl IdxSet { - fn new(init: Word, domain_size: usize) -> Self { - let num_words = (domain_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD; - IdxSet { - _pd: Default::default(), - bits: vec![init; num_words], - } + /// Creates set holding no elements. + pub fn new_empty(domain_size: usize) -> Self { + IdxSet(BitArray::new_empty(domain_size)) } /// Creates set holding every element whose index falls in range 0..domain_size. pub fn new_filled(domain_size: usize) -> Self { - let mut result = Self::new(!0, domain_size); - result.trim_to(domain_size); - result - } - - /// Creates set holding no elements. - pub fn new_empty(domain_size: usize) -> Self { - Self::new(0, domain_size) + IdxSet(BitArray::new_filled(domain_size)) } /// Duplicates as a hybrid set. pub fn to_hybrid(&self) -> HybridIdxSet { // This domain_size may be slightly larger than the one specified // upon creation, due to rounding up to a whole word. That's ok. - let domain_size = self.bits.len() * BITS_PER_WORD; + let domain_size = self.words().len() * WORD_BITS; // Note: we currently don't bother trying to make a Sparse set. HybridIdxSet::Dense(self.to_owned(), domain_size) @@ -114,60 +83,35 @@ impl IdxSet { /// Removes all elements pub fn clear(&mut self) { - for b in &mut self.bits { - *b = 0; - } + self.0.clear(); } /// Sets all elements up to `domain_size` pub fn set_up_to(&mut self, domain_size: usize) { - for b in &mut self.bits { - *b = !0; - } - self.trim_to(domain_size); - } - - /// Clear all elements above `domain_size`. - fn trim_to(&mut self, domain_size: usize) { - // `trim_block` is the first block where some bits have - // to be cleared. - let trim_block = domain_size / BITS_PER_WORD; - - // all the blocks above it have to be completely cleared. - if trim_block < self.bits.len() { - for b in &mut self.bits[trim_block+1..] { - *b = 0; - } - - // at that block, the `domain_size % BITS_PER_WORD` LSBs - // should remain. - let remaining_bits = domain_size % BITS_PER_WORD; - let mask = (1< bool { - self.bits.clear_bit(elem.index()) + self.0.remove(*elem) } /// Adds `elem` to the set `self`; returns true iff this changed `self`. pub fn add(&mut self, elem: &T) -> bool { - self.bits.set_bit(elem.index()) + self.0.insert(*elem) } /// Returns true iff set `self` contains `elem`. pub fn contains(&self, elem: &T) -> bool { - self.bits.get_bit(elem.index()) + self.0.contains(*elem) } pub fn words(&self) -> &[Word] { - &self.bits + self.0.words() } pub fn words_mut(&mut self) -> &mut [Word] { - &mut self.bits + self.0.words_mut() } /// Efficiently overwrite `self` with `other`. Panics if `self` and `other` @@ -196,9 +140,7 @@ impl IdxSet { pub fn iter(&self) -> Iter { Iter { - cur: None, - iter: self.words().iter().enumerate(), - _pd: PhantomData, + iter: self.0.iter() } } } @@ -216,28 +158,14 @@ impl SubtractFromIdxSet for IdxSet { } pub struct Iter<'a, T: Idx> { - cur: Option<(Word, usize)>, - iter: iter::Enumerate>, - _pd: PhantomData, + iter: BitIter<'a, T> } impl<'a, T: Idx> Iterator for Iter<'a, T> { type Item = T; fn next(&mut self) -> Option { - loop { - if let Some((ref mut word, offset)) = self.cur { - let bit_pos = word.trailing_zeros() as usize; - if bit_pos != BITS_PER_WORD { - let bit = 1 << bit_pos; - *word ^= bit; - return Some(T::new(bit_pos + offset)) - } - } - - let (i, word) = self.iter.next()?; - self.cur = Some((*word, BITS_PER_WORD * i)); - } + self.iter.next() } } @@ -456,43 +384,3 @@ impl<'a, T: Idx> Iterator for HybridIter<'a, T> { } } } - -#[test] -fn test_trim_to() { - use std::cmp; - - for i in 0..256 { - let mut idx_buf: IdxSet = IdxSet::new_filled(128); - idx_buf.trim_to(i); - - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..cmp::min(i, 128)).collect(); - assert_eq!(elems, expected); - } -} - -#[test] -fn test_set_up_to() { - for i in 0..128 { - for mut idx_buf in - vec![IdxSet::new_empty(128), IdxSet::new_filled(128)] - .into_iter() - { - idx_buf.set_up_to(i); - - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); - } - } -} - -#[test] -fn test_new_filled() { - for i in 0..128 { - let idx_buf = IdxSet::new_filled(i); - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); - } -} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 7915650fd89f7..1fdcab5f7a215 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -63,7 +63,6 @@ pub use rustc_serialize::hex::ToHex; pub mod svh; pub mod array_vec; pub mod base_n; -pub mod bitslice; pub mod bitvec; pub mod const_cstr; pub mod flock; diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 2b5d26c748704..9487147ea9df9 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -12,7 +12,7 @@ use syntax::ast::NodeId; use rustc::mir::{BasicBlock, Mir}; -use rustc_data_structures::bitslice::bits_to_string; +use rustc_data_structures::bitvec::bits_to_string; use dot; use dot::IntoCow; diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f42612b4b7a73..6f004227f5682 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -20,7 +20,7 @@ use rustc::ty::TyCtxt; use rustc::ty::{RegionKind, RegionVid}; use rustc::ty::RegionKind::ReScope; -use rustc_data_structures::bitslice::{BitwiseOperator, Word}; +use rustc_data_structures::bitvec::{BitwiseOperator, Word}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 62c6018809f39..c8f704798529b 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::{BitwiseOperator, Word}; +use rustc_data_structures::bitvec::{BitwiseOperator, Word}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index d6874e290d4f6..49d75d31fc7fb 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, MetaItem}; -use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; +use rustc_data_structures::bitvec::{bitwise, BitwiseOperator}; use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; From 56be2afec56c6c958b3185a4ce8307d13fb8bf2f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Sep 2018 08:06:52 +1000 Subject: [PATCH 3/3] Remove `Iter` and `SparseIter` in indexed_set.rs. Because they're just thin wrappers around `BitIter` and `slice::Iter`. --- src/librustc_data_structures/indexed_set.rs | 42 ++++----------------- src/librustc_mir/borrow_check/flows.rs | 4 +- src/librustc_mir/dataflow/at_location.rs | 7 ++-- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index be519e7bbdeb7..5ba8c150e1fcb 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -138,10 +138,8 @@ impl IdxSet { bitwise(self.words_mut(), other.words(), &Intersect) } - pub fn iter(&self) -> Iter { - Iter { - iter: self.0.iter() - } + pub fn iter(&self) -> BitIter { + self.0.iter() } } @@ -157,18 +155,6 @@ impl SubtractFromIdxSet for IdxSet { } } -pub struct Iter<'a, T: Idx> { - iter: BitIter<'a, T> -} - -impl<'a, T: Idx> Iterator for Iter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.iter.next() - } -} - const SPARSE_MAX: usize = 8; /// A sparse index set with a maximum of SPARSE_MAX elements. Used by @@ -221,10 +207,8 @@ impl SparseIdxSet { dense } - fn iter(&self) -> SparseIter { - SparseIter { - iter: self.0.iter(), - } + fn iter(&self) -> slice::Iter { + self.0.iter() } } @@ -248,18 +232,6 @@ impl SubtractFromIdxSet for SparseIdxSet { } } -pub struct SparseIter<'a, T: Idx> { - iter: slice::Iter<'a, T>, -} - -impl<'a, T: Idx> Iterator for SparseIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - self.iter.next().map(|e| *e) - } -} - /// Like IdxSet, but with a hybrid representation: sparse when there are few /// elements in the set, but dense when there are many. It's especially /// efficient for sets that typically have a small number of elements, but a @@ -370,8 +342,8 @@ impl SubtractFromIdxSet for HybridIdxSet { } pub enum HybridIter<'a, T: Idx> { - Sparse(SparseIter<'a, T>), - Dense(Iter<'a, T>), + Sparse(slice::Iter<'a, T>), + Dense(BitIter<'a, T>), } impl<'a, T: Idx> Iterator for HybridIter<'a, T> { @@ -379,7 +351,7 @@ impl<'a, T: Idx> Iterator for HybridIter<'a, T> { fn next(&mut self) -> Option { match self { - HybridIter::Sparse(sparse) => sparse.next(), + HybridIter::Sparse(sparse) => sparse.next().map(|e| *e), HybridIter::Dense(dense) => dense.next(), } } diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 6b964fec74fdd..a4900ab57f588 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -15,7 +15,7 @@ use rustc::mir::{BasicBlock, Location}; use rustc::ty::RegionVid; -use rustc_data_structures::indexed_set::Iter; +use rustc_data_structures::bitvec::BitIter; use borrow_check::location::LocationIndex; @@ -67,7 +67,7 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { } } - crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter)) { + crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter)) { self.borrows.with_iter_outgoing(op) } } diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 1dc91cd05b33e..39643af77a178 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -12,7 +12,8 @@ //! locations. use rustc::mir::{BasicBlock, Location}; -use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet, Iter}; +use rustc_data_structures::bitvec::BitIter; +use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; use dataflow::{BitDenotation, BlockSets, DataflowResults}; use dataflow::move_paths::{HasMoveData, MovePathIndex}; @@ -125,7 +126,7 @@ where } /// Returns an iterator over the elements present in the current state. - pub fn iter_incoming(&self) -> iter::Peekable> { + pub fn iter_incoming(&self) -> iter::Peekable> { self.curr_state.iter().peekable() } @@ -134,7 +135,7 @@ where /// Invokes `f` with an iterator over the resulting state. pub fn with_iter_outgoing(&self, f: F) where - F: FnOnce(Iter), + F: FnOnce(BitIter), { let mut curr_state = self.curr_state.clone(); curr_state.union(&self.stmt_gen);