From d9e3d2a5314258e2b8adc86c1ded34c4995fcd67 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 12:31:39 -0800 Subject: [PATCH 01/12] Make euclidean division `const` Co-Authored-By: 9999years --- src/libcore/lib.rs | 1 + src/libcore/num/mod.rs | 48 ++++++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6edf253d4bb80..4fc7caa62b5cd 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,6 +72,7 @@ #![feature(concat_idents)] #![feature(const_alloc_layout)] #![feature(const_if_match)] +#![feature(const_int_euclidean)] #![feature(const_panic)] #![feature(const_fn_union)] #![feature(const_generics)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 39c7d6d24ed04..ede568da3e5bd 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -802,10 +802,11 @@ assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -860,10 +861,11 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -1298,10 +1300,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); assert_eq!((-128i8).wrapping_div_euclid(-1), -128); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self.overflowing_div_euclid(rhs).0 } } @@ -1356,10 +1359,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self.overflowing_rem_euclid(rhs).0 } } @@ -1669,9 +1673,10 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { @@ -1736,10 +1741,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { @@ -1981,11 +1987,12 @@ assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + pub const fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { return if rhs > 0 { q - 1 } else { q + 1 } @@ -2020,11 +2027,12 @@ assert_eq!(a.rem_euclid(-b), 3); assert_eq!((-a).rem_euclid(-b), 1); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn rem_euclid(self, rhs: Self) -> Self { + pub const fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2939,10 +2947,11 @@ assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -2992,10 +3001,11 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -3315,10 +3325,11 @@ Basic usage: assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } @@ -3366,10 +3377,11 @@ Basic usage: assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } @@ -3645,9 +3657,10 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } @@ -3704,9 +3717,10 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } @@ -3897,11 +3911,12 @@ Basic usage: assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + pub const fn div_euclid(self, rhs: Self) -> Self { self / rhs } } @@ -3926,11 +3941,12 @@ Basic usage: assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn rem_euclid(self, rhs: Self) -> Self { + pub const fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } From 37c141885ac5972e7c858d65babe1753b0ad994c Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 13:19:07 -0800 Subject: [PATCH 02/12] Make checked arithmetic besides division `const` Co-Authored-By: 9999years --- src/libcore/lib.rs | 1 + src/libcore/num/mod.rs | 39 ++++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4fc7caa62b5cd..78b1524f04f83 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,6 +72,7 @@ #![feature(concat_idents)] #![feature(const_alloc_layout)] #![feature(const_if_match)] +#![feature(const_int_checked)] #![feature(const_int_euclidean)] #![feature(const_panic)] #![feature(const_fn_union)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ede568da3e5bd..91df649f121e7 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -701,10 +701,11 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_add(self, rhs: Self) -> Option { + pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } @@ -725,10 +726,11 @@ assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { + pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } @@ -749,10 +751,11 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { + pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } @@ -889,8 +892,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[inline] - pub fn checked_neg(self) -> Option { + pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } @@ -910,10 +914,11 @@ assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { + pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} } @@ -933,10 +938,11 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { + pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } @@ -958,8 +964,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[inline] - pub fn checked_abs(self) -> Option { + pub const fn checked_abs(self) -> Option { if self.is_negative() { self.checked_neg() } else { @@ -2855,10 +2862,11 @@ Basic usage: assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_add(self, rhs: Self) -> Option { + pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } @@ -2877,10 +2885,11 @@ Basic usage: assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { + pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } @@ -2899,10 +2908,11 @@ Basic usage: assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { + pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } @@ -3029,8 +3039,9 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[inline] - pub fn checked_neg(self) -> Option { + pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } @@ -3049,10 +3060,11 @@ Basic usage: assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { + pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} } @@ -3071,10 +3083,11 @@ Basic usage: assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { + pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } From de52a541d5daab8393d4da8a9508fb7b5c1448e0 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 12:45:51 -0800 Subject: [PATCH 03/12] Make overflowing arithmetic `const` Co-Authored-By: 9999years --- src/libcore/lib.rs | 1 + src/libcore/num/mod.rs | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 78b1524f04f83..f8857b9d73377 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -74,6 +74,7 @@ #![feature(const_if_match)] #![feature(const_int_checked)] #![feature(const_int_euclidean)] +#![feature(const_int_overflowing)] #![feature(const_panic)] #![feature(const_fn_union)] #![feature(const_generics)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 91df649f121e7..690a07ce68090 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1646,9 +1646,10 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { @@ -1715,9 +1716,10 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { @@ -3639,9 +3641,10 @@ Basic usage ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } @@ -3699,9 +3702,10 @@ Basic usage ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } From b422a19c4323e54f635e6d6aa7fc9900ce9f25a6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 13:16:38 -0800 Subject: [PATCH 04/12] Make `saturating_mul` a `const fn` Co-Authored-By: 9999years --- src/libcore/lib.rs | 1 + src/libcore/num/mod.rs | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index f8857b9d73377..76e3d0d32997f 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -75,6 +75,7 @@ #![feature(const_int_checked)] #![feature(const_int_euclidean)] #![feature(const_int_overflowing)] +#![feature(const_int_saturating)] #![feature(const_panic)] #![feature(const_fn_union)] #![feature(const_generics)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 690a07ce68090..1dccc87dd18b2 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1142,17 +1142,19 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($Self $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn saturating_mul(self, rhs: Self) -> Self { - self.checked_mul(rhs).unwrap_or_else(|| { - if (self < 0) == (rhs < 0) { + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => if (self < 0) == (rhs < 0) { Self::max_value() } else { Self::min_value() } - }) + } } } @@ -3195,11 +3197,15 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se "::MAX);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn saturating_mul(self, rhs: Self) -> Self { - self.checked_mul(rhs).unwrap_or(Self::max_value()) + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => Self::max_value(), + } } } From b46d1d27184bf78cc9181feadd192e887fe7d589 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 12:53:34 -0800 Subject: [PATCH 05/12] Make wrapping arithmetic `const` Co-Authored-By: 9999years --- src/libcore/num/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1dccc87dd18b2..004e91c0eb3a6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1280,10 +1280,11 @@ assert_eq!((-128i8).wrapping_div(-1), -128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div(self, rhs: Self) -> Self { + pub const fn wrapping_div(self, rhs: Self) -> Self { self.overflowing_div(rhs).0 } } @@ -1340,10 +1341,11 @@ assert_eq!((-128i8).wrapping_rem(-1), 0);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem(self, rhs: Self) -> Self { + pub const fn wrapping_rem(self, rhs: Self) -> Self { self.overflowing_rem(rhs).0 } } @@ -3320,10 +3322,11 @@ Basic usage: ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div(self, rhs: Self) -> Self { + pub const fn wrapping_div(self, rhs: Self) -> Self { self / rhs } } @@ -3371,10 +3374,11 @@ Basic usage: ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem(self, rhs: Self) -> Self { + pub const fn wrapping_rem(self, rhs: Self) -> Self { self % rhs } } From d4529bec02f5e61a6684ee8ffc40d84d35c23242 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 12:49:31 -0800 Subject: [PATCH 06/12] Const-stabilize some arithmetic intrinsics --- src/libcore/intrinsics.rs | 5 +++++ src/libcore/lib.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 416c73f50bd89..2cee23a5c752c 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1305,9 +1305,11 @@ extern "rust-intrinsic" { /// Performs an unchecked division, resulting in undefined behavior /// where y = 0 or x = `T::min_value()` and y = -1 + #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_div(x: T, y: T) -> T; /// Returns the remainder of an unchecked division, resulting in /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1 + #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_rem(x: T, y: T) -> T; /// Performs an unchecked left shift, resulting in undefined behavior when @@ -1321,14 +1323,17 @@ extern "rust-intrinsic" { /// Returns the result of an unchecked addition, resulting in /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`. + #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_add(x: T, y: T) -> T; /// Returns the result of an unchecked subtraction, resulting in /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`. + #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_sub(x: T, y: T) -> T; /// Returns the result of an unchecked multiplication, resulting in /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`. + #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_mul(x: T, y: T) -> T; /// Performs rotate left. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 76e3d0d32997f..b5baa42fdb3fc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -76,6 +76,7 @@ #![feature(const_int_euclidean)] #![feature(const_int_overflowing)] #![feature(const_int_saturating)] +#![feature(const_int_unchecked_arith)] #![feature(const_panic)] #![feature(const_fn_union)] #![feature(const_generics)] From 526304da1621f6cd718a29d05a058de2beac954e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 13:19:32 -0800 Subject: [PATCH 07/12] Make checked division `const` --- src/libcore/num/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 004e91c0eb3a6..f590c6bc7c285 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -777,10 +777,11 @@ assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div(self, rhs: Self) -> Option { + pub const fn checked_div(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -835,10 +836,11 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem(self, rhs: Self) -> Option { + pub const fn checked_rem(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -2937,10 +2939,11 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div(self, rhs: Self) -> Option { + pub const fn checked_div(self, rhs: Self) -> Option { match rhs { 0 => None, // SAFETY: div by zero has been checked above and unsigned types have no other @@ -2990,10 +2993,11 @@ Basic usage: assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem(self, rhs: Self) -> Option { + pub const fn checked_rem(self, rhs: Self) -> Option { if rhs == 0 { None } else { From dda015aebca79d508b74cae6a0ecfb0a093d8639 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 13:17:13 -0800 Subject: [PATCH 08/12] Make saturating arithmetic using intrinsics `const` --- src/libcore/num/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f590c6bc7c285..38989004f9147 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1091,8 +1091,9 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] + #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] #[inline] - pub fn saturating_neg(self) -> Self { + pub const fn saturating_neg(self) -> Self { intrinsics::saturating_sub(0, self) } } @@ -1117,8 +1118,9 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] + #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] #[inline] - pub fn saturating_abs(self) -> Self { + pub const fn saturating_abs(self) -> Self { if self.is_negative() { self.saturating_neg() } else { From 3e9fd80bd7c0b3aeb700c474edd93a078f822dbc Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 14:23:21 -0800 Subject: [PATCH 09/12] Add tests for newly const arithmetic fns Co-Authored-By: 9999years --- src/test/ui/consts/const-int-arithmetic.rs | 166 +++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/test/ui/consts/const-int-arithmetic.rs diff --git a/src/test/ui/consts/const-int-arithmetic.rs b/src/test/ui/consts/const-int-arithmetic.rs new file mode 100644 index 0000000000000..703f21a3f2952 --- /dev/null +++ b/src/test/ui/consts/const-int-arithmetic.rs @@ -0,0 +1,166 @@ +// run-pass + +#![feature(const_int_checked)] +#![feature(const_int_euclidean)] +#![feature(const_int_overflowing)] +#![feature(const_int_saturating)] +#![feature(const_int_wrapping)] + +macro_rules! assert_same_const { + ($(const $ident:ident: $ty:ty = $exp:expr;)+) => { + $(const $ident: $ty = $exp;)+ + + pub fn main() { + $(assert_eq!($exp, $ident);)+ + } + } +} + +assert_same_const! { + // `const_int_checked` + const CHECKED_ADD_I32_A: Option = 5i32.checked_add(2); + const CHECKED_ADD_I8_A: Option = 127i8.checked_add(2); + const CHECKED_ADD_U8_A: Option = 255u8.checked_add(2); + + const CHECKED_SUB_I32_A: Option = 5i32.checked_sub(2); + const CHECKED_SUB_I8_A: Option = (-127 as i8).checked_sub(2); + const CHECKED_SUB_U8_A: Option = 1u8.checked_sub(2); + + const CHECKED_MUL_I32_A: Option = 5i32.checked_mul(7777); + const CHECKED_MUL_I8_A: Option = (-127 as i8).checked_mul(-99); + const CHECKED_MUL_U8_A: Option = 1u8.checked_mul(3); + + const CHECKED_DIV_I32_A: Option = 5i32.checked_div(7777); + const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div(-99); + const CHECKED_DIV_U8_A: Option = 1u8.checked_div(3); + + const CHECKED_REM_I32_A: Option = 5i32.checked_rem(7777); + const CHECKED_REM_I8_A: Option = (-127 as i8).checked_rem(-99); + const CHECKED_REM_U8_A: Option = 1u8.checked_rem(3); + const CHECKED_REM_U8_B: Option = 1u8.checked_rem(0); + + const CHECKED_NEG_I32_A: Option = 5i32.checked_neg(); + const CHECKED_NEG_I8_A: Option = (-127 as i8).checked_neg(); + const CHECKED_NEG_U8_A: Option = 1u8.checked_neg(); + const CHECKED_NEG_U8_B: Option = u8::min_value().checked_neg(); + + const CHECKED_SHL_I32_A: Option = 5i32.checked_shl(77777); + const CHECKED_SHL_I8_A: Option = (-127 as i8).checked_shl(2); + const CHECKED_SHL_U8_A: Option = 1u8.checked_shl(8); + const CHECKED_SHL_U8_B: Option = 1u8.checked_shl(0); + + const CHECKED_SHR_I32_A: Option = 5i32.checked_shr(77777); + const CHECKED_SHR_I8_A: Option = (-127 as i8).checked_shr(2); + const CHECKED_SHR_U8_A: Option = 1u8.checked_shr(8); + const CHECKED_SHR_U8_B: Option = 1u8.checked_shr(0); + + const CHECKED_ABS_I32_A: Option = 5i32.checked_abs(); + const CHECKED_ABS_I8_A: Option = (-127 as i8).checked_abs(); + const CHECKED_ABS_I8_B: Option = 1i8.checked_abs(); + const CHECKED_ABS_I8_C: Option = i8::min_value().checked_abs(); + + // `const_int_overflowing` + const DIV_A: (i8, bool) = 8i8.overflowing_div(2); + const DIV_B: (i8, bool) = 8i8.overflowing_div(3); + const DIV_C: (i8, bool) = i8::min_value().overflowing_div(-1i8); + const DIV_D: (u8, bool) = 8u8.overflowing_div(2); + const DIV_E: (u8, bool) = 8u8.overflowing_div(3); + + const REM_A: (i8, bool) = 8i8.overflowing_rem(2); + const REM_B: (i8, bool) = 8i8.overflowing_rem(3); + const REM_C: (i8, bool) = i8::min_value().overflowing_rem(-1i8); + const REM_D: (u8, bool) = 8u8.overflowing_rem(2); + const REM_E: (u8, bool) = 8u8.overflowing_rem(3); + + // `const_int_saturating` + const ADD_INT_U32_NO: u32 = (42 as u32).saturating_add(2); + const ADD_INT_U32: u32 = u32::max_value().saturating_add(1); + const ADD_INT_U128: u128 = u128::max_value().saturating_add(1); + const ADD_INT_I128: i128 = i128::max_value().saturating_add(1); + const ADD_INT_I128_NEG: i128 = i128::min_value().saturating_add(-1); + + const SUB_INT_U32_NO: u32 = (42 as u32).saturating_sub(2); + const SUB_INT_U32: u32 = (1 as u32).saturating_sub(2); + const SUB_INT_I32_NO: i32 = (-42 as i32).saturating_sub(2); + const SUB_INT_I32_NEG: i32 = i32::min_value().saturating_sub(1); + const SUB_INT_I32_POS: i32 = i32::max_value().saturating_sub(-1); + const SUB_INT_U128: u128 = (0 as u128).saturating_sub(1); + const SUB_INT_I128_NEG: i128 = i128::min_value().saturating_sub(1); + const SUB_INT_I128_POS: i128 = i128::max_value().saturating_sub(-1); + + const MUL_INT_U32_NO: u32 = (42 as u32).saturating_mul(2); + const MUL_INT_U32: u32 = (1 as u32).saturating_mul(2); + const MUL_INT_I32_NO: i32 = (-42 as i32).saturating_mul(2); + const MUL_INT_I32_NEG: i32 = i32::min_value().saturating_mul(1); + const MUL_INT_I32_POS: i32 = i32::max_value().saturating_mul(2); + const MUL_INT_U128: u128 = (0 as u128).saturating_mul(1); + const MUL_INT_I128_NEG: i128 = i128::min_value().saturating_mul(2); + const MUL_INT_I128_POS: i128 = i128::max_value().saturating_mul(2); + + const NEG_INT_I8: i8 = (-42i8).saturating_neg(); + const NEG_INT_I8_B: i8 = i8::min_value().saturating_neg(); + const NEG_INT_I32: i32 = i32::min_value().saturating_neg(); + const NEG_INT_I32_B: i32 = i32::max_value().saturating_neg(); + const NEG_INT_I128: i128 = i128::min_value().saturating_neg(); + const NEG_INT_I128_B: i128 = i128::max_value().saturating_neg(); + + const ABS_INT_I8_A: i8 = 4i8.saturating_abs(); + const ABS_INT_I8_B: i8 = -4i8.saturating_abs(); + const ABS_INT_I8_C: i8 = i8::min_value().saturating_abs(); + const ABS_INT_I32_A: i32 = 4i32.saturating_abs(); + const ABS_INT_I32_B: i32 = -4i32.saturating_abs(); + const ABS_INT_I32_C: i32 = i32::min_value().saturating_abs(); + const ABS_INT_I128_A: i128 = 4i128.saturating_abs(); + const ABS_INT_I128_B: i128 = -4i128.saturating_abs(); + const ABS_INT_I128_C: i128 = i128::min_value().saturating_abs(); + + // `const_int_euclidean` + const CHECKED_DIV_I32_A: Option = 5i32.checked_div_euclid(7777); + const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div_euclid(-99); + const CHECKED_DIV_I8_B: Option = (-127 as i8).checked_div_euclid(1); + const CHECKED_DIV_I8_C: Option = i8::min_value().checked_div_euclid(-1); + const CHECKED_DIV_U8_A: Option = 1u8.checked_div_euclid(3); + + const CHECKED_REM_I32_A: Option = 5i32.checked_rem_euclid(7777); + const CHECKED_REM_I8_A: Option = (-127 as i8).checked_rem_euclid(-99); + const CHECKED_REM_I8_B: Option = (-127 as i8).checked_rem_euclid(0); + const CHECKED_REM_I8_C: Option = i8::min_value().checked_rem_euclid(-1); + const CHECKED_REM_U8_A: Option = 1u8.checked_rem_euclid(3); + + const WRAPPING_DIV_I32_A: i32 = 5i32.wrapping_div_euclid(7777); + const WRAPPING_DIV_I8_A: i8 = (-127 as i8).wrapping_div_euclid(-99); + const WRAPPING_DIV_I8_B: i8 = (-127 as i8).wrapping_div_euclid(1); + const WRAPPING_DIV_I8_C: i8 = i8::min_value().wrapping_div_euclid(-1); + const WRAPPING_DIV_U8_A: u8 = 1u8.wrapping_div_euclid(3); + + const WRAPPING_REM_I32_A: i32 = 5i32.wrapping_rem_euclid(7777); + const WRAPPING_REM_I8_A: i8 = (-127 as i8).wrapping_rem_euclid(-99); + const WRAPPING_REM_I8_B: i8 = (-127 as i8).wrapping_rem_euclid(1); + const WRAPPING_REM_I8_C: i8 = i8::min_value().wrapping_rem_euclid(-1); + const WRAPPING_REM_U8_A: u8 = 1u8.wrapping_rem_euclid(3); + + const OVERFLOWING_DIV_I32_A: (i32, bool) = 5i32.overflowing_div_euclid(7777); + const OVERFLOWING_DIV_I8_A: (i8, bool) = (-127 as i8).overflowing_div_euclid(-99); + const OVERFLOWING_DIV_I8_B: (i8, bool) = (-127 as i8).overflowing_div_euclid(1); + const OVERFLOWING_DIV_I8_C: (i8, bool) = i8::min_value().overflowing_div_euclid(-1); + const OVERFLOWING_DIV_U8_A: (u8, bool) = 1u8.overflowing_div_euclid(3); + + const OVERFLOWING_REM_I32_A: (i32, bool) = 5i32.overflowing_rem_euclid(7777); + const OVERFLOWING_REM_I8_A: (i8, bool) = (-127 as i8).overflowing_rem_euclid(-99); + const OVERFLOWING_REM_I8_B: (i8, bool) = (-127 as i8).overflowing_rem_euclid(1); + const OVERFLOWING_REM_I8_C: (i8, bool) = i8::min_value().overflowing_rem_euclid(-1); + const OVERFLOWING_REM_U8_A: (u8, bool) = 1u8.overflowing_rem_euclid(3); + + // `const_int_wrapping` + const DIV_A: i8 = 8i8.wrapping_div(2); + const DIV_B: i8 = 8i8.wrapping_div(3); + const DIV_C: i8 = i8::min_value().wrapping_div(-1i8); + const DIV_D: u8 = 8u8.wrapping_div(2); + const DIV_E: u8 = 8u8.wrapping_div(3); + + const REM_A: i8 = 8i8.wrapping_rem(2); + const REM_B: i8 = 8i8.wrapping_rem(3); + const REM_C: i8 = i8::min_value().wrapping_rem(-1i8); + const REM_D: u8 = 8u8.wrapping_rem(2); + const REM_E: u8 = 8u8.wrapping_rem(3); +} From 09160d1b84a21ad2f11c3186bb2f07dc601dc9d8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Feb 2020 11:46:03 -0800 Subject: [PATCH 10/12] Use consistent feature naming --- src/libcore/lib.rs | 8 ++-- src/libcore/num/mod.rs | 90 +++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index b5baa42fdb3fc..1fd70e1a1b049 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,10 +72,10 @@ #![feature(concat_idents)] #![feature(const_alloc_layout)] #![feature(const_if_match)] -#![feature(const_int_checked)] -#![feature(const_int_euclidean)] -#![feature(const_int_overflowing)] -#![feature(const_int_saturating)] +#![feature(const_checked_int_methods)] +#![feature(const_euclidean_int_methods)] +#![feature(const_overflowing_int_methods)] +#![feature(const_saturating_int_methods)] #![feature(const_int_unchecked_arith)] #![feature(const_panic)] #![feature(const_fn_union)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 38989004f9147..ed37b48b3e855 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -701,7 +701,7 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -726,7 +726,7 @@ assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -751,7 +751,7 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -777,7 +777,7 @@ assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -806,7 +806,7 @@ assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -836,7 +836,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -866,7 +866,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -894,7 +894,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); @@ -916,7 +916,7 @@ assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -940,7 +940,7 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -966,7 +966,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[inline] pub const fn checked_abs(self) -> Option { if self.is_negative() { @@ -1091,7 +1091,7 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] - #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] + #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[inline] pub const fn saturating_neg(self) -> Self { intrinsics::saturating_sub(0, self) @@ -1118,7 +1118,7 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] - #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] + #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[inline] pub const fn saturating_abs(self) -> Self { if self.is_negative() { @@ -1146,7 +1146,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($Self $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] + #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1284,7 +1284,7 @@ assert_eq!((-128i8).wrapping_div(-1), -128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1314,7 +1314,7 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); assert_eq!((-128i8).wrapping_div_euclid(-1), -128); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1345,7 +1345,7 @@ assert_eq!((-128i8).wrapping_rem(-1), 0);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1374,7 +1374,7 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1654,7 +1654,7 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { @@ -1689,7 +1689,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { @@ -1724,7 +1724,7 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { @@ -1758,7 +1758,7 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2004,7 +2004,7 @@ assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2044,7 +2044,7 @@ assert_eq!(a.rem_euclid(-b), 3); assert_eq!((-a).rem_euclid(-b), 1); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2872,7 +2872,7 @@ Basic usage: assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2895,7 +2895,7 @@ Basic usage: assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2918,7 +2918,7 @@ Basic usage: assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2941,7 +2941,7 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2968,7 +2968,7 @@ assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2995,7 +2995,7 @@ Basic usage: assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3023,7 +3023,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3051,7 +3051,7 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); @@ -3072,7 +3072,7 @@ Basic usage: assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3095,7 +3095,7 @@ Basic usage: assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_checked", issue = "53718")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3205,7 +3205,7 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se "::MAX);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_saturating", issue = "53718")] + #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3328,7 +3328,7 @@ Basic usage: ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3355,7 +3355,7 @@ Basic usage: assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3380,7 +3380,7 @@ Basic usage: ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_int_wrapping", issue = "53718")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3408,7 +3408,7 @@ Basic usage: assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3657,7 +3657,7 @@ Basic usage ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { @@ -3689,7 +3689,7 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { @@ -3718,7 +3718,7 @@ Basic usage ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_int_overflowing", issue = "53718")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { @@ -3750,7 +3750,7 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); ```"), #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { @@ -3944,7 +3944,7 @@ Basic usage: assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3974,7 +3974,7 @@ Basic usage: assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_int_euclidean", issue = "53718")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] From 040d9873aa6ca1ce458e98fec403cee8ec4f7ae8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Feb 2020 11:46:13 -0800 Subject: [PATCH 11/12] Fix test --- src/test/ui/consts/const-int-arithmetic.rs | 284 +++++++++------------ 1 file changed, 124 insertions(+), 160 deletions(-) diff --git a/src/test/ui/consts/const-int-arithmetic.rs b/src/test/ui/consts/const-int-arithmetic.rs index 703f21a3f2952..cfa2873c68bad 100644 --- a/src/test/ui/consts/const-int-arithmetic.rs +++ b/src/test/ui/consts/const-int-arithmetic.rs @@ -1,166 +1,130 @@ // run-pass -#![feature(const_int_checked)] -#![feature(const_int_euclidean)] -#![feature(const_int_overflowing)] -#![feature(const_int_saturating)] -#![feature(const_int_wrapping)] - -macro_rules! assert_same_const { - ($(const $ident:ident: $ty:ty = $exp:expr;)+) => { - $(const $ident: $ty = $exp;)+ - - pub fn main() { - $(assert_eq!($exp, $ident);)+ +#![feature(saturating_neg)] +#![feature(const_checked_int_methods)] +#![feature(const_euclidean_int_methods)] +#![feature(const_overflowing_int_methods)] +#![feature(const_saturating_int_methods)] +#![feature(const_wrapping_int_methods)] + +use std::i8; + +macro_rules! suite { + ($( + $fn:ident -> $ty:ty { $( $label:ident : $expr:expr, $result:expr; )* } + )*) => { $( + fn $fn() { + $( + const $label: $ty = $expr; + assert_eq!($label, $result); + )* } - } + )* } } -assert_same_const! { - // `const_int_checked` - const CHECKED_ADD_I32_A: Option = 5i32.checked_add(2); - const CHECKED_ADD_I8_A: Option = 127i8.checked_add(2); - const CHECKED_ADD_U8_A: Option = 255u8.checked_add(2); - - const CHECKED_SUB_I32_A: Option = 5i32.checked_sub(2); - const CHECKED_SUB_I8_A: Option = (-127 as i8).checked_sub(2); - const CHECKED_SUB_U8_A: Option = 1u8.checked_sub(2); - - const CHECKED_MUL_I32_A: Option = 5i32.checked_mul(7777); - const CHECKED_MUL_I8_A: Option = (-127 as i8).checked_mul(-99); - const CHECKED_MUL_U8_A: Option = 1u8.checked_mul(3); - - const CHECKED_DIV_I32_A: Option = 5i32.checked_div(7777); - const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div(-99); - const CHECKED_DIV_U8_A: Option = 1u8.checked_div(3); - - const CHECKED_REM_I32_A: Option = 5i32.checked_rem(7777); - const CHECKED_REM_I8_A: Option = (-127 as i8).checked_rem(-99); - const CHECKED_REM_U8_A: Option = 1u8.checked_rem(3); - const CHECKED_REM_U8_B: Option = 1u8.checked_rem(0); - - const CHECKED_NEG_I32_A: Option = 5i32.checked_neg(); - const CHECKED_NEG_I8_A: Option = (-127 as i8).checked_neg(); - const CHECKED_NEG_U8_A: Option = 1u8.checked_neg(); - const CHECKED_NEG_U8_B: Option = u8::min_value().checked_neg(); - - const CHECKED_SHL_I32_A: Option = 5i32.checked_shl(77777); - const CHECKED_SHL_I8_A: Option = (-127 as i8).checked_shl(2); - const CHECKED_SHL_U8_A: Option = 1u8.checked_shl(8); - const CHECKED_SHL_U8_B: Option = 1u8.checked_shl(0); - - const CHECKED_SHR_I32_A: Option = 5i32.checked_shr(77777); - const CHECKED_SHR_I8_A: Option = (-127 as i8).checked_shr(2); - const CHECKED_SHR_U8_A: Option = 1u8.checked_shr(8); - const CHECKED_SHR_U8_B: Option = 1u8.checked_shr(0); - - const CHECKED_ABS_I32_A: Option = 5i32.checked_abs(); - const CHECKED_ABS_I8_A: Option = (-127 as i8).checked_abs(); - const CHECKED_ABS_I8_B: Option = 1i8.checked_abs(); - const CHECKED_ABS_I8_C: Option = i8::min_value().checked_abs(); - - // `const_int_overflowing` - const DIV_A: (i8, bool) = 8i8.overflowing_div(2); - const DIV_B: (i8, bool) = 8i8.overflowing_div(3); - const DIV_C: (i8, bool) = i8::min_value().overflowing_div(-1i8); - const DIV_D: (u8, bool) = 8u8.overflowing_div(2); - const DIV_E: (u8, bool) = 8u8.overflowing_div(3); - - const REM_A: (i8, bool) = 8i8.overflowing_rem(2); - const REM_B: (i8, bool) = 8i8.overflowing_rem(3); - const REM_C: (i8, bool) = i8::min_value().overflowing_rem(-1i8); - const REM_D: (u8, bool) = 8u8.overflowing_rem(2); - const REM_E: (u8, bool) = 8u8.overflowing_rem(3); - - // `const_int_saturating` - const ADD_INT_U32_NO: u32 = (42 as u32).saturating_add(2); - const ADD_INT_U32: u32 = u32::max_value().saturating_add(1); - const ADD_INT_U128: u128 = u128::max_value().saturating_add(1); - const ADD_INT_I128: i128 = i128::max_value().saturating_add(1); - const ADD_INT_I128_NEG: i128 = i128::min_value().saturating_add(-1); - - const SUB_INT_U32_NO: u32 = (42 as u32).saturating_sub(2); - const SUB_INT_U32: u32 = (1 as u32).saturating_sub(2); - const SUB_INT_I32_NO: i32 = (-42 as i32).saturating_sub(2); - const SUB_INT_I32_NEG: i32 = i32::min_value().saturating_sub(1); - const SUB_INT_I32_POS: i32 = i32::max_value().saturating_sub(-1); - const SUB_INT_U128: u128 = (0 as u128).saturating_sub(1); - const SUB_INT_I128_NEG: i128 = i128::min_value().saturating_sub(1); - const SUB_INT_I128_POS: i128 = i128::max_value().saturating_sub(-1); - - const MUL_INT_U32_NO: u32 = (42 as u32).saturating_mul(2); - const MUL_INT_U32: u32 = (1 as u32).saturating_mul(2); - const MUL_INT_I32_NO: i32 = (-42 as i32).saturating_mul(2); - const MUL_INT_I32_NEG: i32 = i32::min_value().saturating_mul(1); - const MUL_INT_I32_POS: i32 = i32::max_value().saturating_mul(2); - const MUL_INT_U128: u128 = (0 as u128).saturating_mul(1); - const MUL_INT_I128_NEG: i128 = i128::min_value().saturating_mul(2); - const MUL_INT_I128_POS: i128 = i128::max_value().saturating_mul(2); - - const NEG_INT_I8: i8 = (-42i8).saturating_neg(); - const NEG_INT_I8_B: i8 = i8::min_value().saturating_neg(); - const NEG_INT_I32: i32 = i32::min_value().saturating_neg(); - const NEG_INT_I32_B: i32 = i32::max_value().saturating_neg(); - const NEG_INT_I128: i128 = i128::min_value().saturating_neg(); - const NEG_INT_I128_B: i128 = i128::max_value().saturating_neg(); - - const ABS_INT_I8_A: i8 = 4i8.saturating_abs(); - const ABS_INT_I8_B: i8 = -4i8.saturating_abs(); - const ABS_INT_I8_C: i8 = i8::min_value().saturating_abs(); - const ABS_INT_I32_A: i32 = 4i32.saturating_abs(); - const ABS_INT_I32_B: i32 = -4i32.saturating_abs(); - const ABS_INT_I32_C: i32 = i32::min_value().saturating_abs(); - const ABS_INT_I128_A: i128 = 4i128.saturating_abs(); - const ABS_INT_I128_B: i128 = -4i128.saturating_abs(); - const ABS_INT_I128_C: i128 = i128::min_value().saturating_abs(); - - // `const_int_euclidean` - const CHECKED_DIV_I32_A: Option = 5i32.checked_div_euclid(7777); - const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div_euclid(-99); - const CHECKED_DIV_I8_B: Option = (-127 as i8).checked_div_euclid(1); - const CHECKED_DIV_I8_C: Option = i8::min_value().checked_div_euclid(-1); - const CHECKED_DIV_U8_A: Option = 1u8.checked_div_euclid(3); - - const CHECKED_REM_I32_A: Option = 5i32.checked_rem_euclid(7777); - const CHECKED_REM_I8_A: Option = (-127 as i8).checked_rem_euclid(-99); - const CHECKED_REM_I8_B: Option = (-127 as i8).checked_rem_euclid(0); - const CHECKED_REM_I8_C: Option = i8::min_value().checked_rem_euclid(-1); - const CHECKED_REM_U8_A: Option = 1u8.checked_rem_euclid(3); - - const WRAPPING_DIV_I32_A: i32 = 5i32.wrapping_div_euclid(7777); - const WRAPPING_DIV_I8_A: i8 = (-127 as i8).wrapping_div_euclid(-99); - const WRAPPING_DIV_I8_B: i8 = (-127 as i8).wrapping_div_euclid(1); - const WRAPPING_DIV_I8_C: i8 = i8::min_value().wrapping_div_euclid(-1); - const WRAPPING_DIV_U8_A: u8 = 1u8.wrapping_div_euclid(3); - - const WRAPPING_REM_I32_A: i32 = 5i32.wrapping_rem_euclid(7777); - const WRAPPING_REM_I8_A: i8 = (-127 as i8).wrapping_rem_euclid(-99); - const WRAPPING_REM_I8_B: i8 = (-127 as i8).wrapping_rem_euclid(1); - const WRAPPING_REM_I8_C: i8 = i8::min_value().wrapping_rem_euclid(-1); - const WRAPPING_REM_U8_A: u8 = 1u8.wrapping_rem_euclid(3); - - const OVERFLOWING_DIV_I32_A: (i32, bool) = 5i32.overflowing_div_euclid(7777); - const OVERFLOWING_DIV_I8_A: (i8, bool) = (-127 as i8).overflowing_div_euclid(-99); - const OVERFLOWING_DIV_I8_B: (i8, bool) = (-127 as i8).overflowing_div_euclid(1); - const OVERFLOWING_DIV_I8_C: (i8, bool) = i8::min_value().overflowing_div_euclid(-1); - const OVERFLOWING_DIV_U8_A: (u8, bool) = 1u8.overflowing_div_euclid(3); - - const OVERFLOWING_REM_I32_A: (i32, bool) = 5i32.overflowing_rem_euclid(7777); - const OVERFLOWING_REM_I8_A: (i8, bool) = (-127 as i8).overflowing_rem_euclid(-99); - const OVERFLOWING_REM_I8_B: (i8, bool) = (-127 as i8).overflowing_rem_euclid(1); - const OVERFLOWING_REM_I8_C: (i8, bool) = i8::min_value().overflowing_rem_euclid(-1); - const OVERFLOWING_REM_U8_A: (u8, bool) = 1u8.overflowing_rem_euclid(3); - - // `const_int_wrapping` - const DIV_A: i8 = 8i8.wrapping_div(2); - const DIV_B: i8 = 8i8.wrapping_div(3); - const DIV_C: i8 = i8::min_value().wrapping_div(-1i8); - const DIV_D: u8 = 8u8.wrapping_div(2); - const DIV_E: u8 = 8u8.wrapping_div(3); - - const REM_A: i8 = 8i8.wrapping_rem(2); - const REM_B: i8 = 8i8.wrapping_rem(3); - const REM_C: i8 = i8::min_value().wrapping_rem(-1i8); - const REM_D: u8 = 8u8.wrapping_rem(2); - const REM_E: u8 = 8u8.wrapping_rem(3); +suite!( + checked -> Option { + // `const_checked_int_methods` + C1: 5i8.checked_add(2), Some(7); + C2: 127i8.checked_add(2), None; + + C3: 5i8.checked_sub(2), Some(3); + C4: (-127i8).checked_sub(2), None; + + C5: 1i8.checked_mul(3), Some(3); + C6: 5i8.checked_mul(122), None; + C7: (-127i8).checked_mul(-99), None; + + C8: (i8::min_value() + 1).checked_div(-1), Some(127); + C9: i8::min_value().checked_div(-1), None; + C10: 1i8.checked_div(0), None; + + C11: 5i8.checked_rem(2), Some(1); + C12: 5i8.checked_rem(0), None; + C13: i8::MIN.checked_rem(-1), None; + + C14: 5i8.checked_neg(), Some(-5); + C15: i8::MIN.checked_neg(), None; + + C16: 0x1i8.checked_shl(4), Some(0x10); + C17: 0x1i8.checked_shl(129), None; + + C18: 0x10i8.checked_shr(4), Some(0x1); + C19: 0x10i8.checked_shr(128), None; + + + C20: (-5i8).checked_abs(), Some(5); + C21: i8::MIN.checked_abs(), None; + + // `const_euclidean_int_methods` + C22: (i8::min_value() + 1).checked_div_euclid(-1), Some(127); + C23: i8::min_value().checked_div_euclid(-1), None; + C24: (1i8).checked_div_euclid(0), None; + + C25: 5i8.checked_rem_euclid(2), Some(1); + C26: 5i8.checked_rem_euclid(0), None; + C27: i8::MIN.checked_rem_euclid(-1), None; + } + + saturating_and_wrapping -> i8 { + // `const_saturating_int_methods` + C28: 100i8.saturating_add(1), 101; + C29: i8::max_value().saturating_add(100), i8::max_value(); + C30: i8::min_value().saturating_add(-1), i8::min_value(); + + C31: 100i8.saturating_sub(127), -27; + C32: i8::min_value().saturating_sub(100), i8::min_value(); + C33: i8::max_value().saturating_sub(-1), i8::max_value(); + + C34: 10i8.saturating_mul(12), 120; + C35: i8::MAX.saturating_mul(10), i8::MAX; + C36: i8::MIN.saturating_mul(10), i8::MIN; + + C37: 100i8.saturating_neg(), -100; + C38: (-100i8).saturating_neg(), 100; + C39: i8::min_value().saturating_neg(), i8::max_value(); + C40: i8::max_value().saturating_neg(), i8::min_value() + 1; + + C57: 100i8.saturating_abs(), 100; + C58: (-100i8).saturating_abs(), 100; + C59: i8::min_value().saturating_abs(), i8::max_value(); + C60: (i8::min_value() + 1).saturating_abs(), i8::max_value(); + + // `const_wrapping_int_methods` + C41: 100i8.wrapping_div(10), 10; + C42: (-128i8).wrapping_div(-1), -128; + + C43: 100i8.wrapping_rem(10), 0; + C44: (-128i8).wrapping_rem(-1), 0; + + // `const_euclidean_int_methods` + C45: 100i8.wrapping_div_euclid(10), 10; + C46: (-128i8).wrapping_div_euclid(-1), -128; + + C47: 100i8.wrapping_rem_euclid(10), 0; + C48: (-128i8).wrapping_rem_euclid(-1), 0; + } + + overflowing -> (i8, bool) { + // `const_overflowing_int_methods` + C49: 5i8.overflowing_div(2), (2, false); + C50: i8::MIN.overflowing_div(-1), (i8::MIN, true); + + C51: 5i8.overflowing_rem(2), (1, false); + C52: i8::MIN.overflowing_rem(-1), (0, true); + + // `const_euclidean_int_methods` + C53: 5i8.overflowing_div_euclid(2), (2, false); + C54: i8::MIN.overflowing_div_euclid(-1), (i8::MIN, true); + + C55: 5i8.overflowing_rem_euclid(2), (1, false); + C56: i8::MIN.overflowing_rem_euclid(-1), (0, true); + + } +); + +fn main() { + checked(); + saturating_and_wrapping(); + overflowing(); } From 78f8ad36409754319011514ca6febc8599abd429 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Feb 2020 17:09:22 -0800 Subject: [PATCH 12/12] Implement remaining `unchecked` arithmetic intrinsics --- src/librustc_mir/interpret/intrinsics.rs | 19 +++++++++++++++++-- src/librustc_span/symbol.rs | 5 +++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index cd6d94357e414..f85da760ada6d 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -218,19 +218,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(val, dest)?; } - sym::unchecked_shl | sym::unchecked_shr => { + sym::unchecked_shl + | sym::unchecked_shr + | sym::unchecked_add + | sym::unchecked_sub + | sym::unchecked_mul + | sym::unchecked_div + | sym::unchecked_rem => { let l = self.read_immediate(args[0])?; let r = self.read_immediate(args[1])?; let bin_op = match intrinsic_name { sym::unchecked_shl => BinOp::Shl, sym::unchecked_shr => BinOp::Shr, + sym::unchecked_add => BinOp::Add, + sym::unchecked_sub => BinOp::Sub, + sym::unchecked_mul => BinOp::Mul, + sym::unchecked_div => BinOp::Div, + sym::unchecked_rem => BinOp::Rem, _ => bug!("Already checked for int ops"), }; let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?; if overflowed { let layout = self.layout_of(substs.type_at(0))?; let r_val = self.force_bits(r.to_scalar()?, layout.size)?; - throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); + if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name { + throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); + } else { + throw_ub_format!("Overflow executing `{}`", intrinsic_name); + } } self.write_scalar(val, dest)?; } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index e4f8b5a014389..c060e8948e3ed 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -755,8 +755,13 @@ symbols! { u64, u8, unboxed_closures, + unchecked_add, + unchecked_div, + unchecked_mul, + unchecked_rem, unchecked_shl, unchecked_shr, + unchecked_sub, underscore_const_names, underscore_imports, underscore_lifetimes,