Skip to content

Commit 943d050

Browse files
committed
Add 'unchecked_disjoint_bitor' method to 'bool', 'i8', 'i16', 'i32', 'i64', 'i128', and 'isize';
1 parent 99b9a88 commit 943d050

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

library/core/src/bool.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! impl bool {}
22
3+
use crate::intrinsics;
4+
use crate::ub_checks::assert_unsafe_precondition;
5+
36
impl bool {
47
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
58
/// or `None` otherwise.
@@ -128,4 +131,46 @@ impl bool {
128131
pub fn ok_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(), E> {
129132
if self { Ok(()) } else { Err(f()) }
130133
}
134+
135+
/// Same value as `self | other`, but UB if any bit position is set in both inputs.
136+
///
137+
/// This is a situational micro-optimization for places where you'd rather
138+
/// use addition on some platforms and bitwise or on other platforms, based
139+
/// on exactly which instructions combine better with whatever else you're
140+
/// doing. Note that there's no reason to bother using this for places
141+
/// where it's clear from the operations involved that they can't overlap.
142+
/// For example, if you're combining `u16`s into a `u32` with
143+
/// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will
144+
/// know those sides of the `|` are disjoint without needing help.
145+
///
146+
/// # Examples
147+
///
148+
/// ```
149+
/// #![feature(disjoint_bitor)]
150+
///
151+
/// // SAFETY: `false` and `true` have no bits in common.
152+
/// unsafe { false.unchecked_disjoint_bitor(true) }
153+
/// ```
154+
///
155+
/// # Safety
156+
///
157+
/// Requires that `self` and `rhs` are disjoint to each other, i.e. do not
158+
/// have overlapping ones (thus `self & rhs == false`). By extension, requires
159+
/// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent.
160+
#[unstable(feature = "disjoint_bitor", issue = "135758")]
161+
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
162+
#[inline]
163+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
164+
assert_unsafe_precondition!(
165+
check_language_ub,
166+
"attempt to disjoint or conjoint values",
167+
(
168+
lhs: bool = self,
169+
rhs: bool = rhs,
170+
) => (lhs & rhs) == false,
171+
);
172+
173+
// SAFETY: Same precondition.
174+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
175+
}
131176
}

library/core/src/num/int_macros.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,50 @@ macro_rules! int_impl {
12161216
if b { overflow_panic::rem() } else { a }
12171217
}
12181218

1219+
/// Same value as `self | other`, but UB if any bit position is set in both inputs.
1220+
///
1221+
/// This is a situational micro-optimization for places where you'd rather
1222+
/// use addition on some platforms and bitwise or on other platforms, based
1223+
/// on exactly which instructions combine better with whatever else you're
1224+
/// doing. Note that there's no reason to bother using this for places
1225+
/// where it's clear from the operations involved that they can't overlap.
1226+
/// For example, if you're combining `u16`s into a `u32` with
1227+
/// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will
1228+
/// know those sides of the `|` are disjoint without needing help.
1229+
///
1230+
/// # Examples
1231+
///
1232+
/// ```
1233+
/// #![feature(disjoint_bitor)]
1234+
///
1235+
/// // SAFETY: `1` and `-2` have no bits in common.
1236+
/// unsafe {
1237+
#[doc = concat!(" assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2), -1);")]
1238+
/// }
1239+
/// ```
1240+
///
1241+
/// # Safety
1242+
///
1243+
/// Requires that `self` and `rhs` are disjoint to each other, i.e. do not
1244+
/// have overlapping ones (thus `self & rhs == 0`). By extension, requires
1245+
/// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent.
1246+
#[unstable(feature = "disjoint_bitor", issue = "135758")]
1247+
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
1248+
#[inline]
1249+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
1250+
assert_unsafe_precondition!(
1251+
check_language_ub,
1252+
"attempt to disjoint or conjoint values",
1253+
(
1254+
lhs: $SelfT = self,
1255+
rhs: $SelfT = rhs,
1256+
) => (lhs & rhs) == 0,
1257+
);
1258+
1259+
// SAFETY: Same precondition.
1260+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
1261+
}
1262+
12191263
/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
12201264
///
12211265
/// # Examples

library/core/src/num/uint_macros.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,24 +1443,24 @@ macro_rules! uint_impl {
14431443
///
14441444
/// # Safety
14451445
///
1446-
/// Requires that `(self & other) == 0`, otherwise it's immediate UB.
1447-
///
1448-
/// Equivalently, requires that `(self | other) == (self + other)`.
1446+
/// Requires that `self` and `rhs` are disjoint to each other, i.e. do not
1447+
/// have overlapping ones (thus `self & rhs == 0`). By extension, requires
1448+
/// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent.
14491449
#[unstable(feature = "disjoint_bitor", issue = "135758")]
14501450
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
14511451
#[inline]
1452-
pub const unsafe fn unchecked_disjoint_bitor(self, other: Self) -> Self {
1452+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
14531453
assert_unsafe_precondition!(
14541454
check_language_ub,
1455-
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot have overlapping bits"),
1455+
"attempt to disjoint or conjoint values",
14561456
(
14571457
lhs: $SelfT = self,
1458-
rhs: $SelfT = other,
1458+
rhs: $SelfT = rhs,
14591459
) => (lhs & rhs) == 0,
14601460
);
14611461

1462-
// SAFETY: Same precondition
1463-
unsafe { intrinsics::disjoint_bitor(self, other) }
1462+
// SAFETY: Same precondition.
1463+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
14641464
}
14651465

14661466
/// Returns the logarithm of the number with respect to an arbitrary base,

0 commit comments

Comments
 (0)