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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ use super::*;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Preorder<'a, 'tcx: 'a> {
|
pub struct Preorder<'a, 'tcx: 'a> {
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
visited: BitArray<BasicBlock>,
|
visited: BitSet<BasicBlock>,
|
||||||
worklist: Vec<BasicBlock>,
|
worklist: Vec<BasicBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
|
||||||
|
|
||||||
Preorder {
|
Preorder {
|
||||||
mir,
|
mir,
|
||||||
visited: BitArray::new(mir.basic_blocks().len()),
|
visited: BitSet::new_empty(mir.basic_blocks().len()),
|
||||||
worklist,
|
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`
|
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
|
||||||
pub struct Postorder<'a, 'tcx: 'a> {
|
pub struct Postorder<'a, 'tcx: 'a> {
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
visited: BitArray<BasicBlock>,
|
visited: BitSet<BasicBlock>,
|
||||||
visit_stack: Vec<(BasicBlock, Successors<'a>)>
|
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> {
|
pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
|
||||||
let mut po = Postorder {
|
let mut po = Postorder {
|
||||||
mir,
|
mir,
|
||||||
visited: BitArray::new(mir.basic_blocks().len()),
|
visited: BitSet::new_empty(mir.basic_blocks().len()),
|
||||||
visit_stack: Vec::new()
|
visit_stack: Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ use ty::relate::TypeRelation;
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
use mir::interpret::{GlobalId};
|
use mir::interpret::{GlobalId};
|
||||||
|
|
||||||
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::sync::Lock;
|
use rustc_data_structures::sync::Lock;
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -3069,7 +3069,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
return Err(Unimplemented);
|
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;
|
let mut found = false;
|
||||||
for ty in field.walk() {
|
for ty in field.walk() {
|
||||||
if let ty::Param(p) = ty.sty {
|
if let ty::Param(p) = ty.sty {
|
||||||
|
|
|
@ -49,14 +49,14 @@ use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
|
||||||
use util::common::{ErrorReported};
|
use util::common::{ErrorReported};
|
||||||
use util::profiling::ProfileCategory::*;
|
use util::profiling::ProfileCategory::*;
|
||||||
|
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_target::spec::PanicStrategy;
|
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::stable_hasher::StableVec;
|
use rustc_data_structures::stable_hasher::StableVec;
|
||||||
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use rustc_data_structures::sync::Lrc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
use syntax_pos::symbol::InternedString;
|
use syntax_pos::symbol::InternedString;
|
||||||
|
@ -208,7 +208,7 @@ define_queries! { <'tcx>
|
||||||
/// Maps DefId's that have an associated Mir to the result
|
/// Maps DefId's that have an associated Mir to the result
|
||||||
/// of the MIR qualify_consts pass. The actual meaning of
|
/// of the MIR qualify_consts pass. The actual meaning of
|
||||||
/// the value isn't known except to the pass itself.
|
/// 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
|
/// Fetch the MIR for a given def-id right after it's built - this includes
|
||||||
/// unreachable code.
|
/// unreachable code.
|
||||||
|
|
|
@ -21,7 +21,7 @@ use libc::c_uint;
|
||||||
|
|
||||||
use syntax_pos::Pos;
|
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 rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||||
|
|
||||||
use syntax_pos::BytePos;
|
use syntax_pos::BytePos;
|
||||||
|
@ -64,7 +64,7 @@ pub fn create_mir_scopes(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find all the scopes with variables defined in them.
|
// 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() {
|
for var in mir.vars_iter() {
|
||||||
let decl = &mir.local_decls[var];
|
let decl = &mir.local_decls[var];
|
||||||
has_variables.insert(decl.visibility_scope);
|
has_variables.insert(decl.visibility_scope);
|
||||||
|
@ -81,7 +81,7 @@ pub fn create_mir_scopes(
|
||||||
|
|
||||||
fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
||||||
mir: &Mir,
|
mir: &Mir,
|
||||||
has_variables: &BitArray<SourceScope>,
|
has_variables: &BitSet<SourceScope>,
|
||||||
debug_context: &FunctionDebugContextData<'ll>,
|
debug_context: &FunctionDebugContextData<'ll>,
|
||||||
scope: SourceScope,
|
scope: SourceScope,
|
||||||
scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
|
scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! An analysis to determine which locals require allocas and
|
//! An analysis to determine which locals require allocas and
|
||||||
//! which do not.
|
//! 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::graph::dominators::Dominators;
|
||||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||||
use rustc::mir::{self, Location, TerminatorKind};
|
use rustc::mir::{self, Location, TerminatorKind};
|
||||||
|
@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use super::FunctionCx;
|
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 mir = fx.mir;
|
||||||
let mut analyzer = LocalAnalyzer::new(fx);
|
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> {
|
struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
|
||||||
fx: &'mir FunctionCx<'a, 'll, 'tcx>,
|
fx: &'mir FunctionCx<'a, 'll, 'tcx>,
|
||||||
dominators: Dominators<mir::BasicBlock>,
|
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
|
// The location of the first visited direct assignment to each
|
||||||
// local, or an invalid location (out of bounds `block` index).
|
// local, or an invalid location (out of bounds `block` index).
|
||||||
first_assignment: IndexVec<mir::Local, Location>
|
first_assignment: IndexVec<mir::Local, Location>
|
||||||
|
@ -67,7 +67,7 @@ impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
|
||||||
let mut analyzer = LocalAnalyzer {
|
let mut analyzer = LocalAnalyzer {
|
||||||
fx,
|
fx,
|
||||||
dominators: fx.mir.dominators(),
|
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)
|
first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use syntax::symbol::keywords;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
|
|
||||||
pub use self::constant::codegen_static_initializer;
|
pub use self::constant::codegen_static_initializer;
|
||||||
|
@ -341,7 +341,7 @@ pub fn codegen_mir(
|
||||||
debuginfo::start_emitting_source_locations(&fx.debug_context);
|
debuginfo::start_emitting_source_locations(&fx.debug_context);
|
||||||
|
|
||||||
let rpo = traversal::reverse_postorder(&mir);
|
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
|
// Codegen the body of each block using reverse postorder
|
||||||
for (bb, _) in rpo {
|
for (bb, _) in rpo {
|
||||||
|
@ -435,7 +435,7 @@ fn arg_local_refs(
|
||||||
bx: &Builder<'a, 'll, 'tcx>,
|
bx: &Builder<'a, 'll, 'tcx>,
|
||||||
fx: &FunctionCx<'a, 'll, 'tcx>,
|
fx: &FunctionCx<'a, 'll, 'tcx>,
|
||||||
scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
|
scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
|
||||||
memory_locals: &BitArray<mir::Local>,
|
memory_locals: &BitSet<mir::Local>,
|
||||||
) -> Vec<LocalRef<'ll, 'tcx>> {
|
) -> Vec<LocalRef<'ll, 'tcx>> {
|
||||||
let mir = fx.mir;
|
let mir = fx.mir;
|
||||||
let tcx = bx.tcx();
|
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
|
//! the field `next_edge`). Each of those fields is an array that should
|
||||||
//! be indexed by the direction (see the type `Direction`).
|
//! be indexed by the direction (see the type `Direction`).
|
||||||
|
|
||||||
use bitvec::BitArray;
|
use bit_set::BitSet;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
|
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
|
||||||
|
@ -266,7 +266,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
entry_node: NodeIndex,
|
entry_node: NodeIndex,
|
||||||
) -> Vec<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 stack = vec![];
|
||||||
let mut result = Vec::with_capacity(self.len_nodes());
|
let mut result = Vec::with_capacity(self.len_nodes());
|
||||||
let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
|
let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
|
||||||
|
@ -348,7 +348,7 @@ where
|
||||||
{
|
{
|
||||||
graph: &'g Graph<N, E>,
|
graph: &'g Graph<N, E>,
|
||||||
stack: Vec<NodeIndex>,
|
stack: Vec<NodeIndex>,
|
||||||
visited: BitArray<usize>,
|
visited: BitSet<usize>,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
|
||||||
start_node: NodeIndex,
|
start_node: NodeIndex,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut visited = BitArray::new(graph.len_nodes());
|
let mut visited = BitSet::new_empty(graph.len_nodes());
|
||||||
visited.insert(start_node.node_id());
|
visited.insert(start_node.node_id());
|
||||||
DepthFirstTraversal {
|
DepthFirstTraversal {
|
||||||
graph,
|
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 svh;
|
||||||
pub mod array_vec;
|
pub mod array_vec;
|
||||||
pub mod base_n;
|
pub mod base_n;
|
||||||
pub mod bitvec;
|
pub mod bit_set;
|
||||||
pub mod const_cstr;
|
pub mod const_cstr;
|
||||||
pub mod flock;
|
pub mod flock;
|
||||||
pub mod fx;
|
pub mod fx;
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
pub mod indexed_set;
|
|
||||||
pub mod indexed_vec;
|
pub mod indexed_vec;
|
||||||
pub mod obligation_forest;
|
pub mod obligation_forest;
|
||||||
pub mod owning_ref;
|
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,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
ctx: &mut CTX,
|
ctx: &mut CTX,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use bitvec::BitMatrix;
|
use bit_set::BitMatrix;
|
||||||
use fx::FxHashMap;
|
use fx::FxHashMap;
|
||||||
use sync::Lock;
|
use sync::Lock;
|
||||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
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.
|
// 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)
|
pare_down(&mut candidates, closure); // (2)
|
||||||
candidates.reverse(); // (3a)
|
candidates.reverse(); // (3a)
|
||||||
pare_down(&mut candidates, closure); // (3b)
|
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
|
// with a slight tweak. In the case where `a R a`, we remove
|
||||||
// that from the set of candidates.
|
// that from the set of candidates.
|
||||||
let ancestors = self.with_closure(|closure| {
|
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
|
// Remove anything that can reach `a`. If this is a
|
||||||
// reflexive relation, this will include `a` itself.
|
// reflexive relation, this will include `a` itself.
|
||||||
|
@ -366,10 +366,10 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
|
||||||
changed = false;
|
changed = false;
|
||||||
for edge in &self.edges {
|
for edge in &self.edges {
|
||||||
// add an edge from S -> T
|
// 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
|
// 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
|
matrix
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use indexed_set::IdxSet;
|
use bit_set::BitSet;
|
||||||
use indexed_vec::Idx;
|
use indexed_vec::Idx;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ use std::collections::VecDeque;
|
||||||
/// and also use a bit set to track occupancy.
|
/// and also use a bit set to track occupancy.
|
||||||
pub struct WorkQueue<T: Idx> {
|
pub struct WorkQueue<T: Idx> {
|
||||||
deque: VecDeque<T>,
|
deque: VecDeque<T>,
|
||||||
set: IdxSet<T>,
|
set: BitSet<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Idx> WorkQueue<T> {
|
impl<T: Idx> WorkQueue<T> {
|
||||||
|
@ -29,7 +29,7 @@ impl<T: Idx> WorkQueue<T> {
|
||||||
pub fn with_all(len: usize) -> Self {
|
pub fn with_all(len: usize) -> Self {
|
||||||
WorkQueue {
|
WorkQueue {
|
||||||
deque: (0..len).map(T::new).collect(),
|
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 {
|
pub fn with_none(len: usize) -> Self {
|
||||||
WorkQueue {
|
WorkQueue {
|
||||||
deque: VecDeque::with_capacity(len),
|
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.
|
/// Attempt to enqueue `element` in the work queue. Returns false if it was already present.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert(&mut self, element: T) -> bool {
|
pub fn insert(&mut self, element: T) -> bool {
|
||||||
if self.set.add(&element) {
|
if self.set.insert(element) {
|
||||||
self.deque.push_back(element);
|
self.deque.push_back(element);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,7 +57,7 @@ impl<T: Idx> WorkQueue<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
if let Some(element) = self.deque.pop_front() {
|
if let Some(element) = self.deque.pop_front() {
|
||||||
self.set.remove(&element);
|
self.set.remove(element);
|
||||||
Some(element)
|
Some(element)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -42,7 +42,7 @@ use syntax::edition::Edition;
|
||||||
use syntax::parse::source_file_to_stream;
|
use syntax::parse::source_file_to_stream;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::{Span, NO_EXPANSION, FileName};
|
use syntax_pos::{Span, NO_EXPANSION, FileName};
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
macro_rules! provide {
|
macro_rules! provide {
|
||||||
|
@ -141,7 +141,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||||
mir
|
mir
|
||||||
}
|
}
|
||||||
mir_const_qualif => {
|
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) }
|
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
|
||||||
inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
|
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::ty::{Region, TyCtxt};
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
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::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
@ -102,7 +102,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
||||||
|
|
||||||
crate enum LocalsStateAtExit {
|
crate enum LocalsStateAtExit {
|
||||||
AllAreInvalidated,
|
AllAreInvalidated,
|
||||||
SomeAreInvalidated { has_storage_dead_or_moved: BitArray<Local> }
|
SomeAreInvalidated { has_storage_dead_or_moved: BitSet<Local> }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalsStateAtExit {
|
impl LocalsStateAtExit {
|
||||||
|
@ -111,7 +111,7 @@ impl LocalsStateAtExit {
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
move_data: &MoveData<'tcx>
|
move_data: &MoveData<'tcx>
|
||||||
) -> Self {
|
) -> Self {
|
||||||
struct HasStorageDead(BitArray<Local>);
|
struct HasStorageDead(BitSet<Local>);
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for HasStorageDead {
|
impl<'tcx> Visitor<'tcx> for HasStorageDead {
|
||||||
fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
|
fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
|
||||||
|
@ -124,7 +124,7 @@ impl LocalsStateAtExit {
|
||||||
if locals_are_invalidated_at_exit {
|
if locals_are_invalidated_at_exit {
|
||||||
LocalsStateAtExit::AllAreInvalidated
|
LocalsStateAtExit::AllAreInvalidated
|
||||||
} else {
|
} 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);
|
has_storage_dead.visit_mir(mir);
|
||||||
let mut has_storage_dead_or_moved = has_storage_dead.0;
|
let mut has_storage_dead_or_moved = has_storage_dead.0;
|
||||||
for move_out in &move_data.moves {
|
for move_out in &move_data.moves {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
use rustc::mir::{BasicBlock, Location};
|
use rustc::mir::{BasicBlock, Location};
|
||||||
use rustc::ty::RegionVid;
|
use rustc::ty::RegionVid;
|
||||||
use rustc_data_structures::bitvec::BitIter;
|
use rustc_data_structures::bit_set::BitIter;
|
||||||
|
|
||||||
use borrow_check::location::LocationIndex;
|
use borrow_check::location::LocationIndex;
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ use rustc::ty::query::Providers;
|
||||||
use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
|
use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
|
||||||
|
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
|
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::fx::FxHashSet;
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
_ => Some(tcx.hir.body_owned_by(id)),
|
_ => 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(
|
let mut flow_inits = FlowAtLocation::new(do_dataflow(
|
||||||
tcx,
|
tcx,
|
||||||
mir,
|
mir,
|
||||||
|
@ -1595,7 +1595,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Check if any of the initializiations of `local` have happened yet:
|
// Check if any of the initializiations of `local` have happened yet:
|
||||||
let mpi = self.move_data.rev_lookup.find_local(local);
|
let mpi = self.move_data.rev_lookup.find_local(local);
|
||||||
let init_indices = &self.move_data.init_path_map[mpi];
|
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 {
|
if let Some(&init_index) = first_init_index {
|
||||||
// And, if so, report an error.
|
// And, if so, report an error.
|
||||||
let init = &self.move_data.inits[init_index];
|
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);
|
debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
|
||||||
match self.move_path_closest_to(place_span.0) {
|
match self.move_path_closest_to(place_span.0) {
|
||||||
Ok(mpi) => {
|
Ok(mpi) => {
|
||||||
if maybe_uninits.contains(&mpi) {
|
if maybe_uninits.contains(mpi) {
|
||||||
self.report_use_of_moved_or_uninitialized(
|
self.report_use_of_moved_or_uninitialized(
|
||||||
context,
|
context,
|
||||||
desired_action,
|
desired_action,
|
||||||
|
@ -1969,7 +1969,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// keyword, since the mutation may be a possible reassignment.
|
// keyword, since the mutation may be a possible reassignment.
|
||||||
let mpi = self.move_data.rev_lookup.find_local(*local);
|
let mpi = self.move_data.rev_lookup.find_local(*local);
|
||||||
let ii = &self.move_data.init_path_map[mpi];
|
let ii = &self.move_data.init_path_map[mpi];
|
||||||
for index in ii {
|
for &index in ii {
|
||||||
if flow_state.ever_inits.contains(index) {
|
if flow_state.ever_inits.contains(index) {
|
||||||
self.used_mut.insert(*local);
|
self.used_mut.insert(*local);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,8 +26,8 @@ use rustc::mir::{
|
||||||
};
|
};
|
||||||
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
|
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc::util::common;
|
use rustc::util::common;
|
||||||
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::graph::scc::Sccs;
|
use rustc_data_structures::graph::scc::Sccs;
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_errors::{DiagnosticBuilder, Diagnostic};
|
use rustc_errors::{DiagnosticBuilder, Diagnostic};
|
||||||
|
|
||||||
|
@ -477,7 +477,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
// SCC. For each SCC, we visit its successors and compute
|
// SCC. For each SCC, we visit its successors and compute
|
||||||
// their values, then we union all those values to get our
|
// their values, then we union all those values to get our
|
||||||
// own.
|
// 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() {
|
for scc_index in self.constraint_sccs.all_sccs() {
|
||||||
self.propagate_constraint_sccs_if_new(scc_index, visited);
|
self.propagate_constraint_sccs_if_new(scc_index, visited);
|
||||||
}
|
}
|
||||||
|
@ -487,9 +487,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn propagate_constraint_sccs_if_new(
|
fn propagate_constraint_sccs_if_new(
|
||||||
&mut self,
|
&mut self,
|
||||||
scc_a: ConstraintSccIndex,
|
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);
|
self.propagate_constraint_sccs_new(scc_a, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn propagate_constraint_sccs_new(
|
fn propagate_constraint_sccs_new(
|
||||||
&mut self,
|
&mut self,
|
||||||
scc_a: ConstraintSccIndex,
|
scc_a: ConstraintSccIndex,
|
||||||
visited: &mut IdxSet<ConstraintSccIndex>,
|
visited: &mut BitSet<ConstraintSccIndex>,
|
||||||
) {
|
) {
|
||||||
let constraint_sccs = self.constraint_sccs.clone();
|
let constraint_sccs = self.constraint_sccs.clone();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use rustc::mir::{BasicBlock, Location, Mir};
|
use rustc::mir::{BasicBlock, Location, Mir};
|
||||||
use rustc::ty::{self, RegionVid};
|
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::Idx;
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -179,19 +179,19 @@ impl<N: Idx> LivenessValues<N> {
|
||||||
crate fn add_element(&mut self, row: N, location: Location) -> bool {
|
crate fn add_element(&mut self, row: N, location: Location) -> bool {
|
||||||
debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
|
debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
|
||||||
let index = self.elements.point_from_location(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
|
/// Adds all the elements in the given bit array into the given
|
||||||
/// region. Returns true if any of them are newly added.
|
/// 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);
|
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`.
|
/// Adds all the control-flow points to the values for `r`.
|
||||||
crate fn add_all_points(&mut self, row: N) {
|
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.
|
/// 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`.
|
/// Adds all the control-flow points to the values for `r`.
|
||||||
crate fn add_all_points(&mut self, r: N) {
|
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:
|
/// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
|
||||||
/// r_from`).
|
/// r_from`).
|
||||||
crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
|
crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
|
||||||
self.points.merge(r_from, r_to)
|
self.points.union_rows(r_from, r_to)
|
||||||
| self.free_regions.merge(r_from, r_to)
|
| self.free_regions.union_rows(r_from, r_to)
|
||||||
| self.placeholders.merge(r_from, r_to)
|
| self.placeholders.union_rows(r_from, r_to)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if the region `r` contains the given element.
|
/// True if the region `r` contains the given element.
|
||||||
|
@ -291,7 +291,7 @@ impl<N: Idx> RegionValues<N> {
|
||||||
/// the region `to` in `self`.
|
/// the region `to` in `self`.
|
||||||
crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
|
crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
|
||||||
if let Some(set) = values.points.row(from) {
|
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 {
|
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(sub_row) = self.points.row(sub_region) {
|
||||||
if let Some(sup_row) = self.points.row(sup_region) {
|
if let Some(sup_row) = self.points.row(sup_region) {
|
||||||
sup_row.contains_all(sub_row)
|
sup_row.superset(sub_row)
|
||||||
} else {
|
} else {
|
||||||
// sup row is empty, so sub row must be empty
|
// sup row is empty, so sub row must be empty
|
||||||
sub_row.is_empty()
|
sub_row.is_empty()
|
||||||
|
@ -378,7 +378,7 @@ crate trait ToElementIndex: Debug + Copy {
|
||||||
impl ToElementIndex for Location {
|
impl ToElementIndex for Location {
|
||||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
||||||
let index = values.elements.point_from_location(self);
|
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 {
|
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 {
|
impl ToElementIndex for RegionVid {
|
||||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
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 {
|
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 {
|
impl ToElementIndex for ty::UniverseIndex {
|
||||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
|
||||||
let index = PlaceholderIndex::new(self.as_usize() - 1);
|
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 {
|
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::outlives::DropckOutlives;
|
||||||
use rustc::traits::query::type_op::TypeOp;
|
use rustc::traits::query::type_op::TypeOp;
|
||||||
use rustc::ty::{Ty, TypeFoldable};
|
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 rustc_data_structures::fx::FxHashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use util::liveness::LiveVariableMap;
|
use util::liveness::LiveVariableMap;
|
||||||
|
@ -121,16 +121,16 @@ where
|
||||||
cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>,
|
cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>,
|
||||||
|
|
||||||
/// Set of points that define the current local.
|
/// Set of points that define the current local.
|
||||||
defs: BitArray<PointIndex>,
|
defs: BitSet<PointIndex>,
|
||||||
|
|
||||||
/// Points where the current variable is "use live" -- meaning
|
/// Points where the current variable is "use live" -- meaning
|
||||||
/// that there is a future "full use" that may use its value.
|
/// 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
|
/// Points where the current variable is "drop live" -- meaning
|
||||||
/// that there is no future "full use" that may use its value, but
|
/// that there is no future "full use" that may use its value, but
|
||||||
/// there is a future drop.
|
/// there is a future drop.
|
||||||
drop_live_at: BitArray<PointIndex>,
|
drop_live_at: BitSet<PointIndex>,
|
||||||
|
|
||||||
/// Locations where drops may occur.
|
/// Locations where drops may occur.
|
||||||
drop_locations: Vec<Location>,
|
drop_locations: Vec<Location>,
|
||||||
|
@ -144,9 +144,9 @@ impl LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> {
|
||||||
let num_points = cx.elements.num_points();
|
let num_points = cx.elements.num_points();
|
||||||
LivenessResults {
|
LivenessResults {
|
||||||
cx,
|
cx,
|
||||||
defs: BitArray::new(num_points),
|
defs: BitSet::new_empty(num_points),
|
||||||
use_live_at: BitArray::new(num_points),
|
use_live_at: BitSet::new_empty(num_points),
|
||||||
drop_live_at: BitArray::new(num_points),
|
drop_live_at: BitSet::new_empty(num_points),
|
||||||
drop_locations: vec![],
|
drop_locations: vec![],
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
||||||
fn add_use_live_facts_for(
|
fn add_use_live_facts_for(
|
||||||
&mut self,
|
&mut self,
|
||||||
value: impl TypeFoldable<'tcx>,
|
value: impl TypeFoldable<'tcx>,
|
||||||
live_at: &BitArray<PointIndex>,
|
live_at: &BitSet<PointIndex>,
|
||||||
) {
|
) {
|
||||||
debug!("add_use_live_facts_for(value={:?})", value);
|
debug!("add_use_live_facts_for(value={:?})", value);
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
||||||
dropped_local: Local,
|
dropped_local: Local,
|
||||||
dropped_ty: Ty<'tcx>,
|
dropped_ty: Ty<'tcx>,
|
||||||
drop_locations: &[Location],
|
drop_locations: &[Location],
|
||||||
live_at: &BitArray<PointIndex>,
|
live_at: &BitSet<PointIndex>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"add_drop_live_constraint(\
|
"add_drop_live_constraint(\
|
||||||
|
@ -508,7 +508,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
|
||||||
elements: &RegionValueElements,
|
elements: &RegionValueElements,
|
||||||
typeck: &mut TypeChecker<'_, '_, 'tcx>,
|
typeck: &mut TypeChecker<'_, '_, 'tcx>,
|
||||||
value: impl TypeFoldable<'tcx>,
|
value: impl TypeFoldable<'tcx>,
|
||||||
live_at: &BitArray<PointIndex>,
|
live_at: &BitSet<PointIndex>,
|
||||||
) {
|
) {
|
||||||
debug!("make_all_regions_live(value={:?})", value);
|
debug!("make_all_regions_live(value={:?})", value);
|
||||||
debug!(
|
debug!(
|
||||||
|
|
|
@ -21,7 +21,7 @@ use hair::*;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::ty::{self, CanonicalTy, Ty};
|
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 rustc_data_structures::fx::FxHashMap;
|
||||||
use syntax::ast::{Name, NodeId};
|
use syntax::ast::{Name, NodeId};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -635,7 +635,7 @@ enum TestKind<'tcx> {
|
||||||
// test the branches of enum
|
// test the branches of enum
|
||||||
Switch {
|
Switch {
|
||||||
adt_def: &'tcx ty::AdtDef,
|
adt_def: &'tcx ty::AdtDef,
|
||||||
variants: BitArray<usize>,
|
variants: BitSet<usize>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// test the branches of enum
|
// test the branches of enum
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
use build::Builder;
|
use build::Builder;
|
||||||
use build::matches::{Candidate, MatchPair, Test, TestKind};
|
use build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||||
use hair::*;
|
use hair::*;
|
||||||
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::util::IntTypeExt;
|
use rustc::ty::util::IntTypeExt;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
|
@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
span: match_pair.pattern.span,
|
span: match_pair.pattern.span,
|
||||||
kind: TestKind::Switch {
|
kind: TestKind::Switch {
|
||||||
adt_def: adt_def.clone(),
|
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,
|
pub fn add_variants_to_switch<'pat>(&mut self,
|
||||||
test_place: &Place<'tcx>,
|
test_place: &Place<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
variants: &mut BitArray<usize>)
|
variants: &mut BitSet<usize>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
//! locations.
|
//! locations.
|
||||||
|
|
||||||
use rustc::mir::{BasicBlock, Location};
|
use rustc::mir::{BasicBlock, Location};
|
||||||
use rustc_data_structures::bitvec::BitIter;
|
use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};
|
||||||
use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
|
|
||||||
|
|
||||||
use dataflow::{BitDenotation, BlockSets, DataflowResults};
|
use dataflow::{BitDenotation, BlockSets, DataflowResults};
|
||||||
use dataflow::move_paths::{HasMoveData, MovePathIndex};
|
use dataflow::move_paths::{HasMoveData, MovePathIndex};
|
||||||
|
@ -76,9 +75,9 @@ where
|
||||||
BD: BitDenotation,
|
BD: BitDenotation,
|
||||||
{
|
{
|
||||||
base_results: DataflowResults<BD>,
|
base_results: DataflowResults<BD>,
|
||||||
curr_state: IdxSet<BD::Idx>,
|
curr_state: BitSet<BD::Idx>,
|
||||||
stmt_gen: HybridIdxSet<BD::Idx>,
|
stmt_gen: HybridBitSet<BD::Idx>,
|
||||||
stmt_kill: HybridIdxSet<BD::Idx>,
|
stmt_kill: HybridBitSet<BD::Idx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BD> FlowAtLocation<BD>
|
impl<BD> FlowAtLocation<BD>
|
||||||
|
@ -105,9 +104,9 @@ where
|
||||||
|
|
||||||
pub fn new(results: DataflowResults<BD>) -> Self {
|
pub fn new(results: DataflowResults<BD>) -> Self {
|
||||||
let bits_per_block = results.sets().bits_per_block();
|
let bits_per_block = results.sets().bits_per_block();
|
||||||
let curr_state = IdxSet::new_empty(bits_per_block);
|
let curr_state = BitSet::new_empty(bits_per_block);
|
||||||
let stmt_gen = HybridIdxSet::new_empty(bits_per_block);
|
let stmt_gen = HybridBitSet::new_empty(bits_per_block);
|
||||||
let stmt_kill = HybridIdxSet::new_empty(bits_per_block);
|
let stmt_kill = HybridBitSet::new_empty(bits_per_block);
|
||||||
FlowAtLocation {
|
FlowAtLocation {
|
||||||
base_results: results,
|
base_results: results,
|
||||||
curr_state: curr_state,
|
curr_state: curr_state,
|
||||||
|
@ -121,7 +120,7 @@ where
|
||||||
self.base_results.operator()
|
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)
|
self.curr_state.contains(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +223,7 @@ where
|
||||||
// siblings);
|
// siblings);
|
||||||
// - ~99% of the time the loop isn't reached, and this code is hot, so
|
// - ~99% of the time the loop isn't reached, and this code is hot, so
|
||||||
// we don't want to allocate `todo` unnecessarily.
|
// we don't want to allocate `todo` unnecessarily.
|
||||||
if self.contains(&mpi) {
|
if self.contains(mpi) {
|
||||||
return Some(mpi);
|
return Some(mpi);
|
||||||
}
|
}
|
||||||
let move_data = self.operator().move_data();
|
let move_data = self.operator().move_data();
|
||||||
|
@ -236,7 +235,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(mpi) = todo.pop() {
|
while let Some(mpi) = todo.pop() {
|
||||||
if self.contains(&mpi) {
|
if self.contains(mpi) {
|
||||||
return Some(mpi);
|
return Some(mpi);
|
||||||
}
|
}
|
||||||
let move_path = &move_data.move_paths[mpi];
|
let move_path = &move_data.move_paths[mpi];
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use rustc::mir::{BasicBlock, Mir};
|
use rustc::mir::{BasicBlock, Mir};
|
||||||
use rustc_data_structures::bitvec::bits_to_string;
|
|
||||||
|
|
||||||
use dot;
|
use dot;
|
||||||
use dot::IntoCow;
|
use dot::IntoCow;
|
||||||
|
@ -223,7 +222,7 @@ where MWF: MirWithFlowState<'tcx>,
|
||||||
|
|
||||||
// Entry
|
// Entry
|
||||||
let set = flow.sets.on_entry_set_for(i);
|
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
|
// Terminator
|
||||||
write!(w, "<td>")?;
|
write!(w, "<td>")?;
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
|
||||||
self.mir.local_decls.len()
|
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
|
// 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
|
// StorageDead invalidates all borrows and raw pointers to a local
|
||||||
match stmt.kind {
|
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,
|
fn propagate_call_return(&self,
|
||||||
_in_out: &mut IdxSet<Local>,
|
_in_out: &mut BitSet<Local>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_place: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
|
@ -118,7 +118,7 @@ impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if let Rvalue::Ref(_, _, ref place) = *rvalue {
|
if let Rvalue::Ref(_, _, ref place) = *rvalue {
|
||||||
if let Some(local) = find_local(place) {
|
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, RegionVid};
|
||||||
use rustc::ty::RegionKind::ReScope;
|
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::fx::FxHashMap;
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_data_structures::sync::Lrc;
|
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
|
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
|
// no borrows of code region_scopes have been taken prior to
|
||||||
// function execution, so this method has no effect on
|
// function execution, so this method has no effect on
|
||||||
// `_sets`.
|
// `_sets`.
|
||||||
|
@ -286,7 +285,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||||
debug!("Borrows::statement_effect_on_borrows \
|
debug!("Borrows::statement_effect_on_borrows \
|
||||||
location: {:?} stmt: {:?} has empty region, killing {:?}",
|
location: {:?} stmt: {:?} has empty region, killing {:?}",
|
||||||
location, stmt.kind, index);
|
location, stmt.kind, index);
|
||||||
sets.kill(&index);
|
sets.kill(*index);
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}",
|
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(|| {
|
assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
|
||||||
panic!("could not find BorrowIndexs for region {:?}", region);
|
panic!("could not find BorrowIndexs for region {:?}", region);
|
||||||
}).contains(&index));
|
}).contains(&index));
|
||||||
sets.gen(&index);
|
sets.gen(*index);
|
||||||
|
|
||||||
// Issue #46746: Two-phase borrows handles
|
// Issue #46746: Two-phase borrows handles
|
||||||
// stmts of form `Tmp = &mut Borrow` ...
|
// 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
|
// e.g. `box (&mut _)`. Current
|
||||||
// conservative solution: force
|
// conservative solution: force
|
||||||
// immediate activation here.
|
// 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 &&
|
if *scope != root_scope &&
|
||||||
self.scope_tree.is_subscope_of(*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,
|
fn propagate_call_return(&self,
|
||||||
_in_out: &mut IdxSet<BorrowIndex>,
|
_in_out: &mut BitSet<BorrowIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_place: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
|
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::{self, Mir, Location};
|
use rustc::mir::{self, Mir, Location};
|
||||||
use rustc_data_structures::bitvec::{BitwiseOperator, Word};
|
use rustc_data_structures::bit_set::{BitSet, BitwiseOperator, Word};
|
||||||
use rustc_data_structures::indexed_set::{IdxSet};
|
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
||||||
use super::MoveDataParamEnv;
|
use super::MoveDataParamEnv;
|
||||||
|
@ -266,8 +265,8 @@ impl<'a, 'gcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
|
||||||
state: DropFlagState)
|
state: DropFlagState)
|
||||||
{
|
{
|
||||||
match state {
|
match state {
|
||||||
DropFlagState::Absent => sets.kill(&path),
|
DropFlagState::Absent => sets.kill(path),
|
||||||
DropFlagState::Present => sets.gen(&path),
|
DropFlagState::Present => sets.gen(path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,8 +276,8 @@ impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
|
||||||
state: DropFlagState)
|
state: DropFlagState)
|
||||||
{
|
{
|
||||||
match state {
|
match state {
|
||||||
DropFlagState::Absent => sets.gen(&path),
|
DropFlagState::Absent => sets.gen(path),
|
||||||
DropFlagState::Present => sets.kill(&path),
|
DropFlagState::Present => sets.kill(path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,8 +287,8 @@ impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
|
||||||
state: DropFlagState)
|
state: DropFlagState)
|
||||||
{
|
{
|
||||||
match state {
|
match state {
|
||||||
DropFlagState::Absent => sets.kill(&path),
|
DropFlagState::Absent => sets.kill(path),
|
||||||
DropFlagState::Present => sets.gen(&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()
|
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(
|
drop_flag_effects_for_function_entry(
|
||||||
self.tcx, self.mir, self.mdpe,
|
self.tcx, self.mir, self.mdpe,
|
||||||
|path, s| {
|
|path, s| {
|
||||||
assert!(s == DropFlagState::Present);
|
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,
|
fn propagate_call_return(&self,
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut BitSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_place: &mir::Place) {
|
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).
|
// the bits for that dest_place to 1 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_place),
|
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
|
// 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
|
// set all bits to 1 (uninit) before gathering counterevidence
|
||||||
entry_set.set_up_to(self.bits_per_block());
|
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,
|
self.tcx, self.mir, self.mdpe,
|
||||||
|path, s| {
|
|path, s| {
|
||||||
assert!(s == DropFlagState::Present);
|
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,
|
fn propagate_call_return(&self,
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut BitSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_place: &mir::Place) {
|
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).
|
// the bits for that dest_place to 0 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_place),
|
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
|
// 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();
|
entry_set.clear();
|
||||||
|
|
||||||
drop_flag_effects_for_function_entry(
|
drop_flag_effects_for_function_entry(
|
||||||
self.tcx, self.mir, self.mdpe,
|
self.tcx, self.mir, self.mdpe,
|
||||||
|path, s| {
|
|path, s| {
|
||||||
assert!(s == DropFlagState::Present);
|
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,
|
fn propagate_call_return(&self,
|
||||||
in_out: &mut IdxSet<MovePathIndex>,
|
in_out: &mut BitSet<MovePathIndex>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
dest_place: &mir::Place) {
|
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).
|
// the bits for that dest_place to 1 (initialized).
|
||||||
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
|
||||||
self.move_data().rev_lookup.find(dest_place),
|
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()
|
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 {
|
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,
|
fn propagate_call_return(&self,
|
||||||
in_out: &mut IdxSet<InitIndex>,
|
in_out: &mut BitSet<InitIndex>,
|
||||||
call_bb: mir::BasicBlock,
|
call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_place: &mir::Place) {
|
_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] {
|
for init_index in &init_loc_map[call_loc] {
|
||||||
assert!(init_index.index() < bits_per_block);
|
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()
|
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
|
// 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];
|
let stmt = &self.mir[loc.block].statements[loc.statement_index];
|
||||||
|
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
StatementKind::StorageLive(l) => sets.gen(&l),
|
StatementKind::StorageLive(l) => sets.gen(l),
|
||||||
StatementKind::StorageDead(l) => sets.kill(&l),
|
StatementKind::StorageDead(l) => sets.kill(l),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_call_return(&self,
|
fn propagate_call_return(&self,
|
||||||
_in_out: &mut IdxSet<Local>,
|
_in_out: &mut BitSet<Local>,
|
||||||
_call_bb: mir::BasicBlock,
|
_call_bb: mir::BasicBlock,
|
||||||
_dest_bb: mir::BasicBlock,
|
_dest_bb: mir::BasicBlock,
|
||||||
_dest_place: &mir::Place) {
|
_dest_place: &mir::Place) {
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
|
|
||||||
use syntax::ast::{self, MetaItem};
|
use syntax::ast::{self, MetaItem};
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::{bitwise, BitwiseOperator};
|
use rustc_data_structures::bit_set::{bitwise, BitwiseOperator, BitSet, HybridBitSet};
|
||||||
use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet};
|
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use rustc_data_structures::work_queue::WorkQueue;
|
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>,
|
mir: &'a Mir<'tcx>,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
attributes: &[ast::Attribute],
|
attributes: &[ast::Attribute],
|
||||||
dead_unwinds: &IdxSet<BasicBlock>,
|
dead_unwinds: &BitSet<BasicBlock>,
|
||||||
bd: BD,
|
bd: BD,
|
||||||
p: P)
|
p: P)
|
||||||
-> DataflowResults<BD>
|
-> 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
|
impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
|
||||||
{
|
{
|
||||||
fn propagate(&mut self) {
|
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 {
|
let mut propcx = PropagationContext {
|
||||||
builder: self,
|
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
|
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> =
|
let mut dirty_queue: WorkQueue<mir::BasicBlock> =
|
||||||
WorkQueue::with_all(self.builder.mir.basic_blocks().len());
|
WorkQueue::with_all(self.builder.mir.basic_blocks().len());
|
||||||
let mir = self.builder.mir;
|
let mir = self.builder.mir;
|
||||||
|
@ -352,7 +351,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
|
||||||
analysis: &T,
|
analysis: &T,
|
||||||
result: &DataflowResults<T>,
|
result: &DataflowResults<T>,
|
||||||
mir: &Mir<'tcx>)
|
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 on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
|
||||||
let mut kill_set = on_entry.to_hybrid();
|
let mut kill_set = on_entry.to_hybrid();
|
||||||
let mut gen_set = kill_set.clone();
|
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
|
pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
|
||||||
{
|
{
|
||||||
flow_state: DataflowState<O>,
|
flow_state: DataflowState<O>,
|
||||||
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
|
dead_unwinds: &'a BitSet<mir::BasicBlock>,
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +425,7 @@ pub struct DataflowState<O: BitDenotation>
|
||||||
impl<O: BitDenotation> DataflowState<O> {
|
impl<O: BitDenotation> DataflowState<O> {
|
||||||
pub(crate) fn interpret_set<'c, P>(&self,
|
pub(crate) fn interpret_set<'c, P>(&self,
|
||||||
o: &'c O,
|
o: &'c O,
|
||||||
set: &IdxSet<O::Idx>,
|
set: &BitSet<O::Idx>,
|
||||||
render_idx: &P)
|
render_idx: &P)
|
||||||
-> Vec<DebugFormatted>
|
-> Vec<DebugFormatted>
|
||||||
where P: Fn(&O, O::Idx) -> 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,
|
pub(crate) fn interpret_hybrid_set<'c, P>(&self,
|
||||||
o: &'c O,
|
o: &'c O,
|
||||||
set: &HybridIdxSet<O::Idx>,
|
set: &HybridBitSet<O::Idx>,
|
||||||
render_idx: &P)
|
render_idx: &P)
|
||||||
-> Vec<DebugFormatted>
|
-> Vec<DebugFormatted>
|
||||||
where P: Fn(&O, O::Idx) -> DebugFormatted
|
where P: Fn(&O, O::Idx) -> DebugFormatted
|
||||||
|
@ -451,21 +450,21 @@ pub struct AllSets<E: Idx> {
|
||||||
bits_per_block: usize,
|
bits_per_block: usize,
|
||||||
|
|
||||||
/// For each block, bits valid on entry to the block.
|
/// 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 +
|
/// For each block, bits generated by executing the statements +
|
||||||
/// terminator in the block -- with one caveat. In particular, for
|
/// terminator in the block -- with one caveat. In particular, for
|
||||||
/// *call terminators*, the effect of storing the destination is
|
/// *call terminators*, the effect of storing the destination is
|
||||||
/// not included, since that only takes effect on the **success**
|
/// not included, since that only takes effect on the **success**
|
||||||
/// edge (and not the unwind edge).
|
/// 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 +
|
/// For each block, bits killed by executing the statements +
|
||||||
/// terminator in the block -- with one caveat. In particular, for
|
/// terminator in the block -- with one caveat. In particular, for
|
||||||
/// *call terminators*, the effect of storing the destination is
|
/// *call terminators*, the effect of storing the destination is
|
||||||
/// not included, since that only takes effect on the **success**
|
/// not included, since that only takes effect on the **success**
|
||||||
/// edge (and not the unwind edge).
|
/// edge (and not the unwind edge).
|
||||||
kill_sets: Vec<HybridIdxSet<E>>,
|
kill_sets: Vec<HybridBitSet<E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triple of sets associated with a given block.
|
/// Triple of sets associated with a given block.
|
||||||
|
@ -485,20 +484,20 @@ pub struct AllSets<E: Idx> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BlockSets<'a, E: Idx> {
|
pub struct BlockSets<'a, E: Idx> {
|
||||||
/// Dataflow state immediately before control flow enters the given block.
|
/// 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
|
/// Bits that are set to 1 by the time we exit the given block. Hybrid
|
||||||
/// because it usually contains only 0 or 1 elements.
|
/// 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
|
/// Bits that are set to 0 by the time we exit the given block. Hybrid
|
||||||
/// because it usually contains only 0 or 1 elements.
|
/// 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> {
|
impl<'a, E:Idx> BlockSets<'a, E> {
|
||||||
fn gen(&mut self, e: &E) {
|
fn gen(&mut self, e: E) {
|
||||||
self.gen_set.add(e);
|
self.gen_set.insert(e);
|
||||||
self.kill_set.remove(e);
|
self.kill_set.remove(e);
|
||||||
}
|
}
|
||||||
fn gen_all<I>(&mut self, i: I)
|
fn gen_all<I>(&mut self, i: I)
|
||||||
|
@ -506,13 +505,13 @@ impl<'a, E:Idx> BlockSets<'a, E> {
|
||||||
I::Item: Borrow<E>
|
I::Item: Borrow<E>
|
||||||
{
|
{
|
||||||
for j in i {
|
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.gen_set.remove(e);
|
||||||
self.kill_set.add(e);
|
self.kill_set.insert(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill_all<I>(&mut self, i: I)
|
fn kill_all<I>(&mut self, i: I)
|
||||||
|
@ -520,7 +519,7 @@ impl<'a, E:Idx> BlockSets<'a, E> {
|
||||||
I::Item: Borrow<E>
|
I::Item: Borrow<E>
|
||||||
{
|
{
|
||||||
for j in i {
|
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]
|
&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]
|
&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]
|
&self.kill_sets[block_idx]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -609,7 +608,7 @@ pub trait BitDenotation: BitwiseOperator {
|
||||||
/// these won't be accounted for correctly.
|
/// these won't be accounted for correctly.
|
||||||
///
|
///
|
||||||
/// (For example, establishing the call arguments.)
|
/// (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
|
/// Similar to `statement_effect`, except it applies
|
||||||
/// *just before* the statement rather than *just after* it.
|
/// *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
|
/// kill-sets associated with each edge coming out of the basic
|
||||||
/// block.
|
/// block.
|
||||||
fn propagate_call_return(&self,
|
fn propagate_call_return(&self,
|
||||||
in_out: &mut IdxSet<Self::Idx>,
|
in_out: &mut BitSet<Self::Idx>,
|
||||||
call_bb: mir::BasicBlock,
|
call_bb: mir::BasicBlock,
|
||||||
dest_bb: mir::BasicBlock,
|
dest_bb: mir::BasicBlock,
|
||||||
dest_place: &mir::Place);
|
dest_place: &mir::Place);
|
||||||
|
@ -698,17 +697,17 @@ pub trait BitDenotation: BitwiseOperator {
|
||||||
impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
||||||
{
|
{
|
||||||
pub fn new(mir: &'a Mir<'tcx>,
|
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 {
|
denotation: D) -> Self where D: InitialFlow {
|
||||||
let bits_per_block = denotation.bits_per_block();
|
let bits_per_block = denotation.bits_per_block();
|
||||||
let num_blocks = mir.basic_blocks().len();
|
let num_blocks = mir.basic_blocks().len();
|
||||||
|
|
||||||
let on_entry_sets = if D::bottom_value() {
|
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 {
|
} 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();
|
let kill_sets = gen_sets.clone();
|
||||||
|
|
||||||
DataflowAnalysis {
|
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>,
|
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>,
|
sets: AllSets<D::Idx>,
|
||||||
denotation: D) -> Self {
|
denotation: D) -> Self {
|
||||||
DataflowAnalysis {
|
DataflowAnalysis {
|
||||||
|
@ -758,7 +757,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
|
||||||
/// unwind target).
|
/// unwind target).
|
||||||
fn propagate_bits_into_graph_successors_of(
|
fn propagate_bits_into_graph_successors_of(
|
||||||
&mut self,
|
&mut self,
|
||||||
in_out: &mut IdxSet<D::Idx>,
|
in_out: &mut BitSet<D::Idx>,
|
||||||
(bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData),
|
(bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData),
|
||||||
dirty_list: &mut WorkQueue<mir::BasicBlock>)
|
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)
|
target, value: _, location: _, unwind: Some(unwind)
|
||||||
} => {
|
} => {
|
||||||
self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
|
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);
|
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: _ } => {
|
mir::TerminatorKind::Call { cleanup, ref destination, func: _, args: _ } => {
|
||||||
if let Some(unwind) = cleanup {
|
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);
|
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 } => {
|
mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
|
||||||
self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
|
self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
|
||||||
if let Some(unwind) = unwind {
|
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);
|
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,
|
fn propagate_bits_into_entry_set_for(&mut self,
|
||||||
in_out: &IdxSet<D::Idx>,
|
in_out: &BitSet<D::Idx>,
|
||||||
bb: mir::BasicBlock,
|
bb: mir::BasicBlock,
|
||||||
dirty_queue: &mut WorkQueue<mir::BasicBlock>) {
|
dirty_queue: &mut WorkQueue<mir::BasicBlock>) {
|
||||||
let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry;
|
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 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};
|
use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
#[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
|
// 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.
|
// is true if that mono item needs to be inlined into every CGU.
|
||||||
inlines: BitVector<usize>,
|
inlines: GrowableBitSet<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> InliningMap<'tcx> {
|
impl<'tcx> InliningMap<'tcx> {
|
||||||
|
@ -240,7 +240,7 @@ impl<'tcx> InliningMap<'tcx> {
|
||||||
InliningMap {
|
InliningMap {
|
||||||
index: FxHashMap(),
|
index: FxHashMap(),
|
||||||
targets: Vec::new(),
|
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::ty::{self, TyCtxt};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::util::nodemap::FxHashMap;
|
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 transform::{MirPass, MirSource};
|
||||||
use util::patch::MirPatch;
|
use util::patch::MirPatch;
|
||||||
use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
|
use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
|
||||||
use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
|
use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
|
||||||
use syntax::ast;
|
|
||||||
use syntax_pos::Span;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub struct ElaborateDrops;
|
pub struct ElaborateDrops;
|
||||||
|
|
||||||
|
@ -92,12 +91,12 @@ fn find_dead_unwinds<'a, 'tcx>(
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
env: &MoveDataParamEnv<'tcx, 'tcx>)
|
env: &MoveDataParamEnv<'tcx, 'tcx>)
|
||||||
-> IdxSet<BasicBlock>
|
-> BitSet<BasicBlock>
|
||||||
{
|
{
|
||||||
debug!("find_dead_unwinds({:?})", mir.span);
|
debug!("find_dead_unwinds({:?})", mir.span);
|
||||||
// We only need to do this pass once, because unwind edges can only
|
// We only need to do this pass once, because unwind edges can only
|
||||||
// reach cleanup blocks, which can't have unwind edges themselves.
|
// 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 =
|
let flow_inits =
|
||||||
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||||
MaybeInitializedPlaces::new(tcx, mir, &env),
|
MaybeInitializedPlaces::new(tcx, mir, &env),
|
||||||
|
@ -111,7 +110,7 @@ fn find_dead_unwinds<'a, 'tcx>(
|
||||||
|
|
||||||
let mut init_data = InitializationData {
|
let mut init_data = InitializationData {
|
||||||
live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(),
|
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={:?}",
|
debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}",
|
||||||
bb, bb_data, init_data.live);
|
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);
|
debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
|
||||||
if !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 {
|
struct InitializationData {
|
||||||
live: IdxSet<MovePathIndex>,
|
live: BitSet<MovePathIndex>,
|
||||||
dead: IdxSet<MovePathIndex>
|
dead: BitSet<MovePathIndex>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InitializationData {
|
impl InitializationData {
|
||||||
|
@ -162,19 +161,19 @@ impl InitializationData {
|
||||||
loc, path, df);
|
loc, path, df);
|
||||||
match df {
|
match df {
|
||||||
DropFlagState::Present => {
|
DropFlagState::Present => {
|
||||||
self.live.add(&path);
|
self.live.insert(path);
|
||||||
self.dead.remove(&path);
|
self.dead.remove(path);
|
||||||
}
|
}
|
||||||
DropFlagState::Absent => {
|
DropFlagState::Absent => {
|
||||||
self.dead.add(&path);
|
self.dead.insert(path);
|
||||||
self.live.remove(&path);
|
self.live.remove(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state(&self, path: MovePathIndex) -> (bool, bool) {
|
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 util::liveness::{self, IdentityMap};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
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::borrow::Cow;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -331,7 +331,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored {
|
||||||
_location: Location) {
|
_location: Location) {
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::StorageLive(l) |
|
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) {
|
fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Local(l) => { locals.0.add(&l); },
|
Place::Local(l) => { locals.0.insert(l); },
|
||||||
Place::Promoted(_) |
|
Place::Promoted(_) |
|
||||||
Place::Static(..) => (),
|
Place::Static(..) => (),
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
|
@ -376,7 +376,7 @@ fn locals_live_across_suspend_points(
|
||||||
liveness::LiveVarSet<Local>,
|
liveness::LiveVarSet<Local>,
|
||||||
FxHashMap<BasicBlock, 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();
|
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
|
// 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.
|
// Find the MIR locals which do not use StorageLive/StorageDead statements.
|
||||||
// The storage of these locals are always live.
|
// 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);
|
ignored.visit_mir(mir);
|
||||||
|
|
||||||
// Calculate the MIR locals which have been previously
|
// Calculate the MIR locals which have been previously
|
||||||
|
@ -472,7 +472,7 @@ fn locals_live_across_suspend_points(
|
||||||
}
|
}
|
||||||
|
|
||||||
// The generator argument is ignored
|
// The generator argument is ignored
|
||||||
set.remove(&self_arg());
|
set.remove(self_arg());
|
||||||
|
|
||||||
(set, storage_liveness_map)
|
(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() {
|
for (local, decl) in mir.local_decls.iter_enumerated() {
|
||||||
// Ignore locals which are internal or not live
|
// Ignore locals which are internal or not live
|
||||||
if !live_locals.contains(&local) || decl.internal {
|
if !live_locals.contains(local) || decl.internal {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,7 +823,7 @@ fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
|
||||||
// Create StorageLive instructions for locals with live storage
|
// Create StorageLive instructions for locals with live storage
|
||||||
for i in 0..(mir.local_decls.len()) {
|
for i in 0..(mir.local_decls.len()) {
|
||||||
let l = Local::new(i);
|
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 {
|
statements.push(Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::StorageLive(l),
|
kind: StatementKind::StorageLive(l),
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc::hir;
|
||||||
use rustc::hir::CodegenFnAttrFlags;
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def_id::DefId;
|
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_data_structures::indexed_vec::{Idx, IndexVec};
|
||||||
|
|
||||||
use rustc::mir::*;
|
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
|
// Traverse the MIR manually so we can account for the effects of
|
||||||
// inlining on the CFG.
|
// inlining on the CFG.
|
||||||
let mut work_list = vec![START_BLOCK];
|
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() {
|
while let Some(bb) = work_list.pop() {
|
||||||
if !visited.insert(bb.index()) { continue; }
|
if !visited.insert(bb.index()) { continue; }
|
||||||
let blk = &callee_mir.basic_blocks()[bb];
|
let blk = &callee_mir.basic_blocks()[bb];
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
//! The Qualif flags below can be used to also provide better
|
//! The Qualif flags below can be used to also provide better
|
||||||
//! diagnostics as to why a constant rvalue wasn't promoted.
|
//! diagnostics as to why a constant rvalue wasn't promoted.
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::indexed_set::IdxSet;
|
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
@ -116,7 +115,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
local_qualif: IndexVec<Local, Option<Qualif>>,
|
local_qualif: IndexVec<Local, Option<Qualif>>,
|
||||||
qualif: Qualif,
|
qualif: Qualif,
|
||||||
const_fn_arg_vars: BitArray<Local>,
|
const_fn_arg_vars: BitSet<Local>,
|
||||||
temp_promotion_state: IndexVec<Local, TempState>,
|
temp_promotion_state: IndexVec<Local, TempState>,
|
||||||
promotion_candidates: Vec<Candidate>
|
promotion_candidates: Vec<Candidate>
|
||||||
}
|
}
|
||||||
|
@ -151,7 +150,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||||
param_env,
|
param_env,
|
||||||
local_qualif,
|
local_qualif,
|
||||||
qualif: Qualif::empty(),
|
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,
|
temp_promotion_state: temps,
|
||||||
promotion_candidates: vec![]
|
promotion_candidates: vec![]
|
||||||
}
|
}
|
||||||
|
@ -280,12 +279,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Qualify a whole const, static initializer or const fn.
|
/// 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);
|
debug!("qualifying {} {:?}", self.mode, self.def_id);
|
||||||
|
|
||||||
let mir = self.mir;
|
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;
|
let mut bb = START_BLOCK;
|
||||||
loop {
|
loop {
|
||||||
seen_blocks.insert(bb.index());
|
seen_blocks.insert(bb.index());
|
||||||
|
@ -383,14 +382,14 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
|
|
||||||
// Collect all the temps we need to promote.
|
// 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 {
|
for candidate in &self.promotion_candidates {
|
||||||
match *candidate {
|
match *candidate {
|
||||||
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
|
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
|
||||||
match self.mir[bb].statements[stmt_idx].kind {
|
match self.mir[bb].statements[stmt_idx].kind {
|
||||||
StatementKind::Assign(_, Rvalue::Ref(_, _, Place::Local(index))) => {
|
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>,
|
fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> (u8, Lrc<IdxSet<Local>>) {
|
-> (u8, Lrc<BitSet<Local>>) {
|
||||||
// NB: This `borrow()` is guaranteed to be valid (i.e., the value
|
// NB: This `borrow()` is guaranteed to be valid (i.e., the value
|
||||||
// cannot yet be stolen), because `mir_validated()`, which steals
|
// cannot yet be stolen), because `mir_validated()`, which steals
|
||||||
// from `mir_const(), forces this query to execute before
|
// 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() {
|
if mir.return_ty().references_error() {
|
||||||
tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors");
|
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);
|
let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const);
|
||||||
|
@ -1220,7 +1219,7 @@ impl MirPass for QualifyAndPromoteConstants {
|
||||||
block.statements.retain(|statement| {
|
block.statements.retain(|statement| {
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::StorageDead(index) => {
|
StatementKind::StorageDead(index) => {
|
||||||
!promoted_temps.contains(&index)
|
!promoted_temps.contains(index)
|
||||||
}
|
}
|
||||||
_ => true
|
_ => true
|
||||||
}
|
}
|
||||||
|
@ -1228,7 +1227,7 @@ impl MirPass for QualifyAndPromoteConstants {
|
||||||
let terminator = block.terminator_mut();
|
let terminator = block.terminator_mut();
|
||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
|
TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
|
||||||
if promoted_temps.contains(&index) {
|
if promoted_temps.contains(index) {
|
||||||
terminator.kind = TerminatorKind::Goto {
|
terminator.kind = TerminatorKind::Goto {
|
||||||
target,
|
target,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use transform::{MirPass, MirSource};
|
use transform::{MirPass, MirSource};
|
||||||
use util::patch::MirPatch;
|
use util::patch::MirPatch;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ impl RemoveNoopLandingPads {
|
||||||
&self,
|
&self,
|
||||||
bb: BasicBlock,
|
bb: BasicBlock,
|
||||||
mir: &Mir,
|
mir: &Mir,
|
||||||
nop_landing_pads: &BitArray<BasicBlock>,
|
nop_landing_pads: &BitSet<BasicBlock>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
for stmt in &mir[bb].statements {
|
for stmt in &mir[bb].statements {
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
|
@ -111,7 +111,7 @@ impl RemoveNoopLandingPads {
|
||||||
|
|
||||||
let mut jumps_folded = 0;
|
let mut jumps_folded = 0;
|
||||||
let mut landing_pads_removed = 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
|
// This is a post-order traversal, so that if A post-dominates B
|
||||||
// then A will be visited before B.
|
// then A will be visited before B.
|
||||||
|
|
|
@ -14,7 +14,7 @@ use syntax_pos::Span;
|
||||||
|
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::mir::{self, Mir, Location};
|
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 transform::{MirPass, MirSource};
|
||||||
|
|
||||||
use dataflow::{do_dataflow, DebugFormatted};
|
use dataflow::{do_dataflow, DebugFormatted};
|
||||||
|
@ -46,7 +46,7 @@ impl MirPass for SanityCheck {
|
||||||
let param_env = tcx.param_env(def_id);
|
let param_env = tcx.param_env(def_id);
|
||||||
let move_data = MoveData::gather_moves(mir, tcx).unwrap();
|
let move_data = MoveData::gather_moves(mir, tcx).unwrap();
|
||||||
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
|
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 =
|
let flow_inits =
|
||||||
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
||||||
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
|
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.
|
// Okay, our search is over.
|
||||||
match move_data.rev_lookup.find(peeking_at_place) {
|
match move_data.rev_lookup.find(peeking_at_place) {
|
||||||
LookupResult::Exact(peek_mpi) => {
|
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: {}",
|
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
|
||||||
place, peeking_at_place, bit_state);
|
place, peeking_at_place, bit_state);
|
||||||
if !bit_state {
|
if !bit_state {
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
||||||
//! return.
|
//! return.
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::BitArray;
|
use rustc_data_structures::bit_set::BitSet;
|
||||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_dead_blocks(mir: &mut Mir) {
|
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) {
|
for (bb, _) in traversal::preorder(mir) {
|
||||||
seen.insert(bb.index());
|
seen.insert(bb.index());
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ impl MirPass for SimplifyLocals {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
_: MirSource,
|
_: MirSource,
|
||||||
mir: &mut Mir<'tcx>) {
|
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);
|
marker.visit_mir(mir);
|
||||||
// Return pointer and arguments are always live
|
// Return pointer and arguments are always live
|
||||||
marker.locals.insert(RETURN_PLACE);
|
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`.
|
/// Construct the mapping while swapping out unused stuff out from the `vec`.
|
||||||
fn make_local_map<'tcx, V>(
|
fn make_local_map<'tcx, V>(
|
||||||
vec: &mut IndexVec<Local, V>,
|
vec: &mut IndexVec<Local, V>,
|
||||||
mask: BitArray<Local>,
|
mask: BitSet<Local>,
|
||||||
) -> IndexVec<Local, Option<Local>> {
|
) -> IndexVec<Local, Option<Local>> {
|
||||||
let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
|
let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
|
||||||
let mut used = Local::new(0);
|
let mut used = Local::new(0);
|
||||||
|
@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DeclMarker {
|
struct DeclMarker {
|
||||||
pub locals: BitArray<Local>,
|
pub locals: BitSet<Local>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for DeclMarker {
|
impl<'tcx> Visitor<'tcx> for DeclMarker {
|
||||||
|
|
|
@ -37,7 +37,7 @@ use rustc::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc::mir::Local;
|
use rustc::mir::Local;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::ty::{item_path, TyCtxt};
|
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::indexed_vec::{Idx, IndexVec};
|
||||||
use rustc_data_structures::work_queue::WorkQueue;
|
use rustc_data_structures::work_queue::WorkQueue;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -46,7 +46,7 @@ use std::path::{Path, PathBuf};
|
||||||
use transform::MirSource;
|
use transform::MirSource;
|
||||||
use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
|
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
|
/// This gives the result of the liveness analysis at the boundary of
|
||||||
/// basic blocks.
|
/// basic blocks.
|
||||||
|
@ -243,8 +243,8 @@ impl<V: Idx> DefsUses<V> {
|
||||||
// X = 5
|
// X = 5
|
||||||
// // Defs = {}, Uses = {X}
|
// // Defs = {}, Uses = {X}
|
||||||
// use(X)
|
// use(X)
|
||||||
self.uses.remove(&index);
|
self.uses.remove(index);
|
||||||
self.defs.add(&index);
|
self.defs.insert(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_use(&mut self, index: V) {
|
fn add_use(&mut self, index: V) {
|
||||||
|
@ -258,8 +258,8 @@ impl<V: Idx> DefsUses<V> {
|
||||||
// X = 5
|
// X = 5
|
||||||
// // Defs = {}, Uses = {X}
|
// // Defs = {}, Uses = {X}
|
||||||
// use(X)
|
// use(X)
|
||||||
self.defs.remove(&index);
|
self.defs.remove(index);
|
||||||
self.uses.add(&index);
|
self.uses.insert(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ extern crate smallvec;
|
||||||
extern crate serialize as rustc_serialize; // used by deriving
|
extern crate serialize as rustc_serialize; // used by deriving
|
||||||
|
|
||||||
use rustc_data_structures::sync::Lock;
|
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::small_vec::OneVector;
|
||||||
pub use rustc_data_structures::thin_vec::ThinVec;
|
pub use rustc_data_structures::thin_vec::ThinVec;
|
||||||
use ast::AttrId;
|
use ast::AttrId;
|
||||||
|
@ -82,8 +82,8 @@ macro_rules! unwrap_or {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Globals {
|
pub struct Globals {
|
||||||
used_attrs: Lock<BitVector<AttrId>>,
|
used_attrs: Lock<GrowableBitSet<AttrId>>,
|
||||||
known_attrs: Lock<BitVector<AttrId>>,
|
known_attrs: Lock<GrowableBitSet<AttrId>>,
|
||||||
syntax_pos_globals: syntax_pos::Globals,
|
syntax_pos_globals: syntax_pos::Globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ impl Globals {
|
||||||
Globals {
|
Globals {
|
||||||
// We have no idea how many attributes their will be, so just
|
// We have no idea how many attributes their will be, so just
|
||||||
// initiate the vectors with 0 bits. We'll grow them as necessary.
|
// initiate the vectors with 0 bits. We'll grow them as necessary.
|
||||||
used_attrs: Lock::new(BitVector::new()),
|
used_attrs: Lock::new(GrowableBitSet::new_empty()),
|
||||||
known_attrs: Lock::new(BitVector::new()),
|
known_attrs: Lock::new(GrowableBitSet::new_empty()),
|
||||||
syntax_pos_globals: syntax_pos::Globals::new(),
|
syntax_pos_globals: syntax_pos::Globals::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue