Skip to content

Commit 4dca6d7

Browse files
committed
Add SAFETY comments
1 parent 6efe566 commit 4dca6d7

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

src/lib.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ macro_rules! make_bitflags {
401401
$(
402402
n |= $enum::$variant as <$enum as $crate::_internal::RawBitFlags>::Numeric;
403403
)*
404+
// SAFETY: The value has been created from numeric values of the underlying
405+
// enum, so only valid bits are set.
404406
unsafe { $crate::BitFlags::<$enum>::from_bits_unchecked_c(
405407
n, $crate::BitFlags::CONST_TOKEN) }
406408
}
@@ -460,6 +462,8 @@ where
460462
#[must_use]
461463
#[inline(always)]
462464
pub fn from_bits_truncate(bits: T::Numeric) -> Self {
465+
// SAFETY: We're truncating out all the invalid bits, so the remaining
466+
// ones must be valid.
463467
unsafe { BitFlags::from_bits_unchecked(bits & T::ALL_BITS) }
464468
}
465469

@@ -486,6 +490,7 @@ where
486490
#[must_use]
487491
#[inline(always)]
488492
pub fn from_flag(flag: T) -> Self {
493+
// SAFETY: A value of the underlying enum is valid by definition.
489494
unsafe { Self::from_bits_unchecked(flag.bits()) }
490495
}
491496

@@ -586,6 +591,8 @@ where
586591
#[inline(always)]
587592
pub fn exactly_one(self) -> Option<T> {
588593
if self.val.is_power_of_two() {
594+
// SAFETY: By the invariant of the BitFlags type, all bits are valid
595+
// in isolation for the underlying enum.
589596
Some(unsafe { core::mem::transmute_copy(&self.val) })
590597
} else {
591598
None
@@ -677,6 +684,10 @@ where
677684
if self.rest.is_empty() {
678685
None
679686
} else {
687+
// SAFETY: `flag` will be a single bit, because
688+
// x & -x = x & (~x + 1), and the increment causes only one 0 -> 1 transition.
689+
// The invariant of `from_bits_unchecked` is satisfied, because bits & x
690+
// is a subset of bits, which we know are the valid bits.
680691
unsafe {
681692
let bits = self.rest.bits();
682693
let flag: T::Numeric = bits & bits.wrapping_neg();
@@ -867,6 +878,8 @@ where
867878
type Output = BitFlags<T>;
868879
#[inline(always)]
869880
fn bitor(self, other: B) -> BitFlags<T> {
881+
// SAFETY: The two operands are known to be composed of valid bits,
882+
// and 0 | 0 = 0 in the columns of the invalid bits.
870883
unsafe { BitFlags::from_bits_unchecked(self.bits() | other.into().bits()) }
871884
}
872885
}
@@ -879,6 +892,8 @@ where
879892
type Output = BitFlags<T>;
880893
#[inline(always)]
881894
fn bitand(self, other: B) -> BitFlags<T> {
895+
// SAFETY: The two operands are known to be composed of valid bits,
896+
// and 0 & 0 = 0 in the columns of the invalid bits.
882897
unsafe { BitFlags::from_bits_unchecked(self.bits() & other.into().bits()) }
883898
}
884899
}
@@ -891,6 +906,8 @@ where
891906
type Output = BitFlags<T>;
892907
#[inline(always)]
893908
fn bitxor(self, other: B) -> BitFlags<T> {
909+
// SAFETY: The two operands are known to be composed of valid bits,
910+
// and 0 ^ 0 = 0 in the columns of the invalid bits.
894911
unsafe { BitFlags::from_bits_unchecked(self.bits() ^ other.into().bits()) }
895912
}
896913
}
@@ -934,7 +951,7 @@ where
934951
type Output = BitFlags<T>;
935952
#[inline(always)]
936953
fn not(self) -> BitFlags<T> {
937-
unsafe { BitFlags::from_bits_unchecked(!self.bits() & T::ALL_BITS) }
954+
BitFlags::from_bits_truncate(!self.bits())
938955
}
939956
}
940957

0 commit comments

Comments
 (0)