about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-13 09:12:51 +0000
committerbors <bors@rust-lang.org>2019-01-13 09:12:51 +0000
commit5012d7fb53d9f1e489c1ae1a081347fddbbffe5f (patch)
treed310753c22ca69e2d076366dab73616ce87b31f1
parent75a369c5b11459baa6bf7734eeb6135998a0a7de (diff)
parentb172e89c148d11afc85147294c47496bda48fce7 (diff)
downloadrust-5012d7fb53d9f1e489c1ae1a081347fddbbffe5f.tar.gz
rust-5012d7fb53d9f1e489c1ae1a081347fddbbffe5f.zip
Auto merge of #57566 - Centril:const-stabilize-overflowing, r=alexreg
Const-stabilize `const_int_overflowing`

Fixes https://github.com/rust-lang/rust/issues/57237.

r? @alexreg
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/bignum.rs25
-rw-r--r--src/libcore/num/mod.rs56
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs3
-rw-r--r--src/librustc_typeck/check/intrinsic.rs1
-rw-r--r--src/test/run-pass/const-int-overflowing.rs2
6 files changed, 58 insertions, 30 deletions
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a5f20d08e47..8879112fcf0 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -114,6 +114,7 @@
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
+#![cfg_attr(stage0, feature(const_let))]
 #![cfg_attr(stage0, feature(const_int_rotate))]
 #![feature(const_int_conversion)]
 #![feature(const_transmute)]
diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs
index 99a427ba159..5326ef1e7c1 100644
--- a/src/libcore/num/bignum.rs
+++ b/src/libcore/num/bignum.rs
@@ -46,25 +46,37 @@ macro_rules! impl_full_ops {
     ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
         $(
             impl FullOps for $ty {
+                #[cfg(stage0)]
                 fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
-                    // this cannot overflow, the output is between 0 and 2*2^nbits - 1
-                    // FIXME will LLVM optimize this into ADC or similar???
+                    // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`.
+                    // FIXME: will LLVM optimize this into ADC or similar?
                     let (v, carry1) = unsafe { intrinsics::add_with_overflow(self, other) };
                     let (v, carry2) = unsafe {
                         intrinsics::add_with_overflow(v, if carry {1} else {0})
                     };
                     (carry1 || carry2, v)
                 }
+                #[cfg(not(stage0))]
+                fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
+                    // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`.
+                    // FIXME: will LLVM optimize this into ADC or similar?
+                    let (v, carry1) = intrinsics::add_with_overflow(self, other);
+                    let (v, carry2) = intrinsics::add_with_overflow(v, if carry {1} else {0});
+                    (carry1 || carry2, v)
+                }
 
                 fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
-                    // this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)
+                    // This cannot overflow;
+                    // the output is between `0` and `2^nbits * (2^nbits - 1)`.
+                    // FIXME: will LLVM optimize this into ADC or similar?
                     let nbits = mem::size_of::<$ty>() * 8;
                     let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
                     ((v >> nbits) as $ty, v as $ty)
                 }
 
                 fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
-                    // this cannot overflow, the output is between 0 and 2^(2*nbits) - 1
+                    // This cannot overflow;
+                    // the output is between `0` and `2^nbits * (2^nbits - 1)`.
                     let nbits = mem::size_of::<$ty>() * 8;
                     let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
                             (carry as $bigty);
@@ -73,7 +85,7 @@ macro_rules! impl_full_ops {
 
                 fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
                     debug_assert!(borrow < other);
-                    // this cannot overflow, the dividend is between 0 and other * 2^nbits - 1
+                    // This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`.
                     let nbits = mem::size_of::<$ty>() * 8;
                     let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
                     let rhs = other as $bigty;
@@ -88,7 +100,8 @@ impl_full_ops! {
     u8:  add(intrinsics::u8_add_with_overflow),  mul/div(u16);
     u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
     u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
-//  u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
+    // See RFC #521 for enabling this.
+    // u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
 }
 
 /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 7ff04410516..6827364c0f8 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1340,13 +1340,15 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($Sel
 "::MIN, true));", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+                #[cfg(stage0)]
                 let (a, b) = unsafe {
-                    intrinsics::add_with_overflow(self as $ActualT,
-                                                  rhs as $ActualT)
+                    intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT)
                 };
+                #[cfg(not(stage0))]
+                let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
                 (a as Self, b)
             }
         }
