Skip to content

Commit 280bee5

Browse files
author
Tage Johansson
committed
DenseBitSet: Solve a few bugs related to overflow in SHR.
1 parent c7076d9 commit 280bee5

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

compiler/rustc_index/src/bit_set/dense_bit_set.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<T> DenseBitSet<T> {
8181

8282
/// The tag for the `empty_unallocated` variant. The two most significant bits are
8383
/// `[0, 1]`.
84-
const EMPTY_UNALLOCATED_TAG_BITS: usize = 0b01 << (WORD_BITS - 2);
84+
const EMPTY_UNALLOCATED_TAG_BITS: usize = 0b01 << (usize::BITS - 2);
8585

8686
/// Create a new empty bit set with a given domain_size.
8787
///
@@ -115,7 +115,9 @@ impl<T> DenseBitSet<T> {
115115
*word = Word::MAX;
116116
}
117117
// Remove excessive bits on the last word.
118-
*words.last_mut().unwrap() >>= WORD_BITS - domain_size % WORD_BITS;
118+
// Trust me: this mask is correct.
119+
let last_word_mask = Word::MAX.wrapping_shr(domain_size.wrapping_neg() as u32);
120+
*words.last_mut().unwrap() &= last_word_mask;
119121
Self { on_heap: ManuallyDrop::new(on_heap) }
120122
}
121123
}
@@ -135,8 +137,8 @@ impl<T> DenseBitSet<T> {
135137
// safe to assume `self.inline`, or `self.on_heap`.
136138
#[inline(always)]
137139
pub const fn is_empty_unallocated(&self) -> bool {
138-
(unsafe { self.empty_unallocated }) >> usize::BITS as u32 - 2
139-
== Self::EMPTY_UNALLOCATED_TAG_BITS >> usize::BITS as u32 - 2
140+
const MASK: usize = usize::MAX << usize::BITS - 2;
141+
(unsafe { self.empty_unallocated } & MASK) == Self::EMPTY_UNALLOCATED_TAG_BITS
140142
}
141143

142144
/// Check if `self` is `empty_unallocated` and if so return the number of words required to

0 commit comments

Comments
 (0)