Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -145,11 +145,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
self.mutate_place(location, *resume_arg, Deep);
}
TerminatorKind::Reattach { continuation } => {
// FIXME(jhilton): Should we be invalidating locals in the current basic block as well? I think we should be,
// FIXME(jhilton): Should we be invalidating locals in the current basic block as well? I think we should be,
// for consistency with what we did in the type-checker. My concern is that we only want to kill locals for the
// *current block*, which I don't think we're currently expressing. One way to think about modeling this
// is that we can imagine Detach as pushing a new stack frame for the spawned task so that way we don't
// invalidate all locals, only the locals that are generated in the spawned task. Alternatively, loan invalidation
// invalidate all locals, only the locals that are generated in the spawned task. Alternatively, loan invalidation
// can be handled by however blocks handle this situation.
let borrow_set = self.borrow_set;
let end_spawned_task =
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_data_structures/src/work_queue.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -42,3 +42,11 @@ impl<T: Idx> WorkQueue<T> {
}
}
}

impl<T: Idx> Extend<T> for WorkQueue<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for element in iter {
self.insert(element);
}
}
}
59 changes: 57 additions & 2 deletions compiler/rustc_index/src/bit_set.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -677,8 +677,63 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
unimplemented!("implement if/when necessary");
}

fn intersect(&mut self, _other: &ChunkedBitSet<T>) -> bool {
unimplemented!("implement if/when necessary");
fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
debug_assert_eq!(self.chunks.len(), other.chunks.len());

let mut changed = false;
for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
match (&mut self_chunk, &other_chunk) {
(_, Ones(_)) | (Zeros(_), _) => {}
(Ones(self_chunk_domain_size), Zeros(other_chunk_domain_size))
| (Ones(self_chunk_domain_size), Mixed(other_chunk_domain_size, ..))
| (Mixed(self_chunk_domain_size, ..), Zeros(other_chunk_domain_size, ..)) => {
// `other_chunk` fully overwrites `self_chunk`
debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
*self_chunk = other_chunk.clone();
changed = true;
}
(
Mixed(
self_chunk_domain_size,
ref mut self_chunk_count,
ref mut self_chunk_words,
),
Mixed(other_chunk_domain_size, _other_chunk_count, other_chunk_words),
) => {
debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
// First check if the operation would change
// `self_chunk.words`. If not, we can avoid allocating some
// words, and this happens often enough that it's a
// performance win. Also, we only need to operate on the
// in-use words, hence the slicing.
let op = |a, b| a & b;
let num_words = num_words(*self_chunk_domain_size as usize);
if bitwise_changes(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
) {
let self_chunk_words = Rc::make_mut(self_chunk_words);
let has_changed = bitwise(
&mut self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
);
debug_assert!(has_changed);
*self_chunk_count = self_chunk_words[0..num_words]
.iter()
.map(|w| w.count_ones() as ChunkSize)
.sum();
if *self_chunk_count == *self_chunk_domain_size {
*self_chunk = Ones(*self_chunk_domain_size);
}
changed = true;
}
}
}
}
changed
}
}

Expand Down
86 changes: 86 additions & 0 deletions compiler/rustc_index/src/bit_set/tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -437,6 +437,92 @@ fn chunked_bitset_iter() {
check_iter(&bit, &vec);
}

#[test]
fn chunked_bitset_intersect_empty_empty() {
let vec: Vec<usize> = Vec::new();
let n = 10000;
let mut bit1 = with_elements_chunked(&vec, n);
let mut bit2 = with_elements_chunked(&vec, n);
assert!(!bit1.intersect(&bit2));
assert_eq!(bit1, bit2);
assert!(!bit2.intersect(&bit1));
assert_eq!(bit1, bit2);
}

#[test]
fn chunked_bitset_intersect_empty_filled() {
let n = 10000;
let vec1: Vec<usize> = Vec::new();
let vec2: Vec<usize> = (0..n).collect();
let mut bit1 = with_elements_chunked(&vec1, n);
let mut bit2 = with_elements_chunked(&vec2, n);
let bit1_clone = bit1.clone();
assert!(!bit1.intersect(&bit2));
assert_eq!(bit1, bit1_clone);
assert!(bit2.intersect(&bit1));
assert_eq!(bit2, bit1);
}

