Skip to content

Commit 845a872

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

File tree

3 files changed

+97
-12
lines changed

3 files changed

+97
-12
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 ones 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: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,48 @@ 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 ones in common.
1236+
#[doc = concat!("unsafe { assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2), -1) };")]
1237+
/// ```
1238+
///
1239+
/// # Safety
1240+
///
1241+
/// Requires that `self` and `rhs` are disjoint to each other, i.e. do not
1242+
/// have overlapping ones (thus `self & rhs == 0`). By extension, requires
1243+
/// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent.
1244+
#[unstable(feature = "disjoint_bitor", issue = "135758")]
1245+
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
1246+
#[inline]
1247+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
1248+
assert_unsafe_precondition!(
1249+
check_language_ub,
1250+
"attempt to disjoint or conjoint values",
1251+
(
1252+
lhs: $SelfT = self,
1253+
rhs: $SelfT = rhs,
1254+
) => (lhs & rhs) == 0,
1255+
);
1256+
1257+
// SAFETY: Same precondition.
1258+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
1259+
}
1260+
12191261
/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
12201262
///
12211263
/// # Examples

library/core/src/num/uint_macros.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,32 +1435,30 @@ macro_rules! uint_impl {
14351435
/// ```
14361436
/// #![feature(disjoint_bitor)]
14371437
///
1438-
/// // SAFETY: `1` and `4` have no bits in common.
1439-
/// unsafe {
1440-
#[doc = concat!(" assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5);")]
1441-
/// }
1438+
/// // SAFETY: `1` and `4` have no ones in common.
1439+
#[doc = concat!("unsafe { assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5) };")]
14421440
/// ```
14431441
///
14441442
/// # Safety
14451443
///
1446-
/// Requires that `(self & other) == 0`, otherwise it's immediate UB.
1447-
///
1448-
/// Equivalently, requires that `(self | other) == (self + other)`.
1444+
/// Requires that `self` and `rhs` are disjoint to each other, i.e. do not
1445+
/// have overlapping ones (thus `self & rhs == 0`). By extension, requires
1446+
/// that `self | rhs`, `self + rhs`, and `self ^ rhs` are equivalent.
14491447
#[unstable(feature = "disjoint_bitor", issue = "135758")]
14501448
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
14511449
#[inline]
1452-
pub const unsafe fn unchecked_disjoint_bitor(self, other: Self) -> Self {
1450+
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
14531451
assert_unsafe_precondition!(
14541452
check_language_ub,
1455-
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot have overlapping bits"),
1453+
"attempt to disjoint or conjoint values",
14561454
(
14571455
lhs: $SelfT = self,
1458-
rhs: $SelfT = other,
1456+
rhs: $SelfT = rhs,
14591457
) => (lhs & rhs) == 0,
14601458
);
14611459

1462-
// SAFETY: Same precondition
1463-
unsafe { intrinsics::disjoint_bitor(self, other) }
1460+
// SAFETY: Same precondition.
1461+
unsafe { intrinsics::disjoint_bitor(self, rhs) }
14641462
}
14651463

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

0 commit comments

Comments
 (0)