Skip to content

Commit 99fc5a1

Browse files
Tage Johanssonlqd
Tage Johansson
authored andcommitted
Implement ThinBitSet::only_one_elem().
1 parent bcf90b6 commit 99fc5a1

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

compiler/rustc_index/src/bit_set/thin_bit_set.rs

+36
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,34 @@ impl<T: Idx> ThinBitSet<T> {
581581
}
582582
}
583583

584+
/// Returns `Some(elem)` if the set contains exactly one elemement otherwise returns `None`.
585+
#[inline(always)]
586+
pub fn only_one_elem(&self) -> Option<T> {
587+
if self.is_inline() {
588+
let word = unsafe { self.inline } ^ Self::IS_INLINE_TAG_BIT;
589+
if word.is_power_of_two() { Some(T::new(word.trailing_zeros() as usize)) } else { None }
590+
} else if self.is_empty_unallocated() {
591+
None
592+
} else {
593+
let words = self.on_heap().unwrap().as_slice();
594+
let mut found_elem = None;
595+
for (i, &word) in words.iter().enumerate() {
596+
if word > 0 {
597+
if found_elem.is_some() {
598+
return None;
599+
}
600+
if word.is_power_of_two() {
601+
found_elem =
602+
Some(T::new(i * WORD_BITS as usize + word.trailing_zeros() as usize));
603+
} else {
604+
return None;
605+
}
606+
}
607+
}
608+
found_elem
609+
}
610+
}
611+
584612
#[inline]
585613
pub fn insert_range(&mut self, range: Range<T>) {
586614
if let Some(end) = range.end.index().checked_sub(1) {
@@ -1633,6 +1661,14 @@ mod tests {
16331661
assert_eq!(set_1.count(), set_1_reference.iter().filter(|&&x| x).count());
16341662
assert_eq!(set_2.count(), set_2_reference.iter().filter(|&&x| x).count());
16351663

1664+
// Check `only_one_elem()`.
1665+
if let Some(elem) = set_1.only_one_elem() {
1666+
assert_eq!(set_1.count(), 1);
1667+
assert_eq!(elem, set_1.iter().next().unwrap());
1668+
} else {
1669+
assert_ne!(set_1.count(), 1);
1670+
}
1671+
16361672
// Check `last_set_in()`.
16371673
if domain_size > 0 {
16381674
let range = rng.sample_range(domain_size - 1);

0 commit comments

Comments
 (0)