#[test]
fn chunked_bitset_intersect_empty_mixed() {
let n = 10000;
let vec1: Vec<usize> = Vec::new();
let vec2: Vec<usize> = vec![0, 1, 2, 2010, 2047, 2099, 6000, 6002, 6004];
let mut bit1 = with_elements_chunked(&vec1, n);
let mut bit2 = with_elements_chunked(&vec2, n);
let bit1_clone = bit1.clone();
assert!(!bit1.intersect(&bit2));
assert_eq!(bit1, bit1_clone);
assert!(bit2.intersect(&bit1));
assert_eq!(bit2, bit1);
}

#[test]
fn chunked_bitset_intersect_filled_filled() {
let n = 10000;
let vec1: Vec<usize> = (0..n).collect();
let vec2: Vec<usize> = (0..n).collect();
let mut bit1 = with_elements_chunked(&vec1, n);
let mut bit2 = with_elements_chunked(&vec2, n);
let bit1_clone = bit1.clone();
assert!(!bit1.intersect(&bit2));
assert_eq!(bit1, bit1_clone);
assert!(!bit2.intersect(&bit1));
assert_eq!(bit2, bit1);
}

#[test]
fn chunked_bitset_intersect_filled_mixed() {
let n = 10000;
let vec1: Vec<usize> = (0..n).collect();
let vec2: Vec<usize> = vec![0, 1, 2, 2010, 2047, 2099, 6000, 6002, 6004];
let vec_expected: Vec<usize> = vec![0, 1, 2, 2010, 2047, 2099, 6000, 6002, 6004];
let mut bit1 = with_elements_chunked(&vec1, n);
let mut bit2 = with_elements_chunked(&vec2, n);
let bit_expected = with_elements_chunked(&vec_expected, n);
let bit1_clone = bit1.clone();
assert!(bit1.intersect(&bit2));
assert_eq!(bit1, bit_expected);
assert!(!bit2.intersect(&bit1_clone));
assert_eq!(bit2, bit_expected);
}

#[test]
fn chunked_bitset_intersect_mixed_mixed() {
let n = 10000;
let vec1: Vec<usize> = vec![0, 1, 2, 2010, 5, 10, 20];
let vec2: Vec<usize> = vec![0, 1, 2, 2010, 2047, 2099, 6000, 6002, 6004];
let vec_expected: Vec<usize> = vec![0, 1, 2, 2010];
let mut bit1 = with_elements_chunked(&vec1, n);
let mut bit2 = with_elements_chunked(&vec2, n);
let expected = with_elements_chunked(&vec_expected, n);
let bit1_clone = bit1.clone();
assert!(bit1.intersect(&bit2));
assert_eq!(bit1, expected);
assert!(bit2.intersect(&bit1_clone));
assert_eq!(bit2, expected);
}

#[test]
fn grow() {
let mut set: GrowableBitSet<usize> = GrowableBitSet::with_capacity(65);
Expand Down
29 changes: 22 additions & 7 deletions compiler/rustc_mir_build/src/build/matches/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -553,6 +553,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

fn should_inject_fake_read(&self, initializer_id: ExprId) -> bool {
// For spawns, we don't want to emit a FakeRead since the value will only be defined on sync.
// They're nested inside a Scope consistently, so we just unwrap the scope.
match self.thir[initializer_id] {
Expr { kind: ExprKind::Scope { value, .. }, .. } => {
!matches!(self.thir[value], Expr { kind: ExprKind::CilkSpawn { .. }, .. })
}
_ => true,
}
}

pub(super) fn expr_into_pattern(
&mut self,
mut block: BasicBlock,
Expand All@@ -566,9 +577,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
unpack!(block = self.expr_into_dest(place, block, initializer_id));

// Inject a fake read, see comments on `FakeReadCause::ForLet`.
let source_info = self.source_info(irrefutable_pat.span);
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place);
if self.should_inject_fake_read(initializer_id) {
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
let source_info = self.source_info(irrefutable_pat.span);
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place);
}

self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
block.unit()
Expand DownExpand Up@@ -597,10 +610,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
unpack!(block = self.expr_into_dest(place, block, initializer_id));

// Inject a fake read, see comments on `FakeReadCause::ForLet`.
let pattern_source_info = self.source_info(irrefutable_pat.span);
let cause_let = FakeReadCause::ForLet(None);
self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
if self.should_inject_fake_read(initializer_id) {
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
let pattern_source_info = self.source_info(irrefutable_pat.span);
let cause_let = FakeReadCause::ForLet(None);
self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
}

let ty_source_info = self.source_info(annotation.span);

Expand Down
Loading