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
42 changes: 42 additions & 0 deletions library/core/src/bool.rs
Original file line number Diff line number Diff line change
@@ -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),
Expand Down Expand Up @@ -137,4 +139,44 @@ impl bool {
) -> Result<(), E> {
if self { Ok(()) } else { Err(f()) }
}

/// Disjoint, bitwise or. Computes `self | rhs`, assuming inequality.

@traviscross traviscross May 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Disjoint, bitwise or. Computes `self | rhs`, assuming inequality.
/// Disjoint, bitwise or. Computes `self | rhs`, assuming at most one is `true`.

Right, or no? I'd expect (false, false) to be valid.

View changes since the review

///
/// 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` are inequal.

@traviscross traviscross May 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// // SAFETY: `false` and `true` are inequal.
/// // SAFETY: `false` and `true` have no bits in common.

As above.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually requested this move away from talking about bits with booleans, since I don't think users should need to think about the representation when thinking about values is sufficient. But looks like I gave a bad suggestion here.

So perhaps "has only one true" or "has at most one true"?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a false, false test to the doc would be good too

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// // SAFETY: `false` and `true` are inequal.
/// // SAFETY: `false` and `true` are not both `true`.

/// unsafe { false.unchecked_disjoint_bitor(true) },
/// true,
/// );
/// ```
///
/// # Safety
///
/// This results in undefined behaviour if `self` and `rhs` are equal.

@traviscross traviscross May 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This results in undefined behaviour if `self` and `rhs` are equal.
/// This results in undefined behavior if `self` and `rhs` are both `true`.

As above.

Nit: We generally use American spellings.

View changes since the review

#[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,
"bool::unchecked_disjoint_bitor cannot bitor equal values",

@traviscross traviscross May 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"bool::unchecked_disjoint_bitor cannot bitor equal values",
"bool::unchecked_disjoint_bitor cannot bitor overlapping ones",

As above.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, maybe "more than one true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"bool::unchecked_disjoint_bitor cannot bitor equal values",
"bool::unchecked_disjoint_bitor cannot bitor two `true` values",

(
lhs: bool = self,
rhs: bool = rhs,
) => lhs != rhs,

@traviscross traviscross May 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
) => lhs != rhs,
) => !(lhs && rhs),

Right? As above, I'd expect (false, false) to be valid.

View changes since the review

);

// SAFETY: Same precondition.
unsafe { intrinsics::disjoint_bitor(self, rhs) }
}
}
44 changes: 41 additions & 3 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot bitor overlapping ones"),
(
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 Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -3228,7 +3267,6 @@ macro_rules! int_impl {
q
}


/// Calculates the least nonnegative remainder of `self` when
/// divided by `rhs`.
///
Expand Down
40 changes: 18 additions & 22 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"assuming no one bits in common" -> "assuming there are no one bits in common."

Or something like "Computes self | rhs given the precondition that no set bits of the inputs overlap."

///
/// 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "code gen" -> either "codegen" or "code generation"

@bjoernager bjoernager May 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is wrong with "code gen" ? It's already used in the repo: https://github.com/search?q=repo%3Arust-lang%2Frust%20%22code%20gen%22&type=code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of those hits are part of "code generation" https://github.com/search?q=repo%3Arust-lang%2Frust+%2Fcode+gen%5Cb%2F&type=code. Loosely I think "gen" is considered an abbreviation rather than a word that can stand on its own, but we do consider "codegen" to be one.

Also we have codegen-units, codegen-backend etc. rather than code-gen-units and code-gen-backend.

/// -- 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"),
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot bitor overlapping ones"),
(
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 Expand Up @@ -3684,7 +3681,6 @@ macro_rules! uint_impl {
self / rhs
}


/// Calculates the least remainder of `self` when divided by
/// `rhs`.
///
Expand Down
Loading