-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add debug_assert_nounwind to unchecked_{add,sub,neg,mul,shl,shr} methods (haunted PR) #117494
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -510,9 +510,15 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_add`. | ||
unsafe { intrinsics::unchecked_add(self, rhs) } | ||
debug_assert_nounwind!( | ||
!self.overflowing_add(rhs).1, | ||
concat!(stringify!($SelfT), "::unchecked_add cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
unsafe { | ||
let lhs = self; | ||
intrinsics::unchecked_add(lhs, rhs) | ||
} | ||
} | ||
|
||
/// Checked addition with an unsigned integer. Computes `self + rhs`, | ||
|
@@ -648,9 +654,15 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_sub`. | ||
unsafe { intrinsics::unchecked_sub(self, rhs) } | ||
debug_assert_nounwind!( | ||
!self.overflowing_sub(rhs).1, | ||
concat!(stringify!($SelfT), "::unchecked_sub cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
unsafe { | ||
let lhs = self; | ||
intrinsics::unchecked_sub(lhs, rhs) | ||
} | ||
} | ||
|
||
/// Checked subtraction with an unsigned integer. Computes `self - rhs`, | ||
|
@@ -786,9 +798,15 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_mul`. | ||
unsafe { intrinsics::unchecked_mul(self, rhs) } | ||
debug_assert_nounwind!( | ||
!self.overflowing_mul(rhs).1, | ||
concat!(stringify!($SelfT), "::unchecked_mul cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
unsafe { | ||
let lhs = self; | ||
intrinsics::unchecked_mul(lhs, rhs) | ||
} | ||
} | ||
|
||
/// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` | ||
|
@@ -1125,9 +1143,15 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_neg(self) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_neg`. | ||
unsafe { intrinsics::unchecked_sub(0, self) } | ||
debug_assert_nounwind!( | ||
!self.overflowing_neg().1, | ||
concat!(stringify!($SelfT), "::unchecked_neg cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
unsafe { | ||
let n = self; | ||
intrinsics::unchecked_sub(0, n) | ||
} | ||
} | ||
|
||
/// Strict negation. Computes `-self`, panicking if `self == MIN`. | ||
|
@@ -1179,7 +1203,7 @@ macro_rules! int_impl { | |
#[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] | ||
#[must_use = "this returns the result of the operation, \ | ||
without modifying the original"] | ||
#[inline] | ||
#[inline(always)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, functions which are My PR to stop this behavior of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, I initially added this after the stuff I mentioned here, but I did just leave it based upon assumptions that are probably wrong, so, I can remove it. Note that this does show up for the other unchecked operations and that shift is the only one marking them without always. |
||
pub const fn checked_shl(self, rhs: u32) -> Option<Self> { | ||
let (a, b) = self.overflowing_shl(rhs); | ||
if unlikely!(b) { None } else { Some(a) } | ||
|
@@ -1241,10 +1265,17 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_shl`. | ||
debug_assert_nounwind!( | ||
rhs < Self::BITS, | ||
concat!(stringify!($SelfT), "::unchecked_shl cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
// Any legal shift amount is losslessly representable in the self type. | ||
unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } | ||
unsafe { | ||
let lhs = self; | ||
let rhs = conv_rhs_for_unchecked_shift!($SelfT, rhs); | ||
intrinsics::unchecked_shl(lhs, rhs) | ||
} | ||
} | ||
|
||
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is | ||
|
@@ -1262,7 +1293,7 @@ macro_rules! int_impl { | |
#[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] | ||
#[must_use = "this returns the result of the operation, \ | ||
without modifying the original"] | ||
#[inline] | ||
#[inline(always)] | ||
pub const fn checked_shr(self, rhs: u32) -> Option<Self> { | ||
let (a, b) = self.overflowing_shr(rhs); | ||
if unlikely!(b) { None } else { Some(a) } | ||
|
@@ -1324,10 +1355,17 @@ macro_rules! int_impl { | |
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_shr`. | ||
debug_assert_nounwind!( | ||
rhs < Self::BITS, | ||
concat!(stringify!($SelfT), "::unchecked_shr cannot overflow"), | ||
); | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
// Any legal shift amount is losslessly representable in the self type. | ||
unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } | ||
unsafe { | ||
let lhs = self; | ||
let rhs = conv_rhs_for_unchecked_shift!($SelfT, rhs); | ||
intrinsics::unchecked_shr(lhs, rhs) | ||
} | ||
} | ||
|
||
/// Checked absolute value. Computes `self.abs()`, returning `None` if | ||
|
@@ -1991,7 +2029,10 @@ macro_rules! int_impl { | |
// SAFETY: the masking by the bitsize of the type ensures that we do not shift | ||
// out of bounds | ||
unsafe { | ||
self.unchecked_shl(rhs & (Self::BITS - 1)) | ||
// FIXME: we can't optimize out the extra check here, | ||
// so, we can't just call the method for now | ||
let rhs = conv_rhs_for_unchecked_shift!($SelfT, rhs & (Self::BITS - 1)); | ||
intrinsics::unchecked_shl(self, rhs) | ||
} | ||
} | ||
|
||
|
@@ -2021,7 +2062,10 @@ macro_rules! int_impl { | |
// SAFETY: the masking by the bitsize of the type ensures that we do not shift | ||
// out of bounds | ||
unsafe { | ||
self.unchecked_shr(rhs & (Self::BITS - 1)) | ||
// FIXME: we can't optimize out the extra check here, | ||
// so, we can't just call the method for now | ||
let rhs = conv_rhs_for_unchecked_shift!($SelfT, rhs & (Self::BITS - 1)); | ||
intrinsics::unchecked_shr(self, rhs) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This extra
let
is going to cause more LLVM IR to be generated in order to have debuginfo for it. I learned about this unfortunate behavior only recently:rust/library/core/src/intrinsics.rs
Lines 2688 to 2691 in 8f359be
I wish I had a way to tell rustc that we don't need variable-level debuginfo for a span of code, but here we are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh, I didn't realise it got all the way to the LLVM IR level. It's unfortunate, but I'll remove the extra lets from these operations. (Will wait until current perf run finishes before doing this.)