diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 9b9d2f02550bd..463a973d44834 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -1,6 +1,8 @@ //! impl bool {} +use crate::intrinsics; use crate::marker::Destruct; +use crate::ub_checks::assert_unsafe_precondition; impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), @@ -137,4 +139,44 @@ impl bool { ) -> Result<(), E> { if self { Ok(()) } else { Err(f()) } } + + /// Disjoint, bitwise or. Computes `self | rhs`, assuming inequality. + /// + /// Practically, this requires that `self | rhs` and `self ^ rhs` both yield the + /// same result, allowing for any of the two to be emitted in code gen -- depending + /// on whichever is cheapest. + /// + /// # Examples + /// + /// ``` + /// #![feature(disjoint_bitor)] + /// + /// assert_eq!( + /// // SAFETY: `false` and `true` have no ones in common. + /// unsafe { false.unchecked_disjoint_bitor(true) }, + /// true, + /// ); + /// ``` + /// + /// # Safety + /// + /// This results in undefined behaviour if `self` and `rhs` are equal. + #[unstable(feature = "disjoint_bitor", issue = "135758")] + #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + "attempt to disjoint or equal booleans", + ( + lhs: bool = self, + rhs: bool = rhs, + ) => lhs != rhs, + ); + + // 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 4e7be6f065c9b..1f48be6ee0931 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1316,6 +1316,47 @@ macro_rules! int_impl { if b { imp::overflow_panic::rem() } else { a } } + /// Disjoint, bitwise or. Computes `self | rhs`, assuming no one bits in common. + /// + /// Practically, this requires that `self | rhs`, `self ^ rhs`, and `self + rhs` all + /// yield the same result, allowing for any of the three to be emitted in code gen + /// -- depending on whichever is cheapest. + /// + /// # Examples + /// + /// ``` + /// #![feature(disjoint_bitor)] + /// + /// assert_eq!( + /// // SAFETY: `1` and `-2` have no ones in common. + #[doc = concat!(" unsafe { 1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2) },")] + /// -1, + /// ); + /// ``` + /// + /// # Safety + /// + /// This results in undefined behaviour if `self` and `rhs` are not fully disjoint, + /// i.e. if `self & rhs == 0` doesn't apply. + #[unstable(feature = "disjoint_bitor", issue = "135758")] + #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[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 @@ -2933,7 +2974,6 @@ macro_rules! int_impl { } } - /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. /// /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an @@ -2963,7 +3003,6 @@ macro_rules! int_impl { } } - /// Negates self, overflowing if this is equal to the minimum value. /// /// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow @@ -3228,7 +3267,6 @@ macro_rules! int_impl { q } - /// Calculates the least nonnegative remainder of `self` when /// divided by `rhs`. /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 9bf765f1c4ed9..7dd79d852f22d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1671,48 +1671,45 @@ macro_rules! uint_impl { self % rhs } - /// Same value as `self | other`, but UB if any bit position is set in both inputs. + /// Disjoint, bitwise or. Computes `self | rhs`, assuming no one bits in common. /// - /// 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. + /// Practically, this requires that `self | rhs`, `self ^ rhs`, and `self + rhs` all + /// yield the same result, allowing for any of the three to be emitted in code gen + /// -- depending on whichever is cheapest. /// /// # Examples /// /// ``` /// #![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);")] - /// } + /// assert_eq!( + /// // SAFETY: `1` and `4` have no ones in common. + #[doc = concat!(" unsafe { 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)`. + /// This results in undefined behaviour if `self` and `rhs` are not fully disjoint, + /// i.e. if `self & rhs == 0` doesn't apply. #[unstable(feature = "disjoint_bitor", issue = "135758")] #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[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, @@ -3684,7 +3681,6 @@ macro_rules! uint_impl { self / rhs } - /// Calculates the least remainder of `self` when divided by /// `rhs`. ///