@@ -1369,13 +1371,15 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($Sel
 "::MAX, true));", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+                #[cfg(stage0)]
                 let (a, b) = unsafe {
-                    intrinsics::sub_with_overflow(self as $ActualT,
-                                                  rhs as $ActualT)
+                    intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT)
                 };
+                #[cfg(not(stage0))]
+                let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
                 (a as Self, b)
             }
         }
@@ -1396,13 +1400,15 @@ assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+                #[cfg(stage0)]
                 let (a, b) = unsafe {
-                    intrinsics::mul_with_overflow(self as $ActualT,
-                                                  rhs as $ActualT)
+                    intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT)
                 };
+                #[cfg(not(stage0))]
+                let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
                 (a as Self, b)
             }
         }
@@ -1585,7 +1591,7 @@ assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
@@ -1609,7 +1615,7 @@ assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
@@ -3213,13 +3219,15 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
 assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+                #[cfg(stage0)]
                 let (a, b) = unsafe {
-                    intrinsics::add_with_overflow(self as $ActualT,
-                                                  rhs as $ActualT)
+                    intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT)
                 };
+                #[cfg(not(stage0))]
+                let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
                 (a as Self, b)
             }
         }
@@ -3243,13 +3251,15 @@ assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT),
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+                #[cfg(stage0)]
                 let (a, b) = unsafe {
-                    intrinsics::sub_with_overflow(self as $ActualT,
-                                                  rhs as $ActualT)
+                    intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT)
                 };
+                #[cfg(not(stage0))]
+                let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
                 (a as Self, b)
             }
         }
@@ -3272,13 +3282,15 @@ $EndFeature, "
         /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
         /// ```
         #[stable(feature = "wrapping", since = "1.7.0")]
-        #[rustc_const_unstable(feature = "const_int_overflowing")]
+        #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
         #[inline]
         pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            #[cfg(stage0)]
             let (a, b) = unsafe {
-                intrinsics::mul_with_overflow(self as $ActualT,
-                                              rhs as $ActualT)
+                intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT)
             };
+            #[cfg(not(stage0))]
+            let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
             (a as Self, b)
         }
 
@@ -3436,7 +3448,7 @@ Basic usage
 assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
@@ -3461,7 +3473,7 @@ Basic usage
 assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
-            #[rustc_const_unstable(feature = "const_int_overflowing")]
+            #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
             #[inline]
             pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
                 (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 41a042ebcb6..059b88a4d70 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -374,6 +374,9 @@ fn is_intrinsic_whitelisted(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool
         | "min_align_of"
         | "needs_drop"
         // Arithmetic:
+        | "add_with_overflow" // ~> .overflowing_add
+        | "sub_with_overflow" // ~> .overflowing_sub
+        | "mul_with_overflow" // ~> .overflowing_mul
         | "overflowing_add" // ~> .wrapping_add
         | "overflowing_sub" // ~> .wrapping_sub
         | "overflowing_mul" // ~> .wrapping_mul
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 04d18ff7aa3..9f323b9116d 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -70,6 +70,7 @@ fn equate_intrinsic_type<'a, 'tcx>(
 pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
     match intrinsic {
         "size_of" | "min_align_of" | "needs_drop" |
+        "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
         "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
         "rotate_left" | "rotate_right" |
         "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse"
diff --git a/src/test/run-pass/const-int-overflowing.rs b/src/test/run-pass/const-int-overflowing.rs
index ae7ee5aa96e..289b1236cf1 100644
--- a/src/test/run-pass/const-int-overflowing.rs
+++ b/src/test/run-pass/const-int-overflowing.rs
@@ -1,5 +1,3 @@
-#![feature(const_int_overflowing)]
-
 const ADD_A: (u32, bool) = 5u32.overflowing_add(2);
 const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1);