Rollup merge of #115626 - clarfonthey:unchecked-math, r=thomcc

Clean up unchecked_math, separate out unchecked_shifts

Tracking issue: #85122

Changes:

1. Remove `const_inherent_unchecked_arith` flag and make const-stability flags the same as the method feature flags. Given the number of other unsafe const fns already stabilised, it makes sense to just stabilise these in const context when they're stabilised.
2. Move `unchecked_shl` and `unchecked_shr` into a separate `unchecked_shifts` flag, since the semantics for them are unclear and they'll likely be stabilised separately as a result.
3. Add an `unchecked_neg` method exclusively to signed integers, under the `unchecked_neg` flag. This is because it's a new API and probably needs some time to marinate before it's stabilised, and while it *would* make sense to have a similar version for unsigned integers since `checked_neg` also exists for those there is absolutely no case where that would be a good idea, IMQHO.

The longer-term goal here is to prepare the `unchecked_math` methods for an FCP and stabilisation since they've existed for a while, their semantics are clear, and people seem in favour of stabilising them.
This commit is contained in:
Matthias Krüger 2023-11-01 11:29:41 +01:00 committed by GitHub
commit 260e07b0cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 23 deletions

View File

@ -134,7 +134,6 @@
#![feature(const_hash)]
#![feature(const_heap)]
#![feature(const_index_range_slice_index)]
#![feature(const_inherent_unchecked_arith)]
#![feature(const_int_unchecked_arith)]
#![feature(const_intrinsic_forget)]
#![feature(const_ipv4)]
@ -188,6 +187,8 @@
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
#![feature(strict_provenance)]
#![feature(unchecked_math)]
#![feature(unchecked_shifts)]
#![feature(utf16_extra)]
#![feature(utf16_extra_const)]
#![feature(variant_count)]

View File

@ -471,7 +471,7 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -539,7 +539,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -607,7 +607,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -740,6 +740,31 @@ pub const fn checked_neg(self) -> Option<Self> {
if unlikely!(b) {None} else {Some(a)}
}
/// Unchecked negation. Computes `-self`, assuming overflow cannot occur.
///
/// # Safety
///
/// This results in undefined behavior when
#[doc = concat!("`self == ", stringify!($SelfT), "::MIN`,")]
/// i.e. when [`checked_neg`] would return `None`.
///
#[doc = concat!("[`checked_neg`]: ", stringify!($SelfT), "::checked_neg")]
#[unstable(
feature = "unchecked_neg",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "unchecked_neg", issue = "85122")]
#[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) }
}
/// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
/// than or equal to the number of bits in `self`.
///
@ -772,13 +797,13 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
feature = "unchecked_math",
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[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 {
@ -820,13 +845,13 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
feature = "unchecked_math",
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[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 {
@ -1404,7 +1429,7 @@ pub const fn wrapping_neg(self) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
@ -1434,7 +1459,7 @@ pub const fn wrapping_shl(self, rhs: u32) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds

View File

@ -479,7 +479,7 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -548,7 +548,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -595,7 +595,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[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 {
@ -926,13 +926,13 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
feature = "unchecked_math",
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[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 {
@ -974,13 +974,13 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
feature = "unchecked_math",
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[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 {
@ -1418,7 +1418,7 @@ pub const fn wrapping_neg(self) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
@ -1451,7 +1451,7 @@ pub const fn wrapping_shl(self, rhs: u32) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds

View File

@ -1,4 +1,4 @@
#![feature(unchecked_math)]
#![feature(unchecked_shifts)]
fn main() {
unsafe {

View File

@ -1,4 +1,4 @@
#![feature(unchecked_math)]
#![feature(unchecked_shifts)]
fn main() {
unsafe {

View File

@ -2,7 +2,7 @@
// ignore-debug (because unchecked is checked in debug)
#![crate_type = "lib"]
#![feature(unchecked_math)]
#![feature(unchecked_shifts)]
// CHECK-LABEL: @unchecked_shl_unsigned_same
#[no_mangle]

View File

@ -1,7 +1,7 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![crate_type = "lib"]
#![feature(unchecked_math)]
#![feature(unchecked_shifts)]
// ignore-debug: the debug assertions prevent the inlining we are testing for
// compile-flags: -Zmir-opt-level=2 -Zinline-mir