Skip to content

Commit 0421b4a

Browse files
committed
Auto merge of rust-lang#122520 - scottmcm:stabilize_unchecked_math_basics, r=jhpratt
Stabilize `unchecked_{add,sub,mul}` Tracking issue: rust-lang#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 rust-lang#85122 (comment), > 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
2 parents f732282 + 19aa96c commit 0421b4a

File tree

8 files changed

+69
-51
lines changed

8 files changed

+69
-51
lines changed

alloc/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@
166166
#![feature(try_trait_v2)]
167167
#![feature(try_with_capacity)]
168168
#![feature(tuple_trait)]
169-
#![feature(unchecked_math)]
170169
#![feature(unicode_internals)]
171170
#![feature(unsize)]
172171
#![feature(utf8_chunks)]

core/src/intrinsics.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -2240,24 +2240,27 @@ extern "rust-intrinsic" {
22402240
/// Returns the result of an unchecked addition, resulting in
22412241
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
22422242
///
2243-
/// This intrinsic does not have a stable counterpart.
2244-
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
2243+
/// The stable counterpart of this intrinsic is `unchecked_add` on the various
2244+
/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
2245+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
22452246
#[rustc_nounwind]
22462247
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
22472248

22482249
/// Returns the result of an unchecked subtraction, resulting in
22492250
/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
22502251
///
2251-
/// This intrinsic does not have a stable counterpart.
2252-
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
2252+
/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
2253+
/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
2254+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
22532255
#[rustc_nounwind]
22542256
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
22552257

22562258
/// Returns the result of an unchecked multiplication, resulting in
22572259
/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
22582260
///
2259-
/// This intrinsic does not have a stable counterpart.
2260-
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
2261+
/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
2262+
/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
2263+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
22612264
#[rustc_nounwind]
22622265
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
22632266

core/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@
137137
#![feature(const_heap)]
138138
#![feature(const_hint_assert_unchecked)]
139139
#![feature(const_index_range_slice_index)]
140-
#![feature(const_int_unchecked_arith)]
141140
#![feature(const_intrinsic_copy)]
142141
#![feature(const_intrinsic_forget)]
143142
#![feature(const_ipv4)]
@@ -197,7 +196,6 @@
197196
#![feature(str_split_inclusive_remainder)]
198197
#![feature(str_split_remainder)]
199198
#![feature(strict_provenance)]
200-
#![feature(unchecked_math)]
201199
#![feature(unchecked_shifts)]
202200
#![feature(utf16_extra)]
203201
#![feature(utf16_extra_const)]

core/src/num/int_macros.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -492,21 +492,25 @@ macro_rules! int_impl {
492492
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
493493
/// cannot occur.
494494
///
495+
/// Calling `x.unchecked_add(y)` is semantically equivalent to calling
496+
/// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`.
497+
///
498+
/// If you're just trying to avoid the panic in debug mode, then **do not**
499+
/// use this. Instead, you're looking for [`wrapping_add`].
500+
///
495501
/// # Safety
496502
///
497503
/// This results in undefined behavior when
498504
#[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")]
499505
/// i.e. when [`checked_add`] would return `None`.
500506
///
507+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
501508
#[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")]
502-
#[unstable(
503-
feature = "unchecked_math",
504-
reason = "niche optimization path",
505-
issue = "85122",
506-
)]
509+
#[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")]
510+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
511+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
507512
#[must_use = "this returns the result of the operation, \
508513
without modifying the original"]
509-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
510514
#[inline(always)]
511515
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
512516
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
@@ -630,21 +634,25 @@ macro_rules! int_impl {
630634
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
631635
/// cannot occur.
632636
///
637+
/// Calling `x.unchecked_sub(y)` is semantically equivalent to calling
638+
/// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`.
639+
///
640+
/// If you're just trying to avoid the panic in debug mode, then **do not**
641+
/// use this. Instead, you're looking for [`wrapping_sub`].
642+
///
633643
/// # Safety
634644
///
635645
/// This results in undefined behavior when
636646
#[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")]
637647
/// i.e. when [`checked_sub`] would return `None`.
638648
///
649+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
639650
#[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")]
640-
#[unstable(
641-
feature = "unchecked_math",
642-
reason = "niche optimization path",
643-
issue = "85122",
644-
)]
651+
#[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")]
652+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
653+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
645654
#[must_use = "this returns the result of the operation, \
646655
without modifying the original"]
647-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
648656
#[inline(always)]
649657
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
650658
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
@@ -768,21 +776,25 @@ macro_rules! int_impl {
768776
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
769777
/// cannot occur.
770778
///
779+
/// Calling `x.unchecked_mul(y)` is semantically equivalent to calling
780+
/// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`.
781+
///
782+
/// If you're just trying to avoid the panic in debug mode, then **do not**
783+
/// use this. Instead, you're looking for [`wrapping_mul`].
784+
///
771785
/// # Safety
772786
///
773787
/// This results in undefined behavior when
774788
#[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")]
775789
/// i.e. when [`checked_mul`] would return `None`.
776790
///
791+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
777792
#[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")]
778-
#[unstable(
779-
feature = "unchecked_math",
780-
reason = "niche optimization path",
781-
issue = "85122",
782-
)]
793+
#[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")]
794+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
795+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
783796
#[must_use = "this returns the result of the operation, \
784797
without modifying the original"]
785-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
786798
#[inline(always)]
787799
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
788800
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {

core/src/num/uint_macros.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -500,21 +500,25 @@ macro_rules! uint_impl {
500500
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
501501
/// cannot occur.
502502
///
503+
/// Calling `x.unchecked_add(y)` is semantically equivalent to calling
504+
/// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`.
505+
///
506+
/// If you're just trying to avoid the panic in debug mode, then **do not**
507+
/// use this. Instead, you're looking for [`wrapping_add`].
508+
///
503509
/// # Safety
504510
///
505511
/// This results in undefined behavior when
506512
#[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")]
507513
/// i.e. when [`checked_add`] would return `None`.
508514
///
515+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
509516
#[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")]
510-
#[unstable(
511-
feature = "unchecked_math",
512-
reason = "niche optimization path",
513-
issue = "85122",
514-
)]
517+
#[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")]
518+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
519+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
515520
#[must_use = "this returns the result of the operation, \
516521
without modifying the original"]
517-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
518522
#[inline(always)]
519523
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
520524
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
@@ -644,21 +648,25 @@ macro_rules! uint_impl {
644648
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
645649
/// cannot occur.
646650
///
651+
/// Calling `x.unchecked_sub(y)` is semantically equivalent to calling
652+
/// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`.
653+
///
654+
/// If you're just trying to avoid the panic in debug mode, then **do not**
655+
/// use this. Instead, you're looking for [`wrapping_sub`].
656+
///
647657
/// # Safety
648658
///
649659
/// This results in undefined behavior when
650660
#[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")]
651661
/// i.e. when [`checked_sub`] would return `None`.
652662
///
663+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
653664
#[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")]
654-
#[unstable(
655-
feature = "unchecked_math",
656-
reason = "niche optimization path",
657-
issue = "85122",
658-
)]
665+
#[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")]
666+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
667+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
659668
#[must_use = "this returns the result of the operation, \
660669
without modifying the original"]
661-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
662670
#[inline(always)]
663671
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
664672
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
@@ -726,21 +734,25 @@ macro_rules! uint_impl {
726734
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
727735
/// cannot occur.
728736
///
737+
/// Calling `x.unchecked_mul(y)` is semantically equivalent to calling
738+
/// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`.
739+
///
740+
/// If you're just trying to avoid the panic in debug mode, then **do not**
741+
/// use this. Instead, you're looking for [`wrapping_mul`].
742+
///
729743
/// # Safety
730744
///
731745
/// This results in undefined behavior when
732746
#[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")]
733747
/// i.e. when [`checked_mul`] would return `None`.
734748
///
749+
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
735750
#[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")]
736-
#[unstable(
737-
feature = "unchecked_math",
738-
reason = "niche optimization path",
739-
issue = "85122",
740-
)]
751+
#[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")]
752+
#[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
753+
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
741754
#[must_use = "this returns the result of the operation, \
742755
without modifying the original"]
743-
#[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
744756
#[inline(always)]
745757
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
746758
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {

core/src/ptr/const_ptr.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1029,8 +1029,6 @@ impl<T: ?Sized> *const T {
10291029
#[stable(feature = "pointer_methods", since = "1.26.0")]
10301030
#[must_use = "returns a new pointer rather than modifying its argument"]
10311031
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
1032-
// We could always go back to wrapping if unchecked becomes unacceptable
1033-
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
10341032
#[inline(always)]
10351033
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
10361034
pub const unsafe fn sub(self, count: usize) -> Self

core/src/ptr/mut_ptr.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1119,8 +1119,6 @@ impl<T: ?Sized> *mut T {
11191119
#[stable(feature = "pointer_methods", since = "1.26.0")]
11201120
#[must_use = "returns a new pointer rather than modifying its argument"]
11211121
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
1122-
// We could always go back to wrapping if unchecked becomes unacceptable
1123-
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
11241122
#[inline(always)]
11251123
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
11261124
pub const unsafe fn sub(self, count: usize) -> Self

core/src/ptr/non_null.rs

-2
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,6 @@ impl<T: ?Sized> NonNull<T> {
702702
#[unstable(feature = "non_null_convenience", issue = "117691")]
703703
#[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")]
704704
#[must_use = "returns a new pointer rather than modifying its argument"]
705-
// We could always go back to wrapping if unchecked becomes unacceptable
706-
#[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
707705
#[inline(always)]
708706
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
709707
pub const unsafe fn sub(self, count: usize) -> Self

0 commit comments

Comments
 (0)