Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions library/core/src/bool.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -128,4 +131,46 @@ impl bool {
pub fn ok_or_else<E, F: FnOnce() -> 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) }
}
}
42 changes: 42 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 10 additions & 12 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading