mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #122520 - scottmcm:stabilize_unchecked_math_basics, r=jhpratt
Stabilize `unchecked_{add,sub,mul}` Tracking issue: #85122 I think we might as well just stabilize these basic three. They're the ones that have `nuw`/`nsw` flags in LLVM. Notably, this doesn't include the potentially-more-complex or -more-situational things like `unchecked_neg` or `unchecked_shr` that are under different feature flags. To quote Ralf https://github.com/rust-lang/rust/issues/85122#issuecomment-1681669646, > Are there any objections to stabilizing at least `unchecked_{add,sub,mul}`? For those there shouldn't be any surprises about what their safety requirements are. *Semantially* these are [already available on stable, even in `const`, via](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bdb1ff889b61950897f1e9f56d0c9a36) `checked_*`+`unreachable_unchecked`. So IMHO we might as well just let people write them directly, rather than try to go through a `let Some(x) = x.checked_add(y) else { unsafe { hint::unreachable_unchecked() }};` dance. I added additional text to each method to attempt to better describe the behaviour and encourage `wrapping_*` instead. r? rust-lang/libs-api
This commit is contained in:
commit
faae5f1ffe
@ -166,7 +166,6 @@
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(try_with_capacity)]
|
||||
#![feature(tuple_trait)]
|
||||
#![feature(unchecked_math)]
|
||||
#![feature(unicode_internals)]
|
||||
#![feature(unsize)]
|
||||
#![feature(utf8_chunks)]
|
||||
|
@ -2240,24 +2240,27 @@ extern "rust-intrinsic" {
|
||||
/// Returns the result of an unchecked addition, resulting in
|
||||
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_add` on the various
|
||||
/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns the result of an unchecked subtraction, resulting in
|
||||
/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
|
||||
/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns the result of an unchecked multiplication, resulting in
|
||||
/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
|
||||
/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
|
@ -137,7 +137,6 @@
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_hint_assert_unchecked)]
|
||||
#![feature(const_index_range_slice_index)]
|
||||
#![feature(const_int_unchecked_arith)]
|
||||
#![feature(const_intrinsic_copy)]
|
||||
#![feature(const_intrinsic_forget)]
|
||||
#![feature(const_ipv4)]
|
||||
@ -197,7 +196,6 @@
|
||||
#![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)]
|
||||
|
@ -492,21 +492,25 @@ macro_rules! int_impl {
|
||||
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_add(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_add`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_add`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
@ -630,21 +634,25 @@ macro_rules! int_impl {
|
||||
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_sub(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_sub`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_sub`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
@ -768,21 +776,25 @@ macro_rules! int_impl {
|
||||
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_mul(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_mul`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_mul`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
|
@ -500,21 +500,25 @@ macro_rules! uint_impl {
|
||||
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_add(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_add`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_add`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
@ -644,21 +648,25 @@ macro_rules! uint_impl {
|
||||
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_sub(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_sub`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_sub`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
@ -726,21 +734,25 @@ macro_rules! uint_impl {
|
||||
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
|
||||
/// cannot occur.
|
||||
///
|
||||
/// Calling `x.unchecked_mul(y)` is semantically equivalent to calling
|
||||
/// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`.
|
||||
///
|
||||
/// If you're just trying to avoid the panic in debug mode, then **do not**
|
||||
/// use this. Instead, you're looking for [`wrapping_mul`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when
|
||||
#[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")]
|
||||
/// i.e. when [`checked_mul`] would return `None`.
|
||||
///
|
||||
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
|
||||
#[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")]
|
||||
#[unstable(
|
||||
feature = "unchecked_math",
|
||||
reason = "niche optimization path",
|
||||
issue = "85122",
|
||||
)]
|
||||
#[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")]
|
||||
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[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 {
|
||||
|
@ -1029,8 +1029,6 @@ impl<T: ?Sized> *const T {
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||
// We could always go back to wrapping if unchecked becomes unacceptable
|
||||
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn sub(self, count: usize) -> Self
|
||||
|
@ -1119,8 +1119,6 @@ impl<T: ?Sized> *mut T {
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
||||
// We could always go back to wrapping if unchecked becomes unacceptable
|
||||
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn sub(self, count: usize) -> Self
|
||||
|
@ -702,8 +702,6 @@ impl<T: ?Sized> NonNull<T> {
|
||||
#[unstable(feature = "non_null_convenience", issue = "117691")]
|
||||
#[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")]
|
||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||
// We could always go back to wrapping if unchecked becomes unacceptable
|
||||
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn sub(self, count: usize) -> Self
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
|
||||
fn main() {
|
||||
// MAX overflow
|
||||
let _val = unsafe { 40000u16.unchecked_add(30000) }; //~ ERROR: overflow executing `unchecked_add`
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
|
||||
fn main() {
|
||||
// MIN overflow
|
||||
let _val = unsafe { (-30000i16).unchecked_add(-8000) }; //~ ERROR: overflow executing `unchecked_add`
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
fn main() {
|
||||
// MAX overflow
|
||||
let _val = unsafe { 300u16.unchecked_mul(250u16) }; //~ ERROR: overflow executing `unchecked_mul`
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
fn main() {
|
||||
// MIN overflow
|
||||
let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; //~ ERROR: overflow executing `unchecked_mul`
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
fn main() {
|
||||
// MIN overflow
|
||||
let _val = unsafe { 14u32.unchecked_sub(22) }; //~ ERROR: overflow executing `unchecked_sub`
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(unchecked_math)]
|
||||
fn main() {
|
||||
// MAX overflow
|
||||
let _val = unsafe { 30000i16.unchecked_sub(-7000) }; //~ ERROR: overflow executing `unchecked_sub`
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_int_unchecked_arith)]
|
||||
|
||||
|
||||
use std::intrinsics;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user