Merge indexed_set.rs into bitvec.rs, and rename it bit_set.rs.
Currently we have two files implementing bitsets (and 2D bit matrices). This commit combines them into one, taking the best features from each. This involves renaming a lot of things. The high level changes are as follows. - bitvec.rs --> bit_set.rs - indexed_set.rs --> (removed) - BitArray + IdxSet --> BitSet (merged, see below) - BitVector --> GrowableBitSet - {,Sparse,Hybrid}IdxSet --> {,Sparse,Hybrid}BitSet - BitMatrix --> BitMatrix - SparseBitMatrix --> SparseBitMatrix The changes within the bitset types themselves are as follows. ``` OLD OLD NEW BitArray<C> IdxSet<T> BitSet<T> -------- ------ ------ grow - grow new - (remove) new_empty new_empty new_empty new_filled new_filled new_filled - to_hybrid to_hybrid clear clear clear set_up_to set_up_to set_up_to clear_above - clear_above count - count contains(T) contains(&T) contains(T) contains_all - superset is_empty - is_empty insert(T) add(&T) insert(T) insert_all - insert_all() remove(T) remove(&T) remove(T) words words words words_mut words_mut words_mut - overwrite overwrite merge union union - subtract subtract - intersect intersect iter iter iter ``` In general, when choosing names I went with: - names that are more obvious (e.g. `BitSet` over `IdxSet`). - names that are more like the Rust libraries (e.g. `T` over `C`, `insert` over `add`); - names that are more set-like (e.g. `union` over `merge`, `superset` over `contains_all`, `domain_size` over `num_bits`). Also, using `T` for index arguments seems more sensible than `&T` -- even though the latter is standard in Rust collection types -- because indices are always copyable. It also results in fewer `&` and `*` sigils in practice.
This commit is contained in:
parent
8a2dec6e58
commit
266e2d3d69
40 changed files with 1276 additions and 1377 deletions
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -32,7 +32,7 @@ use super::*;
|
|||
#[derive(Clone)]
|
||||
pub struct Preorder<'a, 'tcx: 'a> {
|
||||
mir: &'a Mir<'tcx>,
|
||||
visited: BitArray<BasicBlock>,
|
||||
visited: BitSet<BasicBlock>,
|
||||
worklist: Vec<BasicBlock>,
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
|
|||
|
||||
Preorder {
|
||||
mir,
|
||||
visited: BitArray::new(mir.basic_blocks().len()),
|
||||
visited: BitSet::new_empty(mir.basic_blocks().len()),
|
||||
worklist,
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
|
|||
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
|
||||
pub struct Postorder<'a, 'tcx: 'a> {
|
||||
mir: &'a Mir<'tcx>,
|
||||
visited: BitArray<BasicBlock>,
|
||||
visited: BitSet<BasicBlock>,
|
||||
visit_stack: Vec<(BasicBlock, Successors<'a>)>
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
|
|||
pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
|
||||
let mut po = Postorder {
|
||||
mir,
|
||||
visited: BitArray::new(mir.basic_blocks().len()),
|
||||
visited: BitSet::new_empty(mir.basic_blocks().len()),
|
||||
visit_stack: Vec::new()
|
||||
};
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ use ty::relate::TypeRelation;
|
|||
use middle::lang_items;
|
||||
use mir::interpret::{GlobalId};
|
||||
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use std::iter;
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
|
@ -3069,7 +3069,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
} else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
let mut ty_params = BitArray::new(substs_a.types().count());
|
||||
let mut ty_params = BitSet::new_empty(substs_a.types().count());
|
||||
let mut found = false;
|
||||
for ty in field.walk() {
|
||||
if let ty::Param(p) = ty.sty {
|
||||
|
|
|
@ -49,14 +49,14 @@ use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
|
|||
use util::common::{ErrorReported};
|
||||
use util::profiling::ProfileCategory::*;
|
||||
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::StableVec;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
use std::ops::Deref;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::sync::Arc;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax_pos::symbol::InternedString;
|
||||
|
@ -208,7 +208,7 @@ define_queries! { <'tcx>
|
|||
/// Maps DefId's that have an associated Mir to the result
|
||||
/// of the MIR qualify_consts pass. The actual meaning of
|
||||
/// the value isn't known except to the pass itself.
|
||||
[] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<IdxSet<mir::Local>>),
|
||||
[] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<BitSet<mir::Local>>),
|
||||
|
||||
/// Fetch the MIR for a given def-id right after it's built - this includes
|
||||
/// unreachable code.
|
||||
|
|
|
@ -21,7 +21,7 @@ use libc::c_uint;
|
|||
|
||||
use syntax_pos::Pos;
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
||||
use syntax_pos::BytePos;
|
||||
|
@ -64,7 +64,7 @@ pub fn create_mir_scopes(
|
|||
};
|
||||
|
||||
// Find all the scopes with variables defined in them.
|
||||
let mut has_variables = BitArray::new(mir.source_scopes.len());
|
||||
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
|
||||
for var in mir.vars_iter() {
|
||||
let decl = &mir.local_decls[var];
|
||||
has_variables.insert(decl.visibility_scope);
|
||||
|
@ -81,7 +81,7 @@ pub fn create_mir_scopes(
|
|||
|
||||
fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
||||
mir: &Mir,
|
||||
has_variables: &BitArray<SourceScope>,
|
||||
has_variables: &BitSet<SourceScope>,
|
||||
debug_context: &FunctionDebugContextData<'ll>,
|
||||
scope: SourceScope,
|
||||
scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! An analysis to determine which locals require allocas and
|
||||
//! which do not.
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc::mir::{self, Location, TerminatorKind};
|
||||
|
@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf;
|
|||
use type_of::LayoutLlvmExt;
|
||||
use super::FunctionCx;
|
||||
|
||||
pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
|
||||
pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitSet<mir::Local> {
|
||||
let mir = fx.mir;
|
||||
let mut analyzer = LocalAnalyzer::new(fx);
|
||||
|
||||
|
@ -54,7 +54,7 @@ pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
|
|||
struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
|
||||
fx: &'mir FunctionCx<'a, 'll, 'tcx>,
|
||||
dominators: Dominators<mir::BasicBlock>,
|
||||
non_ssa_locals: BitArray<mir::Local>,
|
||||
non_ssa_locals: BitSet<mir::Local>,
|
||||
// The location of the first visited direct assignment to each
|
||||
// local, or an invalid location (out of bounds `block` index).
|
||||
first_assignment: IndexVec<mir::Local, Location>
|
||||
|
@ -67,7 +67,7 @@ impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
|
|||
let mut analyzer = LocalAnalyzer {
|
||||
fx,
|
||||
dominators: fx.mir.dominators(),
|
||||
non_ssa_locals: BitArray::new(fx.mir.local_decls.len()),
|
||||
non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
|
||||
first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ use syntax::symbol::keywords;
|
|||
|
||||
use std::iter;
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
|
||||
pub use self::constant::codegen_static_initializer;
|
||||
|
@ -341,7 +341,7 @@ pub fn codegen_mir(
|
|||
debuginfo::start_emitting_source_locations(&fx.debug_context);
|
||||
|
||||
let rpo = traversal::reverse_postorder(&mir);
|
||||
let mut visited = BitArray::new(mir.basic_blocks().len());
|
||||
let mut visited = BitSet::new_empty(mir.basic_blocks().len());
|
||||
|
||||
// Codegen the body of each block using reverse postorder
|
||||
for (bb, _) in rpo {
|
||||
|
@ -435,7 +435,7 @@ fn arg_local_refs(
|
|||
bx: &Builder<'a, 'll, 'tcx>,
|
||||
fx: &FunctionCx<'a, 'll, 'tcx>,
|
||||
scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
|
||||
memory_locals: &BitArray<mir::Local>,
|
||||
memory_locals: &BitSet<mir::Local>,
|
||||
) -> Vec<LocalRef<'ll, 'tcx>> {
|
||||
let mir = fx.mir;
|
||||
let tcx = bx.tcx();
|
||||
|
|
1046
src/librustc_data_structures/bit_set.rs
Normal file
1046
src/librustc_data_structures/bit_set.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,781 +0,0 @@
|
|||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use indexed_vec::{Idx, IndexVec};
|
||||
use rustc_serialize;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::slice;
|
||||
|
||||
pub type Word = u64;
|
||||
pub const WORD_BYTES: usize = ::std::mem::size_of::<Word>();
|
||||
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, Eq, PartialEq)]
|
||||
pub struct BitArray<C: Idx> {
|
||||
data: Vec<Word>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: Idx> BitArray<C> {
|
||||
// Do not make this method public, instead switch your use case to BitVector.
|
||||
#[inline]
|
||||
fn grow(&mut self, num_bits: C) {
|
||||
let num_words = num_words(num_bits);
|
||||
if self.data.len() <= num_words {
|
||||
self.data.resize(num_words + 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(num_bits: usize) -> BitArray<C> {
|
||||
BitArray::new_empty(num_bits)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_empty(num_bits: usize) -> BitArray<C> {
|
||||
let num_words = num_words(num_bits);
|
||||
BitArray {
|
||||
data: vec![0; num_words],
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_filled(num_bits: usize) -> BitArray<C> {
|
||||
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 {
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// True if `self` contains the bit `bit`.
|
||||
#[inline]
|
||||
pub fn contains(&self, bit: C) -> bool {
|
||||
let (word, mask) = word_mask(bit);
|
||||
(self.data[word] & mask) != 0
|
||||
}
|
||||
|
||||
/// True if `self` contains all the bits in `other`.
|
||||
///
|
||||
/// The two vectors must have the same length.
|
||||
#[inline]
|
||||
pub fn contains_all(&self, other: &BitArray<C>) -> bool {
|
||||
assert_eq!(self.data.len(), other.data.len());
|
||||
self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.iter().all(|a| *a == 0)
|
||||
}
|
||||
|
||||
/// Returns true if the bit has changed.
|
||||
#[inline]
|
||||
pub fn insert(&mut self, bit: C) -> bool {
|
||||
let (word, mask) = word_mask(bit);
|
||||
let data = &mut self.data[word];
|
||||
let value = *data;
|
||||
let new_value = value | mask;
|
||||
*data = new_value;
|
||||
new_value != value
|
||||
}
|
||||
|
||||
/// Sets all bits to true.
|
||||
pub fn insert_all(&mut self) {
|
||||
for data in &mut self.data {
|
||||
*data = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the bit has changed.
|
||||
#[inline]
|
||||
pub fn remove(&mut self, bit: C) -> bool {
|
||||
let (word, mask) = word_mask(bit);
|
||||
let data = &mut self.data[word];
|
||||
let value = *data;
|
||||
let new_value = value & !mask;
|
||||
*data = new_value;
|
||||
new_value != value
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn merge(&mut self, all: &BitArray<C>) -> bool {
|
||||
assert!(self.data.len() == all.data.len());
|
||||
let mut changed = false;
|
||||
for (i, j) in self.data.iter_mut().zip(&all.data) {
|
||||
let value = *i;
|
||||
*i = value | *j;
|
||||
if value != *i {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
cur: None,
|
||||
iter: self.data.iter().enumerate(),
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> rustc_serialize::Encodable for BitArray<T> {
|
||||
fn encode<E: rustc_serialize::Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
|
||||
self.data.encode(encoder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> rustc_serialize::Decodable for BitArray<T> {
|
||||
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<BitArray<T>, D::Error> {
|
||||
let words: Vec<Word> = rustc_serialize::Decodable::decode(d)?;
|
||||
Ok(BitArray {
|
||||
data: words,
|
||||
marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BitIter<'a, C: Idx> {
|
||||
cur: Option<(Word, usize)>,
|
||||
iter: iter::Enumerate<slice::Iter<'a, Word>>,
|
||||
marker: PhantomData<C>
|
||||
}
|
||||
|
||||
impl<'a, C: Idx> Iterator for BitIter<'a, C> {
|
||||
type Item = C;
|
||||
fn next(&mut self) -> Option<C> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
let (i, word) = self.iter.next()?;
|
||||
self.cur = Some((*word, WORD_BITS * i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<Op: BitwiseOperator>(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.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BitVector<C: Idx> {
|
||||
data: BitArray<C>,
|
||||
}
|
||||
|
||||
impl<C: Idx> BitVector<C> {
|
||||
pub fn grow(&mut self, num_bits: C) {
|
||||
self.data.grow(num_bits)
|
||||
}
|
||||
|
||||
pub fn new() -> BitVector<C> {
|
||||
BitVector { data: BitArray::new(0) }
|
||||
}
|
||||
|
||||
pub fn with_capacity(bits: usize) -> BitVector<C> {
|
||||
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`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BitMatrix<R: Idx, C: Idx> {
|
||||
columns: usize,
|
||||
vector: Vec<Word>,
|
||||
phantom: PhantomData<(R, C)>,
|
||||
}
|
||||
|
||||
impl<R: Idx, C: Idx> BitMatrix<R, C> {
|
||||
/// Create a new `rows x columns` matrix, initially empty.
|
||||
pub fn new(rows: usize, columns: usize) -> BitMatrix<R, C> {
|
||||
// For every element, we need one bit for every other
|
||||
// element. Round up to an even number of words.
|
||||
let words_per_row = num_words(columns);
|
||||
BitMatrix {
|
||||
columns,
|
||||
vector: vec![0; rows * words_per_row],
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// The range of bits for a given row.
|
||||
fn range(&self, row: R) -> (usize, usize) {
|
||||
let row = row.index();
|
||||
let words_per_row = num_words(self.columns);
|
||||
let start = row * words_per_row;
|
||||
(start, start + words_per_row)
|
||||
}
|
||||
|
||||
/// Sets the cell at `(row, column)` to true. Put another way, add
|
||||
/// `column` to the bitset for `row`.
|
||||
///
|
||||
/// Returns true if this changed the matrix, and false otherwise.
|
||||
pub fn add(&mut self, row: R, column: R) -> bool {
|
||||
let (start, _) = self.range(row);
|
||||
let (word, mask) = word_mask(column);
|
||||
let vector = &mut self.vector[..];
|
||||
let v1 = vector[start + word];
|
||||
let v2 = v1 | mask;
|
||||
vector[start + word] = v2;
|
||||
v1 != v2
|
||||
}
|
||||
|
||||
/// Do the bits from `row` contain `column`? Put another way, is
|
||||
/// the matrix cell at `(row, column)` true? Put yet another way,
|
||||
/// if the matrix represents (transitive) reachability, can
|
||||
/// `row` reach `column`?
|
||||
pub fn contains(&self, row: R, column: R) -> bool {
|
||||
let (start, _) = self.range(row);
|
||||
let (word, mask) = word_mask(column);
|
||||
(self.vector[start + word] & mask) != 0
|
||||
}
|
||||
|
||||
/// Returns those indices that are true in rows `a` and `b`. This
|
||||
/// is an O(n) operation where `n` is the number of elements
|
||||
/// (somewhat independent from the actual size of the
|
||||
/// intersection, in particular).
|
||||
pub fn intersection(&self, a: R, b: R) -> Vec<C> {
|
||||
let (a_start, a_end) = self.range(a);
|
||||
let (b_start, b_end) = self.range(b);
|
||||
let mut result = Vec::with_capacity(self.columns);
|
||||
for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() {
|
||||
let mut v = self.vector[i] & self.vector[j];
|
||||
for bit in 0..WORD_BITS {
|
||||
if v == 0 {
|
||||
break;
|
||||
}
|
||||
if v & 0x1 != 0 {
|
||||
result.push(C::new(base * WORD_BITS + bit));
|
||||
}
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Add the bits from row `read` to the bits from row `write`,
|
||||
/// return true if anything changed.
|
||||
///
|
||||
/// This is used when computing transitive reachability because if
|
||||
/// you have an edge `write -> read`, because in that case
|
||||
/// `write` can reach everything that `read` can (and
|
||||
/// potentially more).
|
||||
pub fn merge(&mut self, read: R, write: R) -> bool {
|
||||
let (read_start, read_end) = self.range(read);
|
||||
let (write_start, write_end) = self.range(write);
|
||||
let vector = &mut self.vector[..];
|
||||
let mut changed = false;
|
||||
for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) {
|
||||
let v1 = vector[write_index];
|
||||
let v2 = v1 | vector[read_index];
|
||||
vector[write_index] = v2;
|
||||
changed |= v1 != v2;
|
||||
}
|
||||
changed
|
||||
}
|
||||
|
||||
/// Iterates through all the columns set to true in a given row of
|
||||
/// the matrix.
|
||||
pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
|
||||
let (start, end) = self.range(row);
|
||||
BitIter {
|
||||
cur: None,
|
||||
iter: self.vector[start..end].iter().enumerate(),
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A moderately sparse bit matrix, in which rows are instantiated lazily.
|
||||
///
|
||||
/// Initially, every row has no explicit representation. If any bit within a
|
||||
/// row is set, the entire row is instantiated as
|
||||
/// `Some(<full-column-width-BitArray>)`. Furthermore, any previously
|
||||
/// uninstantiated rows prior to it will be instantiated as `None`. Those prior
|
||||
/// rows may themselves become fully instantiated later on if any of their bits
|
||||
/// are set.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SparseBitMatrix<R, C>
|
||||
where
|
||||
R: Idx,
|
||||
C: Idx,
|
||||
{
|
||||
num_columns: usize,
|
||||
rows: IndexVec<R, Option<BitArray<C>>>,
|
||||
}
|
||||
|
||||
impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
|
||||
/// Create a new empty sparse bit matrix with no rows or columns.
|
||||
pub fn new(num_columns: usize) -> Self {
|
||||
Self {
|
||||
num_columns,
|
||||
rows: IndexVec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_row(&mut self, row: R) -> &mut BitArray<C> {
|
||||
// Instantiate any missing rows up to and including row `row` with an
|
||||
// empty BitArray.
|
||||
self.rows.ensure_contains_elem(row, || None);
|
||||
|
||||
// Then replace row `row` with a full BitArray if necessary.
|
||||
let num_columns = self.num_columns;
|
||||
self.rows[row].get_or_insert_with(|| BitArray::new(num_columns))
|
||||
}
|
||||
|
||||
/// Sets the cell at `(row, column)` to true. Put another way, insert
|
||||
/// `column` to the bitset for `row`.
|
||||
///
|
||||
/// Returns true if this changed the matrix, and false otherwise.
|
||||
pub fn add(&mut self, row: R, column: C) -> bool {
|
||||
self.ensure_row(row).insert(column)
|
||||
}
|
||||
|
||||
/// Do the bits from `row` contain `column`? Put another way, is
|
||||
/// the matrix cell at `(row, column)` true? Put yet another way,
|
||||
/// if the matrix represents (transitive) reachability, can
|
||||
/// `row` reach `column`?
|
||||
pub fn contains(&self, row: R, column: C) -> bool {
|
||||
self.row(row).map_or(false, |r| r.contains(column))
|
||||
}
|
||||
|
||||
/// Add the bits from row `read` to the bits from row `write`,
|
||||
/// return true if anything changed.
|
||||
///
|
||||
/// This is used when computing transitive reachability because if
|
||||
/// you have an edge `write -> read`, because in that case
|
||||
/// `write` can reach everything that `read` can (and
|
||||
/// potentially more).
|
||||
pub fn merge(&mut self, read: R, write: R) -> bool {
|
||||
if read == write || self.row(read).is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.ensure_row(write);
|
||||
if let (Some(bitvec_read), Some(bitvec_write)) = self.rows.pick2_mut(read, write) {
|
||||
bitvec_write.merge(bitvec_read)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge a row, `from`, into the `into` row.
|
||||
pub fn merge_into(&mut self, into: R, from: &BitArray<C>) -> bool {
|
||||
self.ensure_row(into).merge(from)
|
||||
}
|
||||
|
||||
/// Add all bits to the given row.
|
||||
pub fn add_all(&mut self, row: R) {
|
||||
self.ensure_row(row).insert_all();
|
||||
}
|
||||
|
||||
pub fn rows(&self) -> impl Iterator<Item = R> {
|
||||
self.rows.indices()
|
||||
}
|
||||
|
||||
/// Iterates through all the columns set to true in a given row of
|
||||
/// the matrix.
|
||||
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
|
||||
self.row(row).into_iter().flat_map(|r| r.iter())
|
||||
}
|
||||
|
||||
pub fn row(&self, row: R) -> Option<&BitArray<C>> {
|
||||
if let Some(Some(row)) = self.rows.get(row) {
|
||||
Some(row)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_words<C: Idx>(elements: C) -> usize {
|
||||
(elements.index() + WORD_BITS - 1) / WORD_BITS
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn word_mask<C: Idx>(index: C) -> (usize, Word) {
|
||||
let index = index.index();
|
||||
let word = index / WORD_BITS;
|
||||
let mask = 1 << (index % WORD_BITS);
|
||||
(word, mask)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_above() {
|
||||
use std::cmp;
|
||||
|
||||
for i in 0..256 {
|
||||
let mut idx_buf: BitArray<usize> = BitArray::new_filled(128);
|
||||
idx_buf.clear_above(i);
|
||||
|
||||
let elems: Vec<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (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<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (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<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (0..i).collect();
|
||||
assert_eq!(elems, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitvec_iter_works() {
|
||||
let mut bitvec: BitArray<usize> = BitArray::new(100);
|
||||
bitvec.insert(1);
|
||||
bitvec.insert(10);
|
||||
bitvec.insert(19);
|
||||
bitvec.insert(62);
|
||||
bitvec.insert(63);
|
||||
bitvec.insert(64);
|
||||
bitvec.insert(65);
|
||||
bitvec.insert(66);
|
||||
bitvec.insert(99);
|
||||
assert_eq!(
|
||||
bitvec.iter().collect::<Vec<_>>(),
|
||||
[1, 10, 19, 62, 63, 64, 65, 66, 99]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitvec_iter_works_2() {
|
||||
let mut bitvec: BitArray<usize> = BitArray::new(319);
|
||||
bitvec.insert(0);
|
||||
bitvec.insert(127);
|
||||
bitvec.insert(191);
|
||||
bitvec.insert(255);
|
||||
bitvec.insert(319);
|
||||
assert_eq!(bitvec.iter().collect::<Vec<_>>(), [0, 127, 191, 255, 319]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn union_two_vecs() {
|
||||
let mut vec1: BitArray<usize> = BitArray::new(65);
|
||||
let mut vec2: BitArray<usize> = BitArray::new(65);
|
||||
assert!(vec1.insert(3));
|
||||
assert!(!vec1.insert(3));
|
||||
assert!(vec2.insert(5));
|
||||
assert!(vec2.insert(64));
|
||||
assert!(vec1.merge(&vec2));
|
||||
assert!(!vec1.merge(&vec2));
|
||||
assert!(vec1.contains(3));
|
||||
assert!(!vec1.contains(4));
|
||||
assert!(vec1.contains(5));
|
||||
assert!(!vec1.contains(63));
|
||||
assert!(vec1.contains(64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grow() {
|
||||
let mut vec1: BitVector<usize> = BitVector::with_capacity(65);
|
||||
for index in 0..65 {
|
||||
assert!(vec1.insert(index));
|
||||
assert!(!vec1.insert(index));
|
||||
}
|
||||
vec1.grow(128);
|
||||
|
||||
// Check if the bits set before growing are still set
|
||||
for index in 0..65 {
|
||||
assert!(vec1.contains(index));
|
||||
}
|
||||
|
||||
// Check if the new bits are all un-set
|
||||
for index in 65..128 {
|
||||
assert!(!vec1.contains(index));
|
||||
}
|
||||
|
||||
// Check that we can set all new bits without running out of bounds
|
||||
for index in 65..128 {
|
||||
assert!(vec1.insert(index));
|
||||
assert!(!vec1.insert(index));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matrix_intersection() {
|
||||
let mut vec1: BitMatrix<usize, usize> = BitMatrix::new(200, 200);
|
||||
|
||||
// (*) Elements reachable from both 2 and 65.
|
||||
|
||||
vec1.add(2, 3);
|
||||
vec1.add(2, 6);
|
||||
vec1.add(2, 10); // (*)
|
||||
vec1.add(2, 64); // (*)
|
||||
vec1.add(2, 65);
|
||||
vec1.add(2, 130);
|
||||
vec1.add(2, 160); // (*)
|
||||
|
||||
vec1.add(64, 133);
|
||||
|
||||
vec1.add(65, 2);
|
||||
vec1.add(65, 8);
|
||||
vec1.add(65, 10); // (*)
|
||||
vec1.add(65, 64); // (*)
|
||||
vec1.add(65, 68);
|
||||
vec1.add(65, 133);
|
||||
vec1.add(65, 160); // (*)
|
||||
|
||||
let intersection = vec1.intersection(2, 64);
|
||||
assert!(intersection.is_empty());
|
||||
|
||||
let intersection = vec1.intersection(2, 65);
|
||||
assert_eq!(intersection, &[10, 64, 160]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matrix_iter() {
|
||||
let mut matrix: BitMatrix<usize, usize> = BitMatrix::new(64, 100);
|
||||
matrix.add(3, 22);
|
||||
matrix.add(3, 75);
|
||||
matrix.add(2, 99);
|
||||
matrix.add(4, 0);
|
||||
matrix.merge(3, 5);
|
||||
|
||||
let expected = [99];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(2) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [22, 75];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(3) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [0];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(4) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [22, 75];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(5) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sparse_matrix_iter() {
|
||||
let mut matrix: SparseBitMatrix<usize, usize> = SparseBitMatrix::new(100);
|
||||
matrix.add(3, 22);
|
||||
matrix.add(3, 75);
|
||||
matrix.add(2, 99);
|
||||
matrix.add(4, 0);
|
||||
matrix.merge(3, 5);
|
||||
|
||||
let expected = [99];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(2) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [22, 75];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(3) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [0];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(4) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
|
||||
let expected = [22, 75];
|
||||
let mut iter = expected.iter();
|
||||
for i in matrix.iter(5) {
|
||||
let j = *iter.next().unwrap();
|
||||
assert_eq!(i, j);
|
||||
}
|
||||
assert!(iter.next().is_none());
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
//! the field `next_edge`). Each of those fields is an array that should
|
||||
//! be indexed by the direction (see the type `Direction`).
|
||||
|
||||
use bitvec::BitArray;
|
||||
use bit_set::BitSet;
|
||||
use std::fmt::Debug;
|
||||
use std::usize;
|
||||
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
|
||||
|
@ -266,7 +266,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
|
|||
direction: Direction,
|
||||
entry_node: NodeIndex,
|
||||
) -> Vec<NodeIndex> {
|
||||
let mut visited = BitArray::new(self.len_nodes());
|
||||
let mut visited = BitSet::new_empty(self.len_nodes());
|
||||
let mut stack = vec![];
|
||||
let mut result = Vec::with_capacity(self.len_nodes());
|
||||
let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
|
||||
|
@ -348,7 +348,7 @@ where
|
|||
{
|
||||
graph: &'g Graph<N, E>,
|
||||
stack: Vec<NodeIndex>,
|
||||
visited: BitArray<usize>,
|
||||
visited: BitSet<usize>,
|
||||
direction: Direction,
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
|
|||
start_node: NodeIndex,
|
||||
direction: Direction,
|
||||
) -> Self {
|
||||
let mut visited = BitArray::new(graph.len_nodes());
|
||||
let mut visited = BitSet::new_empty(graph.len_nodes());
|
||||
visited.insert(start_node.node_id());
|
||||
DepthFirstTraversal {
|
||||
graph,
|
||||
|
|
|
@ -1,358 +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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use array_vec::ArrayVec;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
use bitvec::{bitwise, BitArray, BitIter, Intersect, Subtract, Union, Word, WORD_BITS};
|
||||
use indexed_vec::Idx;
|
||||
use rustc_serialize;
|
||||
|
||||
/// This is implemented by all the index sets so that IdxSet::union() can be
|
||||
/// passed any type of index set.
|
||||
pub trait UnionIntoIdxSet<T: Idx> {
|
||||
// Performs `other = other | self`.
|
||||
fn union_into(&self, other: &mut IdxSet<T>) -> bool;
|
||||
}
|
||||
|
||||
/// This is implemented by all the index sets so that IdxSet::subtract() can be
|
||||
/// passed any type of index set.
|
||||
pub trait SubtractFromIdxSet<T: Idx> {
|
||||
// Performs `other = other - self`.
|
||||
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool;
|
||||
}
|
||||
|
||||
/// Represents a set of some element type E, where each E is identified by some
|
||||
/// unique index type `T`.
|
||||
///
|
||||
/// In other words, `T` is the type used to index into the bitvector
|
||||
/// this type uses to represent the set of object it holds.
|
||||
///
|
||||
/// The representation is dense, using one bit per possible element.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct IdxSet<T: Idx>(BitArray<T>);
|
||||
|
||||
impl<T: Idx> rustc_serialize::Encodable for IdxSet<T> {
|
||||
fn encode<E: rustc_serialize::Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
|
||||
self.0.encode(encoder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> rustc_serialize::Decodable for IdxSet<T> {
|
||||
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<IdxSet<T>, D::Error> {
|
||||
Ok(IdxSet(rustc_serialize::Decodable::decode(d)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> fmt::Debug for IdxSet<T> {
|
||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||
w.debug_list()
|
||||
.entries(self.iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> IdxSet<T> {
|
||||
/// 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 {
|
||||
IdxSet(BitArray::new_filled(domain_size))
|
||||
}
|
||||
|
||||
/// Duplicates as a hybrid set.
|
||||
pub fn to_hybrid(&self) -> HybridIdxSet<T> {
|
||||
// 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.words().len() * WORD_BITS;
|
||||
|
||||
// Note: we currently don't bother trying to make a Sparse set.
|
||||
HybridIdxSet::Dense(self.to_owned(), domain_size)
|
||||
}
|
||||
|
||||
/// Removes all elements
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear();
|
||||
}
|
||||
|
||||
/// Sets all elements up to `domain_size`
|
||||
pub fn set_up_to(&mut self, domain_size: usize) {
|
||||
self.0.set_up_to(domain_size);
|
||||
}
|
||||
|
||||
/// Removes `elem` from the set `self`; returns true iff this changed `self`.
|
||||
pub fn remove(&mut self, elem: &T) -> bool {
|
||||
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.0.insert(*elem)
|
||||
}
|
||||
|
||||
/// Returns true iff set `self` contains `elem`.
|
||||
pub fn contains(&self, elem: &T) -> bool {
|
||||
self.0.contains(*elem)
|
||||
}
|
||||
|
||||
pub fn words(&self) -> &[Word] {
|
||||
self.0.words()
|
||||
}
|
||||
|
||||
pub fn words_mut(&mut self) -> &mut [Word] {
|
||||
self.0.words_mut()
|
||||
}
|
||||
|
||||
/// Efficiently overwrite `self` with `other`. Panics if `self` and `other`
|
||||
/// don't have the same length.
|
||||
pub fn overwrite(&mut self, other: &IdxSet<T>) {
|
||||
self.words_mut().clone_from_slice(other.words());
|
||||
}
|
||||
|
||||
/// Set `self = self | other` and return true if `self` changed
|
||||
/// (i.e., if new bits were added).
|
||||
pub fn union(&mut self, other: &impl UnionIntoIdxSet<T>) -> bool {
|
||||
other.union_into(self)
|
||||
}
|
||||
|
||||
/// Set `self = self - other` and return true if `self` changed.
|
||||
/// (i.e., if any bits were removed).
|
||||
pub fn subtract(&mut self, other: &impl SubtractFromIdxSet<T>) -> bool {
|
||||
other.subtract_from(self)
|
||||
}
|
||||
|
||||
/// Set `self = self & other` and return true if `self` changed.
|
||||
/// (i.e., if any bits were removed).
|
||||
pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
|
||||
bitwise(self.words_mut(), other.words(), &Intersect)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> BitIter<T> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> UnionIntoIdxSet<T> for IdxSet<T> {
|
||||
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
|
||||
bitwise(other.words_mut(), self.words(), &Union)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> SubtractFromIdxSet<T> for IdxSet<T> {
|
||||
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
|
||||
bitwise(other.words_mut(), self.words(), &Subtract)
|
||||
}
|
||||
}
|
||||
|
||||
const SPARSE_MAX: usize = 8;
|
||||
|
||||
/// A sparse index set with a maximum of SPARSE_MAX elements. Used by
|
||||
/// HybridIdxSet; do not use directly.
|
||||
///
|
||||
/// The elements are stored as an unsorted vector with no duplicates.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SparseIdxSet<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
|
||||
|
||||
impl<T: Idx> SparseIdxSet<T> {
|
||||
fn new() -> Self {
|
||||
SparseIdxSet(ArrayVec::new())
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn contains(&self, elem: &T) -> bool {
|
||||
self.0.contains(elem)
|
||||
}
|
||||
|
||||
fn add(&mut self, elem: &T) -> bool {
|
||||
// Ensure there are no duplicates.
|
||||
if self.0.contains(elem) {
|
||||
false
|
||||
} else {
|
||||
self.0.push(*elem);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, elem: &T) -> bool {
|
||||
if let Some(i) = self.0.iter().position(|e| e == elem) {
|
||||
// Swap the found element to the end, then pop it.
|
||||
let len = self.0.len();
|
||||
self.0.swap(i, len - 1);
|
||||
self.0.pop();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn to_dense(&self, domain_size: usize) -> IdxSet<T> {
|
||||
let mut dense = IdxSet::new_empty(domain_size);
|
||||
for elem in self.0.iter() {
|
||||
dense.add(elem);
|
||||
}
|
||||
dense
|
||||
}
|
||||
|
||||
fn iter(&self) -> slice::Iter<T> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> UnionIntoIdxSet<T> for SparseIdxSet<T> {
|
||||
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
|
||||
let mut changed = false;
|
||||
for elem in self.iter() {
|
||||
changed |= other.add(&elem);
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> SubtractFromIdxSet<T> for SparseIdxSet<T> {
|
||||
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
|
||||
let mut changed = false;
|
||||
for elem in self.iter() {
|
||||
changed |= other.remove(&elem);
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// large `domain_size`, and are cleared frequently.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum HybridIdxSet<T: Idx> {
|
||||
Sparse(SparseIdxSet<T>, usize),
|
||||
Dense(IdxSet<T>, usize),
|
||||
}
|
||||
|
||||
impl<T: Idx> HybridIdxSet<T> {
|
||||
pub fn new_empty(domain_size: usize) -> Self {
|
||||
HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
let domain_size = match *self {
|
||||
HybridIdxSet::Sparse(_, size) => size,
|
||||
HybridIdxSet::Dense(_, size) => size,
|
||||
};
|
||||
*self = HybridIdxSet::new_empty(domain_size);
|
||||
}
|
||||
|
||||
/// Returns true iff set `self` contains `elem`.
|
||||
pub fn contains(&self, elem: &T) -> bool {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) => sparse.contains(elem),
|
||||
HybridIdxSet::Dense(dense, _) => dense.contains(elem),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds `elem` to the set `self`.
|
||||
pub fn add(&mut self, elem: &T) -> bool {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
|
||||
// The set is sparse and has space for `elem`.
|
||||
sparse.add(elem)
|
||||
}
|
||||
HybridIdxSet::Sparse(sparse, _) if sparse.contains(elem) => {
|
||||
// The set is sparse and does not have space for `elem`, but
|
||||
// that doesn't matter because `elem` is already present.
|
||||
false
|
||||
}
|
||||
HybridIdxSet::Sparse(_, _) => {
|
||||
// The set is sparse and full. Convert to a dense set.
|
||||
//
|
||||
// FIXME: This code is awful, but I can't work out how else to
|
||||
// appease the borrow checker.
|
||||
let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0);
|
||||
match mem::replace(self, dummy) {
|
||||
HybridIdxSet::Sparse(sparse, domain_size) => {
|
||||
let mut dense = sparse.to_dense(domain_size);
|
||||
let changed = dense.add(elem);
|
||||
assert!(changed);
|
||||
mem::replace(self, HybridIdxSet::Dense(dense, domain_size));
|
||||
changed
|
||||
}
|
||||
_ => panic!("impossible"),
|
||||
}
|
||||
}
|
||||
|
||||
HybridIdxSet::Dense(dense, _) => dense.add(elem),
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes `elem` from the set `self`.
|
||||
pub fn remove(&mut self, elem: &T) -> bool {
|
||||
// Note: we currently don't bother going from Dense back to Sparse.
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) => sparse.remove(elem),
|
||||
HybridIdxSet::Dense(dense, _) => dense.remove(elem),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to a dense set, consuming itself in the process.
|
||||
pub fn to_dense(self) -> IdxSet<T> {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size),
|
||||
HybridIdxSet::Dense(dense, _) => dense,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iteration order is unspecified.
|
||||
pub fn iter(&self) -> HybridIter<T> {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
|
||||
HybridIdxSet::Dense(dense, _) => HybridIter::Dense(dense.iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> UnionIntoIdxSet<T> for HybridIdxSet<T> {
|
||||
fn union_into(&self, other: &mut IdxSet<T>) -> bool {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other),
|
||||
HybridIdxSet::Dense(dense, _) => dense.union_into(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> SubtractFromIdxSet<T> for HybridIdxSet<T> {
|
||||
fn subtract_from(&self, other: &mut IdxSet<T>) -> bool {
|
||||
match self {
|
||||
HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other),
|
||||
HybridIdxSet::Dense(dense, _) => dense.subtract_from(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum HybridIter<'a, T: Idx> {
|
||||
Sparse(slice::Iter<'a, T>),
|
||||
Dense(BitIter<'a, T>),
|
||||
}
|
||||
|
||||
impl<'a, T: Idx> Iterator for HybridIter<'a, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
match self {
|
||||
HybridIter::Sparse(sparse) => sparse.next().map(|e| *e),
|
||||
HybridIter::Dense(dense) => dense.next(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,12 +62,11 @@ pub use rustc_serialize::hex::ToHex;
|
|||
pub mod svh;
|
||||
pub mod array_vec;
|
||||
pub mod base_n;
|
||||
pub mod bitvec;
|
||||
pub mod bit_set;
|
||||
pub mod const_cstr;
|
||||
pub mod flock;
|
||||
pub mod fx;
|
||||
pub mod graph;
|
||||
pub mod indexed_set;
|
||||
pub mod indexed_vec;
|
||||
pub mod obligation_forest;
|
||||
pub mod owning_ref;
|
||||
|
|
|
@ -457,7 +457,7 @@ impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<
|
|||
}
|
||||
|
||||
|
||||
impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSet<I>
|
||||
impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::bit_set::BitSet<I>
|
||||
{
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
ctx: &mut CTX,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use bitvec::BitMatrix;
|
||||
use bit_set::BitMatrix;
|
||||
use fx::FxHashMap;
|
||||
use sync::Lock;
|
||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
|
@ -279,7 +279,7 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
|
|||
//
|
||||
// This same algorithm is used in `parents` below.
|
||||
|
||||
let mut candidates = closure.intersection(a.0, b.0); // (1)
|
||||
let mut candidates = closure.intersect_rows(a.0, b.0); // (1)
|
||||
pare_down(&mut candidates, closure); // (2)
|
||||
candidates.reverse(); // (3a)
|
||||
pare_down(&mut candidates, closure); // (3b)
|
||||
|
@ -321,7 +321,7 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
|
|||
// with a slight tweak. In the case where `a R a`, we remove
|
||||
// that from the set of candidates.
|
||||
let ancestors = self.with_closure(|closure| {
|
||||
let mut ancestors = closure.intersection(a.0, a.0);
|
||||
let mut ancestors = closure.intersect_rows(a.0, a.0);
|
||||
|
||||
// Remove anything that can reach `a`. If this is a
|
||||
// reflexive relation, this will include `a` itself.
|
||||
|
@ -366,10 +366,10 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
|
|||
changed = false;
|
||||
for edge in &self.edges {
|
||||
// add an edge from S -> T
|
||||
changed |= matrix.add(edge.source.0, edge.target.0);
|
||||
changed |= matrix.insert(edge.source.0, edge.target.0);
|
||||
|
||||
// add all outgoing edges from T into S
|
||||
changed |= matrix.merge(edge.target.0, edge.source.0);
|
||||
changed |= matrix.union_rows(edge.target.0, edge.source.0);
|
||||
}
|
||||
}
|
||||
matrix
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use indexed_set::IdxSet;
|
||||
use bit_set::BitSet;
|
||||
use indexed_vec::Idx;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use std::collections::VecDeque;
|
|||
/// and also use a bit set to track occupancy.
|
||||
pub struct WorkQueue<T: Idx> {
|
||||
deque: VecDeque<T>,
|
||||
set: IdxSet<T>,
|
||||
set: BitSet<T>,
|
||||
}
|
||||
|
||||
impl<T: Idx> WorkQueue<T> {
|
||||
|
@ -29,7 +29,7 @@ impl<T: Idx> WorkQueue<T> {
|
|||
pub fn with_all(len: usize) -> Self {
|
||||
WorkQueue {
|
||||
deque: (0..len).map(T::new).collect(),
|
||||
set: IdxSet::new_filled(len),
|
||||
set: BitSet::new_filled(len),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,14 +38,14 @@ impl<T: Idx> WorkQueue<T> {
|
|||
pub fn with_none(len: usize) -> Self {
|
||||
WorkQueue {
|
||||
deque: VecDeque::with_capacity(len),
|
||||
set: IdxSet::new_empty(len),
|
||||
set: BitSet::new_empty(len),
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to enqueue `element` in the work queue. Returns false if it was already present.
|
||||
#[inline]
|
||||
pub fn insert(&mut self, element: T) -> bool {
|
||||
if self.set.add(&element) {
|
||||
if self.set.insert(element) {
|
||||
self.deque.push_back(element);
|
||||
true
|
||||
} else {
|
||||
|
@ -57,7 +57,7 @@ impl<T: Idx> WorkQueue<T> {
|
|||
#[inline]
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if let Some(element) = self.deque.pop_front() {
|
||||
self.set.remove(&element);
|
||||
self.set.remove(element);
|
||||
Some(element)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -42,7 +42,7 @@ use syntax::edition::Edition;
|
|||
use syntax::parse::source_file_to_stream;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{Span, NO_EXPANSION, FileName};
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc::hir;
|
||||
|
||||
macro_rules! provide {
|
||||
|
@ -141,7 +141,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
|||
mir
|
||||
}
|
||||
mir_const_qualif => {
|
||||
(cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSet::new_empty(0)))
|
||||
(cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::new_empty(0)))
|
||||
}
|
||||
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
|
||||
inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc::mir::{self, Location, Mir, Place, Local};
|
|||
use rustc::ty::{Region, TyCtxt};
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
|
@ -102,7 +102,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
|||
|
||||
crate enum LocalsStateAtExit {
|
||||
AllAreInvalidated,
|
||||
SomeAreInvalidated { has_storage_dead_or_moved: BitArray<Local> }
|
||||
SomeAreInvalidated { has_storage_dead_or_moved: BitSet<Local> }
|
||||
}
|
||||
|
||||
impl LocalsStateAtExit {
|
||||
|
@ -111,7 +111,7 @@ impl LocalsStateAtExit {
|
|||
mir: &Mir<'tcx>,
|
||||
move_data: &MoveData<'tcx>
|
||||
) -> Self {
|
||||
struct HasStorageDead(BitArray<Local>);
|
||||
struct HasStorageDead(BitSet<Local>);
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for HasStorageDead {
|
||||
fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
|
||||
|
@ -124,7 +124,7 @@ impl LocalsStateAtExit {
|
|||
if locals_are_invalidated_at_exit {
|
||||
LocalsStateAtExit::AllAreInvalidated
|
||||
} else {
|
||||
let mut has_storage_dead = HasStorageDead(BitArray::new(mir.local_decls.len()));
|
||||
let mut has_storage_dead = HasStorageDead(BitSet::new_empty(mir.local_decls.len()));
|
||||
has_storage_dead.visit_mir(mir);
|
||||
let mut has_storage_dead_or_moved = has_storage_dead.0;
|
||||
for move_out in &move_data.moves {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use rustc::mir::{BasicBlock, Location};
|
||||
use rustc::ty::RegionVid;
|
||||
use rustc_data_structures::bitvec::BitIter;
|
||||
use rustc_data_structures::bit_set::BitIter;
|
||||
|
||||
use borrow_check::location::LocationIndex;
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ use rustc::ty::query::Providers;
|
|||
use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
|
||||
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -167,7 +167,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
_ => Some(tcx.hir.body_owned_by(id)),
|
||||
};
|
||||
|
||||
let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
|
||||
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
|
||||
let mut flow_inits = FlowAtLocation::new(do_dataflow(
|
||||
tcx,
|
||||
mir,
|
||||
|
@ -1595,7 +1595,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// Check if any of the initializiations of `local` have happened yet:
|
||||
let mpi = self.move_data.rev_lookup.find_local(local);
|
||||
let init_indices = &self.move_data.init_path_map[mpi];
|
||||
let first_init_index = init_indices.iter().find(|ii| flow_state.ever_inits.contains(ii));
|
||||
let first_init_index = init_indices.iter().find(|&ii| flow_state.ever_inits.contains(*ii));
|
||||
if let Some(&init_index) = first_init_index {
|
||||
// And, if so, report an error.
|
||||
let init = &self.move_data.inits[init_index];
|
||||
|
@ -1653,7 +1653,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
|
||||
match self.move_path_closest_to(place_span.0) {
|
||||
Ok(mpi) => {
|
||||
if maybe_uninits.contains(&mpi) {
|
||||
if maybe_uninits.contains(mpi) {
|
||||
self.report_use_of_moved_or_uninitialized(
|
||||
context,
|
||||
desired_action,
|
||||
|
@ -1969,7 +1969,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// keyword, since the mutation may be a possible reassignment.
|
||||
let mpi = self.move_data.rev_lookup.find_local(*local);
|
||||
let ii = &self.move_data.init_path_map[mpi];
|
||||
for index in ii {
|
||||
for &index in ii {
|
||||
if flow_state.ever_inits.contains(index) {
|
||||
self.used_mut.insert(*local);
|
||||
break;
|
||||
|
|
|
@ -26,8 +26,8 @@ use rustc::mir::{
|
|||
};
|
||||
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::util::common;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_errors::{DiagnosticBuilder, Diagnostic};
|
||||
|
||||
|
@ -477,7 +477,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// SCC. For each SCC, we visit its successors and compute
|
||||
// their values, then we union all those values to get our
|
||||
// own.
|
||||
let visited = &mut IdxSet::new_empty(self.constraint_sccs.num_sccs());
|
||||
let visited = &mut BitSet::new_empty(self.constraint_sccs.num_sccs());
|
||||
for scc_index in self.constraint_sccs.all_sccs() {
|
||||
self.propagate_constraint_sccs_if_new(scc_index, visited);
|
||||
}
|
||||
|
@ -487,9 +487,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn propagate_constraint_sccs_if_new(
|
||||
&mut self,
|
||||
scc_a: ConstraintSccIndex,
|
||||
visited: &mut IdxSet<ConstraintSccIndex>,
|
||||
visited: &mut BitSet<ConstraintSccIndex>,
|
||||
) {
|
||||
if visited.add(&scc_a) {
|
||||
if visited.insert(scc_a) {
|
||||
self.propagate_constraint_sccs_new(scc_a, visited);
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn propagate_constraint_sccs_new(
|
||||
&mut self,
|
||||
scc_a: ConstraintSccIndex,
|
||||
visited: &mut IdxSet<ConstraintSccIndex>,
|
||||
visited: &mut BitSet<ConstraintSccIndex>,
|
||||
) {
|
||||
let constraint_sccs = self.constraint_sccs.clone();
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use rustc::mir::{BasicBlock, Location, Mir};
|
||||
use rustc::ty::{self, RegionVid};
|
||||
use rustc_data_structures::bitvec::{BitArray, SparseBitMatrix};
|
||||
use rustc_data_structures::bit_set::{BitSet, SparseBitMatrix};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use std::fmt::Debug;
|
||||
|
@ -179,19 +179,19 @@ impl<N: Idx> LivenessValues<N> {
|
|||
crate fn add_element(&mut self, row: N, location: Location) -> bool {
|
||||
debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
|
||||
let index = self.elements.point_from_location(location);
|
||||
self.points.add(row, index)
|
||||
self.points.insert(row, index)
|
||||
}
|
||||
|
||||
/// Adds all the elements in the given bit array into the given
|
||||
/// region. Returns true if any of them are newly added.
|
||||
crate fn add_elements(&mut self, row: N, locations: &BitArray<PointIndex>) -> bool {
|
||||
crate fn add_elements(&mut self, row: N, locations: &BitSet<PointIndex>) -> bool {
|
||||
debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
|
||||
self.points.merge_into(row, locations)
|
||||
self.points.union_into_row(row, locations)
|
||||
}
|
||||
|
||||
/// Adds all the control-flow points to the values for `r`.
|
||||
crate fn add_all_points(&mut self, row: N) {
|
||||
self.points.add_all(row);
|
||||
self.points.insert_all_into_row(row);
|
||||
}
|
||||
|
||||
/// True if the region `r` contains the given element.
|
||||
|
@ -270,15 +270,15 @@ impl<N: Idx> RegionValues<N> {
|
|||
|
||||
/// Adds all the control-flow points to the values for `r`.
|
||||
crate fn add_all_points(&mut self, r: N) {
|
||||
self.points.add_all(r);
|
||||
self.points.insert_all_into_row(r);
|
||||
}
|
||||
|
||||
/// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
|
||||
/// r_from`).
|
||||
crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
|
||||
self.points.merge(r_from, r_to)
|
||||
| self.free_regions.merge(r_from, r_to)
|
||||
| self.placeholders.merge(r_from, r_to)
|
||||
self.points.union_rows(r_from, r_to)
|
||||
| self.free_regions.union_rows(r_from, r_to)
|
||||
| self.placeholders.union_rows(r_from, r_to)
|
||||
}
|
||||
|
||||
/// True if the region `r` contains the given element.
|
||||
|
@ -291,7 +291,7 @@ impl<N: Idx> RegionValues<N> {
|
|||
/// the region `to` in `self`.
|
||||
crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
|
||||
if let Some(set) = values.points.row(from) {
|
||||
self.points.merge_into(to, set);
|
||||
self.points.union_into_row(to, set);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ impl<N: Idx> RegionValues<N> {
|
|||
crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
|
||||
if let Some(sub_row) = self.points.row(sub_region) {
|
||||
if let Some(sup_row) = self.points.row(sup_region) {
|
||||
sup_row.contains_all(sub_row)
|
||||
sup_row.superset(sub_row)
|
||||
} else {
|
||||
// sup row is empty, so sub row must be empty
|
||||
sub_row.is_empty()
|
||||
|
@ -378,7 +378,7 @@ crate trait ToElementIndex: Debug + Copy {
|
|||
impl ToElementIndex for Location {
|
||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
||||
let index = values.elements.point_from_location(self);
|
||||
values.points.add(row, index)
|
||||
values.points.insert(row, index)
|
||||
}
|
||||
|
||||
fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
|
||||
|
@ -389,7 +389,7 @@ impl ToElementIndex for Location {
|
|||
|
||||
impl ToElementIndex for RegionVid {
|
||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
||||
values.free_regions.add(row, self)
|
||||
values.free_regions.insert(row, self)
|
||||
}
|
||||
|
||||
fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
|
||||
|
@ -400,7 +400,7 @@ impl ToElementIndex for RegionVid {
|
|||
impl ToElementIndex for ty::UniverseIndex {
|
||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
||||
let index = PlaceholderIndex::new(self.as_usize() - 1);
|
||||
values.placeholders.add(row, index)
|
||||
values.placeholders.insert(row, index)
|
||||
}
|
||||
|
||||
fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
|
||||
|
|
|
@ -22,7 +22,7 @@ use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
|
|||
use rustc::traits::query::type_op::outlives::DropckOutlives;
|
||||
use rustc::traits::query::type_op::TypeOp;
|
||||
use rustc::ty::{Ty, TypeFoldable};
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use std::rc::Rc;
|
||||
use util::liveness::LiveVariableMap;
|
||||
|
@ -121,16 +121,16 @@ where
|
|||
cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>,
|
||||
|
||||
/// Set of points that define the current local.
|
||||
defs: BitArray<PointIndex>,
|
||||
defs: BitSet<PointIndex>,
|
||||
|
||||
/// Points where the current variable is "use live" -- meaning
|
||||
/// that there is a future "full use" that may use its value.
|
||||
use_live_at: BitArray<PointIndex>,
|
||||
use_live_at: BitSet<PointIndex>,
|
||||
|
||||
/// Points where the current variable is "drop live" -- meaning
|
||||
/// that there is no future "full use" that may use its value, but
|
||||
/// there is a future drop.
|
||||
drop_live_at: BitArray<PointIndex>,
|
||||
drop_live_at: BitSet<PointIndex>,
|
||||
|
||||
/// Locations where drops may occur.
|
||||
drop_locations: Vec<Location>,
|
||||
|
@ -144,9 +144,9 @@ impl LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> {
|
|||
let num_points = cx.elements.num_points();
|
||||
LivenessResults {
|
||||
cx,
|
||||
defs: BitArray::new(num_points),
|
||||
use_live_at: BitArray::new(num_points),
|
||||
drop_live_at: BitArray::new(num_points),
|
||||
defs: BitSet::new_empty(num_points),
|
||||
use_live_at: BitSet::new_empty(num_points),
|
||||
drop_live_at: BitSet::new_empty(num_points),
|
||||
drop_locations: vec![],
|
||||
stack: vec![],
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
|||
fn add_use_live_facts_for(
|
||||
&mut self,
|
||||
value: impl TypeFoldable<'tcx>,
|
||||
live_at: &BitArray<PointIndex>,
|
||||
live_at: &BitSet<PointIndex>,
|
||||
) {
|
||||
debug!("add_use_live_facts_for(value={:?})", value);
|
||||
|
||||
|
@ -465,7 +465,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
|||
dropped_local: Local,
|
||||
dropped_ty: Ty<'tcx>,
|
||||
drop_locations: &[Location],
|
||||
live_at: &BitArray<PointIndex>,
|
||||
live_at: &BitSet<PointIndex>,
|
||||
) {
|
||||
debug!(
|
||||
"add_drop_live_constraint(\
|
||||
|
@ -508,7 +508,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
|||
elements: &RegionValueElements,
|
||||
typeck: &mut TypeChecker<'_, '_, 'tcx>,
|
||||
value: impl TypeFoldable<'tcx>,
|
||||
live_at: &BitArray<PointIndex>,
|
||||
live_at: &BitSet<PointIndex>,
|
||||
) {
|
||||
debug!("make_all_regions_live(value={:?})", value);
|
||||
debug!(
|
||||
|
|
|
@ -21,7 +21,7 @@ use hair::*;
|
|||
use rustc::hir;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, CanonicalTy, Ty};
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use syntax::ast::{Name, NodeId};
|
||||
use syntax_pos::Span;
|
||||
|
@ -635,7 +635,7 @@ enum TestKind<'tcx> {
|
|||
// test the branches of enum
|
||||
Switch {
|
||||
adt_def: &'tcx ty::AdtDef,
|
||||
variants: BitArray<usize>,
|
||||
variants: BitSet<usize>,
|
||||
},
|
||||
|
||||
// test the branches of enum
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
use build::Builder;
|
||||
use build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||
use hair::*;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rustc::mir::*;
|
||||
|
@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Switch {
|
||||
adt_def: adt_def.clone(),
|
||||
variants: BitArray::new(adt_def.variants.len()),
|
||||
variants: BitSet::new_empty(adt_def.variants.len()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
pub fn add_variants_to_switch<'pat>(&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
variants: &mut BitArray<usize>)
|
||||
variants: &mut BitSet<usize>)
|
||||
-> bool
|
||||
{
|
||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
//! locations.
|
||||
|
||||
use rustc::mir::{BasicBlock, Location};
|
||||
use rustc_data_structures::bitvec::BitIter;
|
||||
use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
|
||||
use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};
|
||||
|
||||
use dataflow::{BitDenotation, BlockSets, DataflowResults};
|
||||
use dataflow::move_paths::{HasMoveData, MovePathIndex};
|
||||
|
@ -76,9 +75,9 @@ where
|
|||
BD: BitDenotation,
|
||||
{
|
||||
base_results: DataflowResults<BD>,
|
||||
curr_state: IdxSet<BD::Idx>,
|
||||
stmt_gen: HybridIdxSet<BD::Idx>,
|
||||
stmt_kill: HybridIdxSet<BD::Idx>,
|
||||
curr_state: BitSet<BD::Idx>,
|
||||
stmt_gen: HybridBitSet<BD::Idx>,
|
||||
stmt_kill: HybridBitSet<BD::Idx>,
|
||||
}
|
||||
|
||||
impl<BD> FlowAtLocation<BD>
|
||||
|
@ -105,9 +104,9 @@ where
|
|||
|
||||
pub fn new(results: DataflowResults<BD>) -> Self {
|
||||
let bits_per_block = results.sets().bits_per_block();
|
||||
let curr_state = IdxSet::new_empty(bits_per_block);
|
||||
let stmt_gen = HybridIdxSet::new_empty(bits_per_block);
|
||||
let stmt_kill = HybridIdxSet::new_empty(bits_per_block);
|
||||
let curr_state = BitSet::new_empty(bits_per_block);
|
||||
let stmt_gen = HybridBitSet::new_empty(bits_per_block);
|
||||
let stmt_kill = HybridBitSet::new_empty(bits_per_block);
|
||||
FlowAtLocation {
|
||||
base_results: results,
|
||||
curr_state: curr_state,
|
||||
|
@ -121,7 +120,7 @@ where
|
|||
self.base_results.operator()
|
||||
}
|
||||
|
||||
pub fn contains(&self, x: &BD::Idx) -> bool {
|
||||
pub fn contains(&self, x: BD::Idx) -> bool {
|
||||
self.curr_state.contains(x)
|
||||
}
|
||||
|
||||
|
@ -224,7 +223,7 @@ where
|
|||
// siblings);
|
||||
// - ~99% of the time the loop isn't reached, and this code is hot, so
|
||||
// we don't want to allocate `todo` unnecessarily.
|
||||
if self.contains(&mpi) {
|
||||
if self.contains(mpi) {
|
||||
return Some(mpi);
|
||||
}
|
||||
let move_data = self.operator().move_data();
|
||||
|
@ -236,7 +235,7 @@ where
|
|||
};
|
||||
|
||||
while let Some(mpi) = todo.pop() {
|
||||
if self.contains(&mpi) {
|
||||
if self.contains(mpi) {
|
||||
return Some(mpi);
|
||||
}
|
||||
let move_path = &move_data.move_paths[mpi];
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
use syntax::ast::NodeId;
|
||||
use rustc::mir::{BasicBlock, Mir};
|
||||
use rustc_data_structures::bitvec::bits_to_string;
|
||||
|
||||
use dot;
|
||||
use dot::IntoCow;
|
||||
|
@ -223,7 +222,7 @@ where MWF: MirWithFlowState<'tcx>,
|
|||
|
||||
// Entry
|
||||
let set = flow.sets.on_entry_set_for(i);
|
||||
write!(w, "<td>{:?}</td>", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
|
||||
write!(w, "<td>{:?}</td>", dot::escape_html(&set.to_string(bits_per_block)))?;
|
||||
|
||||
// Terminator
|
||||
write!(w, "<td>")?;
|
||||
|
|
|
@ -43,7 +43,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
|
|||
self.mir.local_decls.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
|
||||
fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
|
||||
// Nothing is borrowed on function entry
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
|
|||
|
||||
// StorageDead invalidates all borrows and raw pointers to a local
|
||||
match stmt.kind {
|
||||
StatementKind::StorageDead(l) => sets.kill(&l),
|
||||
StatementKind::StorageDead(l) => sets.kill(l),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
_in_out: &mut IdxSet<Local>,
|
||||
_in_out: &mut BitSet<Local>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
_dest_place: &mir::Place) {
|
||||
|
@ -118,7 +118,7 @@ impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
|
|||
location: Location) {
|
||||
if let Rvalue::Ref(_, _, ref place) = *rvalue {
|
||||
if let Some(local) = find_local(place) {
|
||||
self.sets.gen(&local);
|
||||
self.sets.gen(local);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,8 @@ use rustc::ty::TyCtxt;
|
|||
use rustc::ty::{RegionKind, RegionVid};
|
||||
use rustc::ty::RegionKind::ReScope;
|
||||
|
||||
use rustc_data_structures::bitvec::{BitwiseOperator, Word};
|
||||
use rustc_data_structures::bit_set::{BitSet, BitwiseOperator, Word};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
|
@ -227,7 +226,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
self.borrow_set.borrows.len() * 2
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _entry_set: &mut IdxSet<BorrowIndex>) {
|
||||
fn start_block_effect(&self, _entry_set: &mut BitSet<BorrowIndex>) {
|
||||
// no borrows of code region_scopes have been taken prior to
|
||||
// function execution, so this method has no effect on
|
||||
// `_sets`.
|
||||
|
@ -286,7 +285,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
debug!("Borrows::statement_effect_on_borrows \
|
||||
location: {:?} stmt: {:?} has empty region, killing {:?}",
|
||||
location, stmt.kind, index);
|
||||
sets.kill(&index);
|
||||
sets.kill(*index);
|
||||
return
|
||||
} else {
|
||||
debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}",
|
||||
|
@ -296,7 +295,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
|
||||
panic!("could not find BorrowIndexs for region {:?}", region);
|
||||
}).contains(&index));
|
||||
sets.gen(&index);
|
||||
sets.gen(*index);
|
||||
|
||||
// Issue #46746: Two-phase borrows handles
|
||||
// stmts of form `Tmp = &mut Borrow` ...
|
||||
|
@ -308,7 +307,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
// e.g. `box (&mut _)`. Current
|
||||
// conservative solution: force
|
||||
// immediate activation here.
|
||||
sets.gen(&index);
|
||||
sets.gen(*index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +377,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
if *scope != root_scope &&
|
||||
self.scope_tree.is_subscope_of(*scope, root_scope)
|
||||
{
|
||||
sets.kill(&borrow_index);
|
||||
sets.kill(borrow_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -399,7 +398,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
_in_out: &mut IdxSet<BorrowIndex>,
|
||||
_in_out: &mut BitSet<BorrowIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
_dest_place: &mir::Place) {
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::{self, Mir, Location};
|
||||
use rustc_data_structures::bitvec::{BitwiseOperator, Word};
|
||||
use rustc_data_structures::indexed_set::{IdxSet};
|
||||
use rustc_data_structures::bit_set::{BitSet, BitwiseOperator, Word};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
use super::MoveDataParamEnv;
|
||||
|
@ -266,8 +265,8 @@ impl<'a, 'gcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
state: DropFlagState)
|
||||
{
|
||||
match state {
|
||||
DropFlagState::Absent => sets.kill(&path),
|
||||
DropFlagState::Present => sets.gen(&path),
|
||||
DropFlagState::Absent => sets.kill(path),
|
||||
DropFlagState::Present => sets.gen(path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -277,8 +276,8 @@ impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
state: DropFlagState)
|
||||
{
|
||||
match state {
|
||||
DropFlagState::Absent => sets.gen(&path),
|
||||
DropFlagState::Present => sets.kill(&path),
|
||||
DropFlagState::Absent => sets.gen(path),
|
||||
DropFlagState::Present => sets.kill(path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,8 +287,8 @@ impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
state: DropFlagState)
|
||||
{
|
||||
match state {
|
||||
DropFlagState::Absent => sets.kill(&path),
|
||||
DropFlagState::Present => sets.gen(&path),
|
||||
DropFlagState::Absent => sets.kill(path),
|
||||
DropFlagState::Present => sets.gen(path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,12 +300,12 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
self.move_data().move_paths.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
drop_flag_effects_for_function_entry(
|
||||
self.tcx, self.mir, self.mdpe,
|
||||
|path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.add(&path);
|
||||
entry_set.insert(path);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -333,7 +332,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
in_out: &mut IdxSet<MovePathIndex>,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
dest_place: &mir::Place) {
|
||||
|
@ -341,7 +340,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
// the bits for that dest_place to 1 (initialized).
|
||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place),
|
||||
|mpi| { in_out.add(&mpi); });
|
||||
|mpi| { in_out.insert(mpi); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +352,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
|
|||
}
|
||||
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
// set all bits to 1 (uninit) before gathering counterevidence
|
||||
entry_set.set_up_to(self.bits_per_block());
|
||||
|
||||
|
@ -361,7 +360,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
|
|||
self.tcx, self.mir, self.mdpe,
|
||||
|path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.remove(&path);
|
||||
entry_set.remove(path);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -388,7 +387,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
in_out: &mut IdxSet<MovePathIndex>,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
dest_place: &mir::Place) {
|
||||
|
@ -396,7 +395,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
|
|||
// the bits for that dest_place to 0 (initialized).
|
||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place),
|
||||
|mpi| { in_out.remove(&mpi); });
|
||||
|mpi| { in_out.remove(mpi); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,14 +407,14 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc
|
|||
}
|
||||
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<MovePathIndex>) {
|
||||
entry_set.clear();
|
||||
|
||||
drop_flag_effects_for_function_entry(
|
||||
self.tcx, self.mir, self.mdpe,
|
||||
|path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
entry_set.add(&path);
|
||||
entry_set.insert(path);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -442,7 +441,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
in_out: &mut IdxSet<MovePathIndex>,
|
||||
in_out: &mut BitSet<MovePathIndex>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
dest_place: &mir::Place) {
|
||||
|
@ -450,7 +449,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc
|
|||
// the bits for that dest_place to 1 (initialized).
|
||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||
self.move_data().rev_lookup.find(dest_place),
|
||||
|mpi| { in_out.add(&mpi); });
|
||||
|mpi| { in_out.insert(mpi); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,9 +460,9 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
self.move_data().inits.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<InitIndex>) {
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<InitIndex>) {
|
||||
for arg_init in 0..self.mir.arg_count {
|
||||
entry_set.add(&InitIndex::new(arg_init));
|
||||
entry_set.insert(InitIndex::new(arg_init));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,7 +530,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
in_out: &mut IdxSet<InitIndex>,
|
||||
in_out: &mut BitSet<InitIndex>,
|
||||
call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
_dest_place: &mir::Place) {
|
||||
|
@ -545,7 +544,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
for init_index in &init_loc_map[call_loc] {
|
||||
assert!(init_index.index() < bits_per_block);
|
||||
in_out.add(init_index);
|
||||
in_out.insert(*init_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
|
|||
self.mir.local_decls.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
|
||||
fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
|
||||
// Nothing is live on function entry
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
|
|||
let stmt = &self.mir[loc.block].statements[loc.statement_index];
|
||||
|
||||
match stmt.kind {
|
||||
StatementKind::StorageLive(l) => sets.gen(&l),
|
||||
StatementKind::StorageDead(l) => sets.kill(&l),
|
||||
StatementKind::StorageLive(l) => sets.gen(l),
|
||||
StatementKind::StorageDead(l) => sets.kill(l),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn propagate_call_return(&self,
|
||||
_in_out: &mut IdxSet<Local>,
|
||||
_in_out: &mut BitSet<Local>,
|
||||
_call_bb: mir::BasicBlock,
|
||||
_dest_bb: mir::BasicBlock,
|
||||
_dest_place: &mir::Place) {
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
|
||||
use syntax::ast::{self, MetaItem};
|
||||
|
||||
use rustc_data_structures::bitvec::{bitwise, BitwiseOperator};
|
||||
use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
|
||||
use rustc_data_structures::bit_set::{bitwise, BitwiseOperator, BitSet, HybridBitSet};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::work_queue::WorkQueue;
|
||||
|
||||
|
@ -125,7 +124,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
mir: &'a Mir<'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
attributes: &[ast::Attribute],
|
||||
dead_unwinds: &IdxSet<BasicBlock>,
|
||||
dead_unwinds: &BitSet<BasicBlock>,
|
||||
bd: BD,
|
||||
p: P)
|
||||
-> DataflowResults<BD>
|
||||
|
@ -182,7 +181,7 @@ struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation
|
|||
impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
|
||||
{
|
||||
fn propagate(&mut self) {
|
||||
let mut temp = IdxSet::new_empty(self.flow_state.sets.bits_per_block);
|
||||
let mut temp = BitSet::new_empty(self.flow_state.sets.bits_per_block);
|
||||
let mut propcx = PropagationContext {
|
||||
builder: self,
|
||||
};
|
||||
|
@ -231,7 +230,7 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
|
|||
|
||||
impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation
|
||||
{
|
||||
fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
|
||||
fn walk_cfg(&mut self, in_out: &mut BitSet<BD::Idx>) {
|
||||
let mut dirty_queue: WorkQueue<mir::BasicBlock> =
|
||||
WorkQueue::with_all(self.builder.mir.basic_blocks().len());
|
||||
let mir = self.builder.mir;
|
||||
|
@ -352,7 +351,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
|
|||
analysis: &T,
|
||||
result: &DataflowResults<T>,
|
||||
mir: &Mir<'tcx>)
|
||||
-> IdxSet<T::Idx> {
|
||||
-> BitSet<T::Idx> {
|
||||
let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
|
||||
let mut kill_set = on_entry.to_hybrid();
|
||||
let mut gen_set = kill_set.clone();
|
||||
|
@ -385,7 +384,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
|
|||
pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
|
||||
{
|
||||
flow_state: DataflowState<O>,
|
||||
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
|
||||
dead_unwinds: &'a BitSet<mir::BasicBlock>,
|
||||
mir: &'a Mir<'tcx>,
|
||||
}
|
||||
|
||||
|
@ -426,7 +425,7 @@ pub struct DataflowState<O: BitDenotation>
|
|||
impl<O: BitDenotation> DataflowState<O> {
|
||||
pub(crate) fn interpret_set<'c, P>(&self,
|
||||
o: &'c O,
|
||||
set: &IdxSet<O::Idx>,
|
||||
set: &BitSet<O::Idx>,
|
||||
render_idx: &P)
|
||||
-> Vec<DebugFormatted>
|
||||
where P: Fn(&O, O::Idx) -> DebugFormatted
|
||||
|
@ -436,7 +435,7 @@ impl<O: BitDenotation> DataflowState<O> {
|
|||
|
||||
pub(crate) fn interpret_hybrid_set<'c, P>(&self,
|
||||
o: &'c O,
|
||||
set: &HybridIdxSet<O::Idx>,
|
||||
set: &HybridBitSet<O::Idx>,
|
||||
render_idx: &P)
|
||||
-> Vec<DebugFormatted>
|
||||
where P: Fn(&O, O::Idx) -> DebugFormatted
|
||||
|
@ -451,21 +450,21 @@ pub struct AllSets<E: Idx> {
|
|||
bits_per_block: usize,
|
||||
|
||||
/// For each block, bits valid on entry to the block.
|
||||
on_entry_sets: Vec<IdxSet<E>>,
|
||||
on_entry_sets: Vec<BitSet<E>>,
|
||||
|
||||
/// For each block, bits generated by executing the statements +
|
||||
/// terminator in the block -- with one caveat. In particular, for
|
||||
/// *call terminators*, the effect of storing the destination is
|
||||
/// not included, since that only takes effect on the **success**
|
||||
/// edge (and not the unwind edge).
|
||||
gen_sets: Vec<HybridIdxSet<E>>,
|
||||
gen_sets: Vec<HybridBitSet<E>>,
|
||||
|
||||
/// For each block, bits killed by executing the statements +
|
||||
/// terminator in the block -- with one caveat. In particular, for
|
||||
/// *call terminators*, the effect of storing the destination is
|
||||
/// not included, since that only takes effect on the **success**
|
||||
/// edge (and not the unwind edge).
|
||||
kill_sets: Vec<HybridIdxSet<E>>,
|
||||
kill_sets: Vec<HybridBitSet<E>>,
|
||||
}
|
||||
|
||||
/// Triple of sets associated with a given block.
|
||||
|
@ -485,20 +484,20 @@ pub struct AllSets<E: Idx> {
|
|||
#[derive(Debug)]
|
||||
pub struct BlockSets<'a, E: Idx> {
|
||||
/// Dataflow state immediately before control flow enters the given block.
|
||||
pub(crate) on_entry: &'a mut IdxSet<E>,
|
||||
pub(crate) on_entry: &'a mut BitSet<E>,
|
||||
|
||||
/// Bits that are set to 1 by the time we exit the given block. Hybrid
|
||||
/// because it usually contains only 0 or 1 elements.
|
||||
pub(crate) gen_set: &'a mut HybridIdxSet<E>,
|
||||
pub(crate) gen_set: &'a mut HybridBitSet<E>,
|
||||
|
||||
/// Bits that are set to 0 by the time we exit the given block. Hybrid
|
||||
/// because it usually contains only 0 or 1 elements.
|
||||
pub(crate) kill_set: &'a mut HybridIdxSet<E>,
|
||||
pub(crate) kill_set: &'a mut HybridBitSet<E>,
|
||||
}
|
||||
|
||||
impl<'a, E:Idx> BlockSets<'a, E> {
|
||||
fn gen(&mut self, e: &E) {
|
||||
self.gen_set.add(e);
|
||||
fn gen(&mut self, e: E) {
|
||||
self.gen_set.insert(e);
|
||||
self.kill_set.remove(e);
|
||||
}
|
||||
fn gen_all<I>(&mut self, i: I)
|
||||
|
@ -506,13 +505,13 @@ impl<'a, E:Idx> BlockSets<'a, E> {
|
|||
I::Item: Borrow<E>
|
||||
{
|
||||
for j in i {
|
||||
self.gen(j.borrow());
|
||||
self.gen(*j.borrow());
|
||||
}
|
||||
}
|
||||
|
||||
fn kill(&mut self, e: &E) {
|
||||
fn kill(&mut self, e: E) {
|
||||
self.gen_set.remove(e);
|
||||
self.kill_set.add(e);
|
||||
self.kill_set.insert(e);
|
||||
}
|
||||
|
||||
fn kill_all<I>(&mut self, i: I)
|
||||
|
@ -520,7 +519,7 @@ impl<'a, E:Idx> BlockSets<'a, E> {
|
|||
I::Item: Borrow<E>
|
||||
{
|
||||
for j in i {
|
||||
self.kill(j.borrow());
|
||||
self.kill(*j.borrow());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,13 +539,13 @@ impl<E:Idx> AllSets<E> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
|
||||
pub fn on_entry_set_for(&self, block_idx: usize) -> &BitSet<E> {
|
||||
&self.on_entry_sets[block_idx]
|
||||
}
|
||||
pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
|
||||
pub fn gen_set_for(&self, block_idx: usize) -> &HybridBitSet<E> {
|
||||
&self.gen_sets[block_idx]
|
||||
}
|
||||
pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSet<E> {
|
||||
pub fn kill_set_for(&self, block_idx: usize) -> &HybridBitSet<E> {
|
||||
&self.kill_sets[block_idx]
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +608,7 @@ pub trait BitDenotation: BitwiseOperator {
|
|||
/// these won't be accounted for correctly.
|
||||
///
|
||||
/// (For example, establishing the call arguments.)
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<Self::Idx>);
|
||||
fn start_block_effect(&self, entry_set: &mut BitSet<Self::Idx>);
|
||||
|
||||
/// Similar to `statement_effect`, except it applies
|
||||
/// *just before* the statement rather than *just after* it.
|
||||
|
@ -689,7 +688,7 @@ pub trait BitDenotation: BitwiseOperator {
|
|||
/// kill-sets associated with each edge coming out of the basic
|
||||
/// block.
|
||||
fn propagate_call_return(&self,
|
||||
in_out: &mut IdxSet<Self::Idx>,
|
||||
in_out: &mut BitSet<Self::Idx>,
|
||||
call_bb: mir::BasicBlock,
|
||||
dest_bb: mir::BasicBlock,
|
||||
dest_place: &mir::Place);
|
||||
|
@ -698,17 +697,17 @@ pub trait BitDenotation: BitwiseOperator {
|
|||
impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
||||
{
|
||||
pub fn new(mir: &'a Mir<'tcx>,
|
||||
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
|
||||
dead_unwinds: &'a BitSet<mir::BasicBlock>,
|
||||
denotation: D) -> Self where D: InitialFlow {
|
||||
let bits_per_block = denotation.bits_per_block();
|
||||
let num_blocks = mir.basic_blocks().len();
|
||||
|
||||
let on_entry_sets = if D::bottom_value() {
|
||||
vec![IdxSet::new_filled(bits_per_block); num_blocks]
|
||||
vec![BitSet::new_filled(bits_per_block); num_blocks]
|
||||
} else {
|
||||
vec![IdxSet::new_empty(bits_per_block); num_blocks]
|
||||
vec![BitSet::new_empty(bits_per_block); num_blocks]
|
||||
};
|
||||
let gen_sets = vec![HybridIdxSet::new_empty(bits_per_block); num_blocks];
|
||||
let gen_sets = vec![HybridBitSet::new_empty(bits_per_block); num_blocks];
|
||||
let kill_sets = gen_sets.clone();
|
||||
|
||||
DataflowAnalysis {
|
||||
|
@ -727,7 +726,7 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
}
|
||||
|
||||
pub fn new_from_sets(mir: &'a Mir<'tcx>,
|
||||
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
|
||||
dead_unwinds: &'a BitSet<mir::BasicBlock>,
|
||||
sets: AllSets<D::Idx>,
|
||||
denotation: D) -> Self {
|
||||
DataflowAnalysis {
|
||||
|
@ -758,7 +757,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
/// unwind target).
|
||||
fn propagate_bits_into_graph_successors_of(
|
||||
&mut self,
|
||||
in_out: &mut IdxSet<D::Idx>,
|
||||
in_out: &mut BitSet<D::Idx>,
|
||||
(bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData),
|
||||
dirty_list: &mut WorkQueue<mir::BasicBlock>)
|
||||
{
|
||||
|
@ -787,7 +786,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
target, value: _, location: _, unwind: Some(unwind)
|
||||
} => {
|
||||
self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
|
||||
if !self.dead_unwinds.contains(&bb) {
|
||||
if !self.dead_unwinds.contains(bb) {
|
||||
self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
|
||||
}
|
||||
}
|
||||
|
@ -798,7 +797,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
}
|
||||
mir::TerminatorKind::Call { cleanup, ref destination, func: _, args: _ } => {
|
||||
if let Some(unwind) = cleanup {
|
||||
if !self.dead_unwinds.contains(&bb) {
|
||||
if !self.dead_unwinds.contains(bb) {
|
||||
self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
|
||||
}
|
||||
}
|
||||
|
@ -819,7 +818,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
|
||||
self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
|
||||
if let Some(unwind) = unwind {
|
||||
if !self.dead_unwinds.contains(&bb) {
|
||||
if !self.dead_unwinds.contains(bb) {
|
||||
self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
|
||||
}
|
||||
}
|
||||
|
@ -828,7 +827,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
|||
}
|
||||
|
||||
fn propagate_bits_into_entry_set_for(&mut self,
|
||||
in_out: &IdxSet<D::Idx>,
|
||||
in_out: &BitSet<D::Idx>,
|
||||
bb: mir::BasicBlock,
|
||||
dirty_queue: &mut WorkQueue<mir::BasicBlock>) {
|
||||
let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry;
|
||||
|
|
|
@ -210,7 +210,7 @@ use rustc::util::common::time;
|
|||
|
||||
use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::bit_set::GrowableBitSet;
|
||||
use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
|
@ -231,7 +231,7 @@ pub struct InliningMap<'tcx> {
|
|||
|
||||
// Contains one bit per mono item in the `targets` field. That bit
|
||||
// is true if that mono item needs to be inlined into every CGU.
|
||||
inlines: BitVector<usize>,
|
||||
inlines: GrowableBitSet<usize>,
|
||||
}
|
||||
|
||||
impl<'tcx> InliningMap<'tcx> {
|
||||
|
@ -240,7 +240,7 @@ impl<'tcx> InliningMap<'tcx> {
|
|||
InliningMap {
|
||||
index: FxHashMap(),
|
||||
targets: Vec::new(),
|
||||
inlines: BitVector::with_capacity(1024),
|
||||
inlines: GrowableBitSet::with_capacity(1024),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,15 +18,14 @@ use dataflow::{self, do_dataflow, DebugFormatted};
|
|||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use transform::{MirPass, MirSource};
|
||||
use util::patch::MirPatch;
|
||||
use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
|
||||
use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub struct ElaborateDrops;
|
||||
|
||||
|
@ -92,12 +91,12 @@ fn find_dead_unwinds<'a, 'tcx>(
|
|||
mir: &Mir<'tcx>,
|
||||
id: ast::NodeId,
|
||||
env: &MoveDataParamEnv<'tcx, 'tcx>)
|
||||
-> IdxSet<BasicBlock>
|
||||
-> BitSet<BasicBlock>
|
||||
{
|
||||
debug!("find_dead_unwinds({:?})", mir.span);
|
||||
// We only need to do this pass once, because unwind edges can only
|
||||
// reach cleanup blocks, which can't have unwind edges themselves.
|
||||
let mut dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
|
||||
let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
|
||||
let flow_inits =
|
||||
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeInitializedPlaces::new(tcx, mir, &env),
|
||||
|
@ -111,7 +110,7 @@ fn find_dead_unwinds<'a, 'tcx>(
|
|||
|
||||
let mut init_data = InitializationData {
|
||||
live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(),
|
||||
dead: IdxSet::new_empty(env.move_data.move_paths.len()),
|
||||
dead: BitSet::new_empty(env.move_data.move_paths.len()),
|
||||
};
|
||||
debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}",
|
||||
bb, bb_data, init_data.live);
|
||||
|
@ -138,7 +137,7 @@ fn find_dead_unwinds<'a, 'tcx>(
|
|||
|
||||
debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
|
||||
if !maybe_live {
|
||||
dead_unwinds.add(&bb);
|
||||
dead_unwinds.insert(bb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,8 +145,8 @@ fn find_dead_unwinds<'a, 'tcx>(
|
|||
}
|
||||
|
||||
struct InitializationData {
|
||||
live: IdxSet<MovePathIndex>,
|
||||
dead: IdxSet<MovePathIndex>
|
||||
live: BitSet<MovePathIndex>,
|
||||
dead: BitSet<MovePathIndex>
|
||||
}
|
||||
|
||||
impl InitializationData {
|
||||
|
@ -162,19 +161,19 @@ impl InitializationData {
|
|||
loc, path, df);
|
||||
match df {
|
||||
DropFlagState::Present => {
|
||||
self.live.add(&path);
|
||||
self.dead.remove(&path);
|
||||
self.live.insert(path);
|
||||
self.dead.remove(path);
|
||||
}
|
||||
DropFlagState::Absent => {
|
||||
self.dead.add(&path);
|
||||
self.live.remove(&path);
|
||||
self.dead.insert(path);
|
||||
self.live.remove(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn state(&self, path: MovePathIndex) -> (bool, bool) {
|
||||
(self.live.contains(&path), self.dead.contains(&path))
|
||||
(self.live.contains(path), self.dead.contains(path))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ use util::dump_mir;
|
|||
use util::liveness::{self, IdentityMap};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use std::borrow::Cow;
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
|
@ -331,7 +331,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored {
|
|||
_location: Location) {
|
||||
match statement.kind {
|
||||
StatementKind::StorageLive(l) |
|
||||
StatementKind::StorageDead(l) => { self.0.remove(&l); }
|
||||
StatementKind::StorageDead(l) => { self.0.remove(l); }
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ struct BorrowedLocals(liveness::LiveVarSet<Local>);
|
|||
|
||||
fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) {
|
||||
match *place {
|
||||
Place::Local(l) => { locals.0.add(&l); },
|
||||
Place::Local(l) => { locals.0.insert(l); },
|
||||
Place::Promoted(_) |
|
||||
Place::Static(..) => (),
|
||||
Place::Projection(ref proj) => {
|
||||
|
@ -376,7 +376,7 @@ fn locals_live_across_suspend_points(
|
|||
liveness::LiveVarSet<Local>,
|
||||
FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
|
||||
) {
|
||||
let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
|
||||
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
|
||||
let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
|
||||
|
||||
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
||||
|
@ -388,7 +388,7 @@ fn locals_live_across_suspend_points(
|
|||
|
||||
// Find the MIR locals which do not use StorageLive/StorageDead statements.
|
||||
// The storage of these locals are always live.
|
||||
let mut ignored = StorageIgnored(IdxSet::new_filled(mir.local_decls.len()));
|
||||
let mut ignored = StorageIgnored(BitSet::new_filled(mir.local_decls.len()));
|
||||
ignored.visit_mir(mir);
|
||||
|
||||
// Calculate the MIR locals which have been previously
|
||||
|
@ -472,7 +472,7 @@ fn locals_live_across_suspend_points(
|
|||
}
|
||||
|
||||
// The generator argument is ignored
|
||||
set.remove(&self_arg());
|
||||
set.remove(self_arg());
|
||||
|
||||
(set, storage_liveness_map)
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
for (local, decl) in mir.local_decls.iter_enumerated() {
|
||||
// Ignore locals which are internal or not live
|
||||
if !live_locals.contains(&local) || decl.internal {
|
||||
if !live_locals.contains(local) || decl.internal {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -823,7 +823,7 @@ fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
|
|||
// Create StorageLive instructions for locals with live storage
|
||||
for i in 0..(mir.local_decls.len()) {
|
||||
let l = Local::new(i);
|
||||
if point.storage_liveness.contains(&l) && !transform.remap.contains_key(&l) {
|
||||
if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) {
|
||||
statements.push(Statement {
|
||||
source_info,
|
||||
kind: StatementKind::StorageLive(l),
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc::hir;
|
|||
use rustc::hir::CodegenFnAttrFlags;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
||||
use rustc::mir::*;
|
||||
|
@ -271,7 +271,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
// Traverse the MIR manually so we can account for the effects of
|
||||
// inlining on the CFG.
|
||||
let mut work_list = vec![START_BLOCK];
|
||||
let mut visited = BitArray::new(callee_mir.basic_blocks().len());
|
||||
let mut visited = BitSet::new_empty(callee_mir.basic_blocks().len());
|
||||
while let Some(bb) = work_list.pop() {
|
||||
if !visited.insert(bb.index()) { continue; }
|
||||
let blk = &callee_mir.basic_blocks()[bb];
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
//! The Qualif flags below can be used to also provide better
|
||||
//! diagnostics as to why a constant rvalue wasn't promoted.
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc::hir;
|
||||
|
@ -116,7 +115,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
local_qualif: IndexVec<Local, Option<Qualif>>,
|
||||
qualif: Qualif,
|
||||
const_fn_arg_vars: BitArray<Local>,
|
||||
const_fn_arg_vars: BitSet<Local>,
|
||||
temp_promotion_state: IndexVec<Local, TempState>,
|
||||
promotion_candidates: Vec<Candidate>
|
||||
}
|
||||
|
@ -151,7 +150,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
|||
param_env,
|
||||
local_qualif,
|
||||
qualif: Qualif::empty(),
|
||||
const_fn_arg_vars: BitArray::new(mir.local_decls.len()),
|
||||
const_fn_arg_vars: BitSet::new_empty(mir.local_decls.len()),
|
||||
temp_promotion_state: temps,
|
||||
promotion_candidates: vec![]
|
||||
}
|
||||
|
@ -280,12 +279,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
|||
}
|
||||
|
||||
/// Qualify a whole const, static initializer or const fn.
|
||||
fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSet<Local>>) {
|
||||
fn qualify_const(&mut self) -> (Qualif, Lrc<BitSet<Local>>) {
|
||||
debug!("qualifying {} {:?}", self.mode, self.def_id);
|
||||
|
||||
let mir = self.mir;
|
||||
|
||||
let mut seen_blocks = BitArray::new(mir.basic_blocks().len());
|
||||
let mut seen_blocks = BitSet::new_empty(mir.basic_blocks().len());
|
||||
let mut bb = START_BLOCK;
|
||||
loop {
|
||||
seen_blocks.insert(bb.index());
|
||||
|
@ -383,14 +382,14 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
|||
|
||||
|
||||
// Collect all the temps we need to promote.
|
||||
let mut promoted_temps = IdxSet::new_empty(self.temp_promotion_state.len());
|
||||
let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len());
|
||||
|
||||
for candidate in &self.promotion_candidates {
|
||||
match *candidate {
|
||||
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
|
||||
match self.mir[bb].statements[stmt_idx].kind {
|
||||
StatementKind::Assign(_, Rvalue::Ref(_, _, Place::Local(index))) => {
|
||||
promoted_temps.add(&index);
|
||||
promoted_temps.insert(index);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1121,7 +1120,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
|
||||
fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> (u8, Lrc<IdxSet<Local>>) {
|
||||
-> (u8, Lrc<BitSet<Local>>) {
|
||||
// NB: This `borrow()` is guaranteed to be valid (i.e., the value
|
||||
// cannot yet be stolen), because `mir_validated()`, which steals
|
||||
// from `mir_const(), forces this query to execute before
|
||||
|
@ -1130,7 +1129,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
if mir.return_ty().references_error() {
|
||||
tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors");
|
||||
return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSet::new_empty(0)));
|
||||
return (Qualif::NOT_CONST.bits(), Lrc::new(BitSet::new_empty(0)));
|
||||
}
|
||||
|
||||
let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const);
|
||||
|
@ -1220,7 +1219,7 @@ impl MirPass for QualifyAndPromoteConstants {
|
|||
block.statements.retain(|statement| {
|
||||
match statement.kind {
|
||||
StatementKind::StorageDead(index) => {
|
||||
!promoted_temps.contains(&index)
|
||||
!promoted_temps.contains(index)
|
||||
}
|
||||
_ => true
|
||||
}
|
||||
|
@ -1228,7 +1227,7 @@ impl MirPass for QualifyAndPromoteConstants {
|
|||
let terminator = block.terminator_mut();
|
||||
match terminator.kind {
|
||||
TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
|
||||
if promoted_temps.contains(&index) {
|
||||
if promoted_temps.contains(index) {
|
||||
terminator.kind = TerminatorKind::Goto {
|
||||
target,
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use transform::{MirPass, MirSource};
|
||||
use util::patch::MirPatch;
|
||||
|
||||
|
@ -45,7 +45,7 @@ impl RemoveNoopLandingPads {
|
|||
&self,
|
||||
bb: BasicBlock,
|
||||
mir: &Mir,
|
||||
nop_landing_pads: &BitArray<BasicBlock>,
|
||||
nop_landing_pads: &BitSet<BasicBlock>,
|
||||
) -> bool {
|
||||
for stmt in &mir[bb].statements {
|
||||
match stmt.kind {
|
||||
|
@ -111,7 +111,7 @@ impl RemoveNoopLandingPads {
|
|||
|
||||
let mut jumps_folded = 0;
|
||||
let mut landing_pads_removed = 0;
|
||||
let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len());
|
||||
let mut nop_landing_pads = BitSet::new_empty(mir.basic_blocks().len());
|
||||
|
||||
// This is a post-order traversal, so that if A post-dominates B
|
||||
// then A will be visited before B.
|
||||
|
|
|
@ -14,7 +14,7 @@ use syntax_pos::Span;
|
|||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::{self, Mir, Location};
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use transform::{MirPass, MirSource};
|
||||
|
||||
use dataflow::{do_dataflow, DebugFormatted};
|
||||
|
@ -46,7 +46,7 @@ impl MirPass for SanityCheck {
|
|||
let param_env = tcx.param_env(def_id);
|
||||
let move_data = MoveData::gather_moves(mir, tcx).unwrap();
|
||||
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
|
||||
let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len());
|
||||
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
|
||||
let flow_inits =
|
||||
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
||||
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
|
||||
|
@ -175,7 +175,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// Okay, our search is over.
|
||||
match move_data.rev_lookup.find(peeking_at_place) {
|
||||
LookupResult::Exact(peek_mpi) => {
|
||||
let bit_state = sets.on_entry.contains(&peek_mpi);
|
||||
let bit_state = sets.on_entry.contains(peek_mpi);
|
||||
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
|
||||
place, peeking_at_place, bit_state);
|
||||
if !bit_state {
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
||||
//! return.
|
||||
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn remove_dead_blocks(mir: &mut Mir) {
|
||||
let mut seen = BitArray::new(mir.basic_blocks().len());
|
||||
let mut seen = BitSet::new_empty(mir.basic_blocks().len());
|
||||
for (bb, _) in traversal::preorder(mir) {
|
||||
seen.insert(bb.index());
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ impl MirPass for SimplifyLocals {
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_: MirSource,
|
||||
mir: &mut Mir<'tcx>) {
|
||||
let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) };
|
||||
let mut marker = DeclMarker { locals: BitSet::new_empty(mir.local_decls.len()) };
|
||||
marker.visit_mir(mir);
|
||||
// Return pointer and arguments are always live
|
||||
marker.locals.insert(RETURN_PLACE);
|
||||
|
@ -310,7 +310,7 @@ impl MirPass for SimplifyLocals {
|
|||
/// Construct the mapping while swapping out unused stuff out from the `vec`.
|
||||
fn make_local_map<'tcx, V>(
|
||||
vec: &mut IndexVec<Local, V>,
|
||||
mask: BitArray<Local>,
|
||||
mask: BitSet<Local>,
|
||||
) -> IndexVec<Local, Option<Local>> {
|
||||
let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
|
||||
let mut used = Local::new(0);
|
||||
|
@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>(
|
|||
}
|
||||
|
||||
struct DeclMarker {
|
||||
pub locals: BitArray<Local>,
|
||||
pub locals: BitSet<Local>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for DeclMarker {
|
||||
|
|
|
@ -37,7 +37,7 @@ use rustc::mir::visit::{PlaceContext, Visitor};
|
|||
use rustc::mir::Local;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{item_path, TyCtxt};
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::work_queue::WorkQueue;
|
||||
use std::fs;
|
||||
|
@ -46,7 +46,7 @@ use std::path::{Path, PathBuf};
|
|||
use transform::MirSource;
|
||||
use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
|
||||
|
||||
pub type LiveVarSet<V> = IdxSet<V>;
|
||||
pub type LiveVarSet<V> = BitSet<V>;
|
||||
|
||||
/// This gives the result of the liveness analysis at the boundary of
|
||||
/// basic blocks.
|
||||
|
@ -243,8 +243,8 @@ impl<V: Idx> DefsUses<V> {
|
|||
// X = 5
|
||||
// // Defs = {}, Uses = {X}
|
||||
// use(X)
|
||||
self.uses.remove(&index);
|
||||
self.defs.add(&index);
|
||||
self.uses.remove(index);
|
||||
self.defs.insert(index);
|
||||
}
|
||||
|
||||
fn add_use(&mut self, index: V) {
|
||||
|
@ -258,8 +258,8 @@ impl<V: Idx> DefsUses<V> {
|
|||
// X = 5
|
||||
// // Defs = {}, Uses = {X}
|
||||
// use(X)
|
||||
self.defs.remove(&index);
|
||||
self.uses.add(&index);
|
||||
self.defs.remove(index);
|
||||
self.uses.insert(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ extern crate smallvec;
|
|||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::bit_set::GrowableBitSet;
|
||||
pub use rustc_data_structures::small_vec::OneVector;
|
||||
pub use rustc_data_structures::thin_vec::ThinVec;
|
||||
use ast::AttrId;
|
||||
|
@ -82,8 +82,8 @@ macro_rules! unwrap_or {
|
|||
}
|
||||
|
||||
pub struct Globals {
|
||||
used_attrs: Lock<BitVector<AttrId>>,
|
||||
known_attrs: Lock<BitVector<AttrId>>,
|
||||
used_attrs: Lock<GrowableBitSet<AttrId>>,
|
||||
known_attrs: Lock<GrowableBitSet<AttrId>>,
|
||||
syntax_pos_globals: syntax_pos::Globals,
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,8 @@ impl Globals {
|
|||
Globals {
|
||||
// We have no idea how many attributes their will be, so just
|
||||
// initiate the vectors with 0 bits. We'll grow them as necessary.
|
||||
used_attrs: Lock::new(BitVector::new()),
|
||||
known_attrs: Lock::new(BitVector::new()),
|
||||
used_attrs: Lock::new(GrowableBitSet::new_empty()),
|
||||
known_attrs: Lock::new(GrowableBitSet::new_empty()),
|
||||
syntax_pos_globals: syntax_pos::Globals::new(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue