Skip to content

Commit 39c4367

Browse files
committed
Add 'unchecked_disjoint_bitor' method to 'bool', 'i8', 'i16', 'i32', 'i64', 'i128', and 'isize'; Update existing 'unchecked_disjoint_bitor' docs; Add 'must_use' to 'unchecked_disjoint_bitor';
1 parent 1f8e04d commit 39c4367

3 files changed

Lines changed: 101 additions & 25 deletions

File tree

library/core/src/bool.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! impl bool {}
22
3+
use crate::intrinsics;
34
use crate::marker::Destruct;
5+
use crate::ub_checks::assert_unsafe_precondition;
46

57
impl bool {
68
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
@@ -137,4 +139,44 @@ impl bool {
137139
) -> Result<(), E> {
138140
if self { Ok(()) } else { Err(f()) }
139141
}
142+
143+
/// Disjoint, bitwise or. Computes `self | rhs`, assumming inequality.
144+
///
145+
/// Practically, this requires that `self | rhs` and `self ^ rhs` both yield the
146+
/// same result, allowing for any of the two to be emitted in code gen -- depending
147+
/// on whichever is cheapest.
148+
///
149+
/// # Examples
150+
///
151+
/// ```
152+
/// #![feature(disjoint_bitor)]
153+
///
154+
/// assert_eq!(
155+
/// // SAFETY: `false` and `true` have no ones in common.
156+
/// unsafe { false.unchecked_disjoint_bitor(true) },
157+
/// true,
158+
/// );
159+
/// ```
160+
///
161+
/// # Safety
162+
///
163+
/// This results in undefined behaviour if `self` and `rhs` are equal.
164+
#[unstable(feature = "disjoint_bitor", issue = "135758")]
165+
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
166+
#[must_use = "this returns the result of the operation, \
167+
without modifying the original"]
168+
#[inline]
169+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
170+
assert_unsafe_precondition!(
171+
check_language_ub,
172+
"attempt to disjoint or equal booleans",
173+
(
174+
lhs: $SelfT = self,
175+
rhs: $SelfT = rhs,
176+
) => lhs != rhs,
177+
);
178+
179+
// SAFETY: Same precondition.
180+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
181+
}
140182
}

library/core/src/num/int_macros.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,47 @@ macro_rules! int_impl {
13161316
if b { imp::overflow_panic::rem() } else { a }
13171317
}
13181318

1319+
/// Disjoint, bitwise or. Computes `self | rhs`, assumming no one bits in common.
1320+
///
1321+
/// Practically, this requires that `self | rhs`, `self ^ rhs`, and `self + rhs` all
1322+
/// yield the same result, allowing for any of the three to be emitted in code gen
1323+
/// -- depending on whichever is cheapest.
1324+
///
1325+
/// # Examples
1326+
///
1327+
/// ```
1328+
/// #![feature(disjoint_bitor)]
1329+
///
1330+
/// assert_eq!(
1331+
/// // SAFETY: `1` and `-2` have no ones in common.
1332+
#[doc = concat!(" unsafe { 1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2),")]
1333+
/// -1,
1334+
/// );
1335+
/// ```
1336+
///
1337+
/// # Safety
1338+
///
1339+
/// This results in undefined behaviour if `self` and `rhs` are not fully disjoint,
1340+
/// i.e. if `self & rhs == 0` doesn't apply.
1341+
#[unstable(feature = "disjoint_bitor", issue = "135758")]
1342+
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
1343+
#[must_use = "this returns the result of the operation, \
1344+
without modifying the original"]
1345+
#[inline]
1346+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
1347+
assert_unsafe_precondition!(
1348+
check_language_ub,
1349+
"attempt to disjoint or conjoint values",
1350+
(
1351+
lhs: $SelfT = self,
1352+
rhs: $SelfT = rhs,
1353+
) => (lhs & rhs) == 0,
1354+
);
1355+
1356+
// SAFETY: Same precondition.
1357+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
1358+
}
1359+
13191360
/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
13201361
///
13211362
/// # Examples
@@ -2933,7 +2974,6 @@ macro_rules! int_impl {
29332974
}
29342975
}
29352976

