diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 99268d6182f6c..3494885c992a0 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -1,5 +1,8 @@ //! impl bool {} +use crate::intrinsics; +use crate::ub_checks::assert_unsafe_precondition; + impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. @@ -128,4 +131,46 @@ impl bool { pub fn ok_or_else E>(self, f: F) -> Result<(), E> { if self { Ok(()) } else { Err(f()) } } + + /// Same value as `self | other`, but UB if any bit position is set in both inputs. + /// + /// This is a situational micro-optimization for places where you'd rather + /// use addition on some platforms and bitwise or on other platforms, based + /// on exactly which instructions combine better with whatever else you're + /// doing. Note that there's no reason to bother using this for places + /// where it's clear from the operations involved that they can't overlap. + /// For example, if you're combining `u16`s into a `u32` with + /// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will + /// know those sides of the `|` are disjoint without needing help. + /// + /// # Examples + /// + /// ``` + /// #![feature(disjoint_bitor)] + /// + /// // SAFETY: `false` and `true` have no ones in common. + /// unsafe { false.unchecked_disjoint_bitor(true) }; + /// ``` + /// + /// # Safety + /// + /// Requires that `self` and `rhs` are disjoint to each other, i.e. do not + /// have overlapping ones (thus `self & rhs == false`). By extension, requires + /// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent. + #[unstable(feature = "disjoint_bitor", issue = "135758")] + #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] + #[inline] + pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + "attempt to disjoint or conjoint values", + ( + lhs: bool = self, + rhs: bool = rhs, + ) => (lhs & rhs) == false, + ); + + // SAFETY: Same precondition. + unsafe { intrinsics::disjoint_bitor(self, rhs) } + } } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index c3460a6409069..5e816a48a92b6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1216,6 +1216,48 @@ macro_rules! int_impl { if b { overflow_panic::rem() } else { a } } + /// Same value as `self | other`, but UB if any bit position is set in both inputs. + /// + /// This is a situational micro-optimization for places where you'd rather + /// use addition on some platforms and bitwise or on other platforms, based + /// on exactly which instructions combine better with whatever else you're + /// doing. Note that there's no reason to bother using this for places + /// where it's clear from the operations involved that they can't overlap. + /// For example, if you're combining `u16`s into a `u32` with + /// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will + /// know those sides of the `|` are disjoint without needing help. + /// + /// # Examples + /// + /// ``` + /// #![feature(disjoint_bitor)] + /// + /// // SAFETY: `1` and `-2` have no ones in common. + #[doc = concat!("unsafe { assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2), -1) };")] + /// ``` + /// + /// # Safety + /// + /// Requires that `self` and `rhs` are disjoint to each other, i.e. do not + /// have overlapping ones (thus `self & rhs == 0`). By extension, requires + /// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent. + #[unstable(feature = "disjoint_bitor", issue = "135758")] + #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] + #[inline] + pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + "attempt to disjoint or conjoint values", + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => (lhs & rhs) == 0, + ); + + // SAFETY: Same precondition. + unsafe { intrinsics::disjoint_bitor(self, rhs) } + } + /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. /// /// # Examples diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 752498bfbd815..ac1294f1f4eb7 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1435,32 +1435,30 @@ macro_rules! uint_impl { /// ``` /// #![feature(disjoint_bitor)] /// - /// // SAFETY: `1` and `4` have no bits in common. - /// unsafe { - #[doc = concat!(" assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5);")] - /// } + /// // SAFETY: `1` and `4` have no ones in common. + #[doc = concat!("unsafe { assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5) };")] /// ``` /// /// # Safety /// - /// Requires that `(self & other) == 0`, otherwise it's immediate UB. - /// - /// Equivalently, requires that `(self | other) == (self + other)`. + /// Requires that `self` and `rhs` are disjoint to each other, i.e. do not + /// have overlapping ones (thus `self & rhs == 0`). By extension, requires + /// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent. #[unstable(feature = "disjoint_bitor", issue = "135758")] #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] #[inline] - pub const unsafe fn unchecked_disjoint_bitor(self, other: Self) -> Self { + pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self { assert_unsafe_precondition!( check_language_ub, - concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot have overlapping bits"), + "attempt to disjoint or conjoint values", ( lhs: $SelfT = self, - rhs: $SelfT = other, + rhs: $SelfT = rhs, ) => (lhs & rhs) == 0, ); - // SAFETY: Same precondition - unsafe { intrinsics::disjoint_bitor(self, other) } + // SAFETY: Same precondition. + unsafe { intrinsics::disjoint_bitor(self, rhs) } } /// Returns the logarithm of the number with respect to an arbitrary base,