2936-
29372977
/// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
29382978
///
29392979
/// Returns a tuple of the remainder after dividing along with a boolean indicating whether an
@@ -2963,7 +3003,6 @@ macro_rules! int_impl {
29633003
}
29643004
}
29653005

2966-
29673006
/// Negates self, overflowing if this is equal to the minimum value.
29683007
///
29693008
/// 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 {
32283267
q
32293268
}
32303269

3231-
32323270
/// Calculates the least nonnegative remainder of `self` when
32333271
/// divided by `rhs`.
32343272
///

library/core/src/num/uint_macros.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,48 +1671,45 @@ macro_rules! uint_impl {
16711671
self % rhs
16721672
}
16731673

1674-
/// Same value as `self | other`, but UB if any bit position is set in both inputs.
1674+
/// Disjoint, bitwise or. Computes `self | rhs`, assumming no one bits in common.
16751675
///
1676-
/// This is a situational micro-optimization for places where you'd rather
1677-
/// use addition on some platforms and bitwise or on other platforms, based
1678-
/// on exactly which instructions combine better with whatever else you're
1679-
/// doing. Note that there's no reason to bother using this for places
1680-
/// where it's clear from the operations involved that they can't overlap.
1681-
/// For example, if you're combining `u16`s into a `u32` with
1682-
/// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will
1683-
/// know those sides of the `|` are disjoint without needing help.
1676+
/// Practically, this requires that `self | rhs`, `self ^ rhs`, and `self + rhs` all
1677+
/// yield the same result, allowing for any of the three to be emitted in code gen
1678+
/// -- depending on whichever is cheapest.
16841679
///
16851680
/// # Examples
16861681
///
16871682
/// ```
16881683
/// #![feature(disjoint_bitor)]
16891684
///
1690-
/// // SAFETY: `1` and `4` have no bits in common.
1691-
/// unsafe {
1692-
#[doc = concat!(" assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5);")]
1693-
/// }
1685+
/// assert_eq!(
1686+
/// // SAFETY: `1` and `4` have no ones in common.
1687+
#[doc = concat!(" unsafe { 1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4),")]
1688+
/// 5,
1689+
/// );
16941690
/// ```
16951691
///
16961692
/// # Safety
16971693
///
1698-
/// Requires that `(self & other) == 0`, otherwise it's immediate UB.
1699-
///
1700-
/// Equivalently, requires that `(self | other) == (self + other)`.
1694+
/// This results in undefined behaviour if `self` and `rhs` are not fully disjoint,
1695+
/// i.e. if `self & rhs == 0` doesn't apply.
17011696
#[unstable(feature = "disjoint_bitor", issue = "135758")]
17021697
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
1698+
#[must_use = "this returns the result of the operation, \
1699+
without modifying the original"]
17031700
#[inline]
1704-
pub const unsafe fn unchecked_disjoint_bitor(self, other: Self) -> Self {
1701+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
17051702
assert_unsafe_precondition!(
17061703
check_language_ub,
1707-
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot have overlapping bits"),
1704+
"attempt to disjoint or conjoint values",
17081705
(
17091706
lhs: $SelfT = self,
1710-
rhs: $SelfT = other,
1707+
rhs: $SelfT = rhs,
17111708
) => (lhs & rhs) == 0,
17121709
);
17131710

1714-
// SAFETY: Same precondition
1715-
unsafe { intrinsics::disjoint_bitor(self, other) }
1711+
// SAFETY: Same precondition.
1712+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
17161713
}
17171714

17181715
/// Returns the logarithm of the number with respect to an arbitrary base,
@@ -3684,7 +3681,6 @@ macro_rules! uint_impl {
36843681
self / rhs
36853682
}
36863683

3687-
36883684
/// Calculates the least remainder of `self` when divided by
36893685
/// `rhs`.
36903686
///

0 commit comments

Comments
 (0)