From 9a9cbd6f611884670c0f5942af3e9c0c6bb3ce25 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:12:58 -0500 Subject: [PATCH 01/14] Make Option fns const With #49146 merged, many Option functions can be made const; some are still left out, like `Option.contains` (which requires PartialEq, and trait functions cannot be const), but it's a good start. --- src/libcore/lib.rs | 1 + src/libcore/option.rs | 224 +++++++++++++++++++++++++++++ src/test/ui/consts/const-option.rs | 120 ++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 src/test/ui/consts/const-option.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a2ab85e64baa1..21e97e4d55e28 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -128,6 +128,7 @@ #![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(associated_type_bounds)] +#![cfg_attr(not(bootstrap), feature(const_if_match))] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 2066a484dac80..3526bdc9aa045 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -183,6 +183,20 @@ impl Option { /// ``` /// /// [`Some`]: #variant.Some + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn is_some(&self) -> bool { + match *self { + Some(_) => true, + None => false, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -206,6 +220,18 @@ impl Option { /// ``` /// /// [`None`]: #variant.None + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[must_use = "if you intended to assert that this doesn't have a value, consider \ + `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn is_none(&self) -> bool { + !self.is_some() + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[must_use = "if you intended to assert that this doesn't have a value, consider \ `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"] #[inline] @@ -267,6 +293,19 @@ impl Option { /// let text_length: Option = text.as_ref().map(|s| s.len()); /// println!("still can print text: {:?}", text); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn as_ref(&self) -> Option<&T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_ref(&self) -> Option<&T> { @@ -340,6 +379,19 @@ impl Option { /// let x: Option<&str> = None; /// x.expect("the world is ending"); // panics with `the world is ending` /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn expect(self, msg: &str) -> T { + match self { + Some(val) => val, + None => expect_failed(msg), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn expect(self, msg: &str) -> T { @@ -396,6 +448,19 @@ impl Option { /// assert_eq!(Some("car").unwrap_or("bike"), "car"); /// assert_eq!(None.unwrap_or("bike"), "bike"); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn unwrap_or(self, default: T) -> T { + match self { + Some(x) => x, + None => default, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or(self, default: T) -> T { @@ -414,6 +479,19 @@ impl Option { /// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn unwrap_or_else T>(self, f: F) -> T { + match self { + Some(x) => x, + None => f(), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_else T>(self, f: F) -> T { @@ -443,6 +521,19 @@ impl Option { /// /// assert_eq!(maybe_some_len, Some(13)); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn map U>(self, f: F) -> Option { + match self { + Some(x) => Some(f(x)), + None => None, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map U>(self, f: F) -> Option { @@ -464,6 +555,19 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.map_or(42, |v| v.len()), 42); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn map_or U>(self, default: U, f: F) -> U { + match self { + Some(t) => f(t), + None => default, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map_or U>(self, default: U, f: F) -> U { @@ -487,6 +591,19 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + match self { + Some(t) => f(t), + None => default(), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { @@ -519,6 +636,19 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.ok_or(0), Err(0)); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn ok_or(self, err: E) -> Result { + match self { + Some(v) => Ok(v), + None => Err(err), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn ok_or(self, err: E) -> Result { @@ -546,6 +676,19 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.ok_or_else(|| 0), Err(0)); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn ok_or_else E>(self, err: F) -> Result { + match self { + Some(v) => Ok(v), + None => Err(err()), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn ok_or_else E>(self, err: F) -> Result { @@ -624,6 +767,19 @@ impl Option { /// let y: Option<&str> = None; /// assert_eq!(x.and(y), None); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn and(self, optb: Option) -> Option { + match self { + Some(_) => optb, + None => None, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn and(self, optb: Option) -> Option { @@ -651,6 +807,19 @@ impl Option { /// assert_eq!(Some(2).and_then(nope).and_then(sq), None); /// assert_eq!(None.and_then(sq).and_then(sq), None); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn and_then Option>(self, f: F) -> Option { + match self { + Some(x) => f(x), + None => None, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn and_then Option>(self, f: F) -> Option { @@ -686,6 +855,21 @@ impl Option { /// [`None`]: #variant.None /// [`Some(t)`]: #variant.Some /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "option_filter", since = "1.27.0")] + pub const fn filter bool>(self, predicate: P) -> Self { + if let Some(x) = self { + if predicate(&x) { + return Some(x); + } + } + None + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "option_filter", since = "1.27.0")] pub fn filter bool>(self, predicate: P) -> Self { @@ -724,6 +908,19 @@ impl Option { /// let y = None; /// assert_eq!(x.or(y), None); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn or(self, optb: Option) -> Option { + match self { + Some(_) => self, + None => optb, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or(self, optb: Option) -> Option { @@ -746,6 +943,19 @@ impl Option { /// assert_eq!(None.or_else(vikings), Some("vikings")); /// assert_eq!(None.or_else(nobody), None); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn or_else Option>(self, f: F) -> Option { + match self { + Some(_) => self, + None => f(), + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or_else Option>(self, f: F) -> Option { @@ -779,6 +989,20 @@ impl Option { /// let y: Option = None; /// assert_eq!(x.xor(y), None); /// ``` + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + #[inline] + #[stable(feature = "option_xor", since = "1.37.0")] + pub const fn xor(self, optb: Option) -> Option { + match (self, optb) { + (Some(a), None) => Some(a), + (None, Some(b)) => Some(b), + _ => None, + } + } + + /// No docs for bootstrap. + #[cfg(bootstrap)] #[inline] #[stable(feature = "option_xor", since = "1.37.0")] pub fn xor(self, optb: Option) -> Option { diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs new file mode 100644 index 0000000000000..831e48c39bfc6 --- /dev/null +++ b/src/test/ui/consts/const-option.rs @@ -0,0 +1,120 @@ +// run-pass +#![feature(const_option_match)] +#![feature(option_result_contains)] + +macro_rules! assert_same_const { + ($(const $ident:ident: $ty:ty = $exp:expr;)+) => { + $(const $ident: $ty = $exp;)+ + + pub fn main() { + $(assert_eq!($exp, $ident);)+ + } + } +} + +// These functions let us use the functional interfaces of Option (like unwrap_or_else, map_or, +// map, etc.) without using closures, which aren't implemented in const contexts yet; see +// https://github.com/rust-lang/rust/issues/63997 + +const fn is_zero(i: i32) -> bool { + i == 0i32 +} + +const fn get_zero() -> i32 { + 0 +} + +const fn get_false() -> bool { + false +} + +const fn get_some() -> Option { + Some(2) +} + +const fn get_none() -> Option { + None +} + +const fn is_pos(i: &i32) -> bool { + i.is_positive() +} + +const fn is_neg(i: &i32) -> bool { + i.is_negative() +} + +const fn i32_to_some(i: i32) -> Option { + Some(i * 2) +} + +const fn i32_to_none(_i: i32) -> Option { + None +} + +assert_same_const! { + const SOME: Option = Some(3); + const NONE: Option = None; + + const IS_SOME_A: bool = SOME.is_some(); + const IS_SOME_B: bool = NONE.is_some(); + + const IS_NONE_A: bool = SOME.is_none(); + const IS_NONE_B: bool = NONE.is_none(); + + const AS_REF_A: Option<&i32> = SOME.as_ref(); + const AS_REF_B: Option<&i32> = NONE.as_ref(); + + const EXPECT_A: i32 = SOME.expect("This is dangerous!"); + + const UNWRAP_OR_A: i32 = SOME.unwrap_or(0); + const UNWRAP_OR_B: i32 = NONE.unwrap_or(0); + + const UNWRAP_OR_ELSE_A: i32 = SOME.unwrap_or_else(get_zero); + const UNWRAP_OR_ELSE_B: i32 = NONE.unwrap_or_else(get_zero); + + const MAP_A: Option = SOME.map(is_zero); + const MAP_B: Option = NONE.map(is_zero); + + const MAP_OR_A: bool = SOME.map_or(false, is_zero); + const MAP_OR_B: bool = NONE.map_or(false, is_zero); + + const MAP_OR_ELSE_A: bool = SOME.map_or_else(get_false, is_zero); + const MAP_OR_ELSE_B: bool = NONE.map_or_else(get_false, is_zero); + + const OK_OR_A: Result = SOME.ok_or(false); + const OK_OR_B: Result = NONE.ok_or(false); + + const OK_OR_ELSE_A: Result = SOME.ok_or_else(get_false); + const OK_OR_ELSE_B: Result = NONE.ok_or_else(get_false); + + const AND_A: Option = SOME.and(Some(true)); + const AND_B: Option = SOME.and(None); + const AND_C: Option = NONE.and(Some(true)); + const AND_D: Option = NONE.and(None); + + const AND_THEN_A: Option = SOME.and_then(i32_to_some); + const AND_THEN_B: Option = SOME.and_then(i32_to_none); + const AND_THEN_C: Option = NONE.and_then(i32_to_some); + const AND_THEN_D: Option = NONE.and_then(i32_to_none); + + const FILTER_A: Option = SOME.filter(is_pos); + const FILTER_B: Option = SOME.filter(is_neg); + const FILTER_C: Option = NONE.filter(is_pos); + const FILTER_D: Option = NONE.filter(is_neg); + + const OR_A: Option = SOME.or(Some(1)); + const OR_B: Option = SOME.or(None); + const OR_C: Option = NONE.or(Some(1)); + const OR_D: Option = NONE.or(None); + + const OR_ELSE_A: Option = SOME.or_else(get_some); + const OR_ELSE_B: Option = SOME.or_else(get_none); + const OR_ELSE_C: Option = NONE.or_else(get_some); + const OR_ELSE_D: Option = NONE.or_else(get_none); + + const XOR_A: Option = SOME.xor(Some(1)); + const XOR_B: Option = SOME.xor(None); + const XOR_C: Option = NONE.xor(Some(1)); + const XOR_D: Option = NONE.xor(None); +} From 20db398fb44835e66aaebe08db76b13d662e5bf7 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:17:44 -0500 Subject: [PATCH 02/14] Make NonZero*::new const With #49146 merged, NonZero*::new can be const; see #53718. --- src/libcore/num/mod.rs | 15 ++++++++ src/test/ui/consts/const-int-nonzero.rs | 47 +++++++++++++++++++++++++ src/test/ui/consts/const-nonzero.rs | 9 ----- 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/consts/const-int-nonzero.rs delete mode 100644 src/test/ui/consts/const-nonzero.rs diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6c864f74b1f14..749ac57b108ff 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -70,6 +70,21 @@ assert_eq!(size_of::>(), size_of::<", s /// Creates a non-zero if the given value is not zero. #[$stability] #[inline] + #[rustc_const_unstable(feature = "const_int_nonzero")] + #[cfg(not(bootstrap))] + pub const fn new(n: $Int) -> Option { + if n != 0 { + // SAFETY: we just checked that there's no `0` + Some(unsafe { $Ty(n) }) + } else { + None + } + } + + /// No docs for bootstrap. + #[$stability] + #[inline] + #[cfg(bootstrap)] pub fn new(n: $Int) -> Option { if n != 0 { // SAFETY: we just checked that there's no `0` diff --git a/src/test/ui/consts/const-int-nonzero.rs b/src/test/ui/consts/const-int-nonzero.rs new file mode 100644 index 0000000000000..31391875fe68d --- /dev/null +++ b/src/test/ui/consts/const-int-nonzero.rs @@ -0,0 +1,47 @@ +// run-pass +#![feature(const_int_nonzero)] + +use std::num::{ + NonZeroI8, + NonZeroU8, + NonZeroI32, + NonZeroUsize, +}; + +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 NON_ZERO_NEW_1: Option = NonZeroI8::new(1); + const NON_ZERO_NEW_2: Option = NonZeroI8::new(0); + const NON_ZERO_NEW_3: Option = NonZeroI8::new(-38); + const NON_ZERO_NEW_4: Option = NonZeroU8::new(1); + const NON_ZERO_NEW_5: Option = NonZeroU8::new(0); + const NON_ZERO_NEW_6: Option = NonZeroI32::new(1); + const NON_ZERO_NEW_7: Option = NonZeroI32::new(0); + const NON_ZERO_NEW_8: Option = NonZeroI32::new(-38); + const NON_ZERO_NEW_9: Option = NonZeroUsize::new(1); + const NON_ZERO_NEW_10: Option = NonZeroUsize::new(0); + + // Option::unwrap isn't supported in const yet, so we use new_unchecked. + const NON_ZERO_GET_1: i8 = unsafe { NonZeroI8::new_unchecked(1) }.get(); + const NON_ZERO_GET_2: i8 = unsafe { NonZeroI8::new_unchecked(-38) }.get(); + const NON_ZERO_GET_3: u8 = unsafe { NonZeroU8::new_unchecked(1) }.get(); + const NON_ZERO_GET_4: i32 = unsafe { NonZeroI32::new_unchecked(1) }.get(); + const NON_ZERO_GET_5: i32 = unsafe { NonZeroI32::new_unchecked(-38) }.get(); + const NON_ZERO_GET_6: usize = unsafe { NonZeroUsize::new_unchecked(1) }.get(); + + const NON_ZERO_NEW_UNCHECKED_1: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(1) }; + const NON_ZERO_NEW_UNCHECKED_2: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(-38) }; + const NON_ZERO_NEW_UNCHECKED_3: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(1) }; + const NON_ZERO_NEW_UNCHECKED_4: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(1) }; + const NON_ZERO_NEW_UNCHECKED_5: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(-38) }; + const NON_ZERO_NEW_UNCHECKED_6: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(1) }; +} diff --git a/src/test/ui/consts/const-nonzero.rs b/src/test/ui/consts/const-nonzero.rs deleted file mode 100644 index 6db3d1b3331fa..0000000000000 --- a/src/test/ui/consts/const-nonzero.rs +++ /dev/null @@ -1,9 +0,0 @@ -// build-pass (FIXME(62277): could be check-pass?) - -use std::num::NonZeroU8; - -const X: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; -const Y: u8 = X.get(); - -fn main() { -} From 09994afaff9fe48219114fea8df61053ab35cc5d Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:24:21 -0500 Subject: [PATCH 03/14] Make overflowing_div and overflowing_rem const With #49146 merged, {u8,i8,u16,...}::overflowing_div and ::overflowing_rem can be const; see #53718. --- src/libcore/num/mod.rs | 63 +++++++++++++++++-- .../ui/consts/const-int-overflowing-rpass.rs | 25 ++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 749ac57b108ff..6cf2ac9000969 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1595,7 +1595,9 @@ $EndFeature, " #[stable(feature = "wrapping", since = "1.7.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { @@ -1604,6 +1606,20 @@ $EndFeature, " } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (self, true) + } else { + (self / rhs, false) + } + } + doc_comment! { concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. @@ -1663,7 +1679,9 @@ $EndFeature, " #[stable(feature = "wrapping", since = "1.7.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { @@ -1672,6 +1690,19 @@ $EndFeature, " } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (0, true) + } else { + (self % rhs, false) + } + } doc_comment! { concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. @@ -3517,11 +3548,23 @@ Basic usage #[stable(feature = "wrapping", since = "1.7.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) + } + doc_comment! { concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. @@ -3576,11 +3619,23 @@ Basic usage #[stable(feature = "wrapping", since = "1.7.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) + } + doc_comment! { concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. diff --git a/src/test/ui/consts/const-int-overflowing-rpass.rs b/src/test/ui/consts/const-int-overflowing-rpass.rs index 9be87a6447cda..7b1a161348568 100644 --- a/src/test/ui/consts/const-int-overflowing-rpass.rs +++ b/src/test/ui/consts/const-int-overflowing-rpass.rs @@ -1,4 +1,5 @@ // run-pass +#![feature(const_int_overflowing)] const ADD_A: (u32, bool) = 5u32.overflowing_add(2); const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1); @@ -22,6 +23,18 @@ const ABS_POS: (i32, bool) = 10i32.overflowing_abs(); const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs(); const ABS_MIN: (i32, bool) = i32::min_value().overflowing_abs(); +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); + fn main() { assert_eq!(ADD_A, (7, false)); assert_eq!(ADD_B, (0, true)); @@ -44,4 +57,16 @@ fn main() { assert_eq!(ABS_POS, (10, false)); assert_eq!(ABS_NEG, (10, false)); assert_eq!(ABS_MIN, (i32::min_value(), true)); + + assert_eq!(DIV_A, (4i8, false)); + assert_eq!(DIV_B, (2i8, false)); + assert_eq!(DIV_C, (i8::min_value(), true)); + assert_eq!(DIV_D, (4u8, false)); + assert_eq!(DIV_E, (2u8, false)); + + assert_eq!(REM_A, (0i8, false)); + assert_eq!(REM_B, (2i8, false)); + assert_eq!(REM_C, (0i8, true)); + assert_eq!(REM_D, (0u8, false)); + assert_eq!(REM_E, (2u8, false)); } From 9aa0a1fd0af17382c18a86dc50ae1caec7cac26a Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:28:17 -0500 Subject: [PATCH 04/14] Power-of-two int tests Most of these have to be deleted; the various power_of_two functions use `intrinsics::ctlz_nonzero` internally, so they can't be made const before #66275 is merged. --- src/test/ui/consts/const-int-pow-rpass.rs | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs index 8e84a900605f5..35bb0d5c9eddc 100644 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -1,11 +1,47 @@ // run-pass +// #![feature(const_int_pow)] +#![feature(wrapping_next_power_of_two)] const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); +const NEXT_POWER_OF_TWO_A: u32 = 0u32.next_power_of_two(); +const NEXT_POWER_OF_TWO_B: u8 = 2u8.next_power_of_two(); +const NEXT_POWER_OF_TWO_C: u8 = 3u8.next_power_of_two(); +const NEXT_POWER_OF_TWO_D: u8 = 127u8.next_power_of_two(); + +const CHECKED_NEXT_POWER_OF_TWO_A: Option = 0u32.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_B: Option = 2u8.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_C: Option = 3u8.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_D: Option = 127u8.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_E: Option = 129u8.checked_next_power_of_two(); + +const WRAPPING_NEXT_POWER_OF_TWO_A: u32 = 0u32.wrapping_next_power_of_two(); +const WRAPPING_NEXT_POWER_OF_TWO_B: u8 = 2u8.wrapping_next_power_of_two(); +const WRAPPING_NEXT_POWER_OF_TWO_C: u8 = 3u8.wrapping_next_power_of_two(); +const WRAPPING_NEXT_POWER_OF_TWO_D: u8 = 127u8.wrapping_next_power_of_two(); +const WRAPPING_NEXT_POWER_OF_TWO_E: u8 = u8::max_value().wrapping_next_power_of_two(); + fn main() { assert!(!IS_POWER_OF_TWO_A); assert!(IS_POWER_OF_TWO_B); assert!(!IS_POWER_OF_TWO_C); + + assert_eq!(NEXT_POWER_OF_TWO_A, 2); + assert_eq!(NEXT_POWER_OF_TWO_B, 2); + assert_eq!(NEXT_POWER_OF_TWO_C, 4); + assert_eq!(NEXT_POWER_OF_TWO_D, 128); + + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_A, Some(2)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_B, Some(2)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_C, Some(4)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_D, Some(128)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_E, None); + + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_A, 2); + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_B, 2); + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_C, 4); + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_D, 128); + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_E, 0); } From 60168a7ac98176367e2e9a77f3a5bb1141113e40 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:31:05 -0500 Subject: [PATCH 05/14] Power-of-two int tests Most of the tests had to be deleted; the various power_of_two functions use `intrinsics::ctlz_nonzero` internally, so they can't be made const before #66275 is merged. --- src/test/ui/consts/const-int-pow-rpass.rs | 36 ++--------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs index 35bb0d5c9eddc..26fb40650d451 100644 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -5,43 +5,11 @@ const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); - -const NEXT_POWER_OF_TWO_A: u32 = 0u32.next_power_of_two(); -const NEXT_POWER_OF_TWO_B: u8 = 2u8.next_power_of_two(); -const NEXT_POWER_OF_TWO_C: u8 = 3u8.next_power_of_two(); -const NEXT_POWER_OF_TWO_D: u8 = 127u8.next_power_of_two(); - -const CHECKED_NEXT_POWER_OF_TWO_A: Option = 0u32.checked_next_power_of_two(); -const CHECKED_NEXT_POWER_OF_TWO_B: Option = 2u8.checked_next_power_of_two(); -const CHECKED_NEXT_POWER_OF_TWO_C: Option = 3u8.checked_next_power_of_two(); -const CHECKED_NEXT_POWER_OF_TWO_D: Option = 127u8.checked_next_power_of_two(); -const CHECKED_NEXT_POWER_OF_TWO_E: Option = 129u8.checked_next_power_of_two(); - -const WRAPPING_NEXT_POWER_OF_TWO_A: u32 = 0u32.wrapping_next_power_of_two(); -const WRAPPING_NEXT_POWER_OF_TWO_B: u8 = 2u8.wrapping_next_power_of_two(); -const WRAPPING_NEXT_POWER_OF_TWO_C: u8 = 3u8.wrapping_next_power_of_two(); -const WRAPPING_NEXT_POWER_OF_TWO_D: u8 = 127u8.wrapping_next_power_of_two(); -const WRAPPING_NEXT_POWER_OF_TWO_E: u8 = u8::max_value().wrapping_next_power_of_two(); +const IS_POWER_OF_TWO_D: bool = 3u8.is_power_of_two(); fn main() { assert!(!IS_POWER_OF_TWO_A); assert!(IS_POWER_OF_TWO_B); assert!(!IS_POWER_OF_TWO_C); - - assert_eq!(NEXT_POWER_OF_TWO_A, 2); - assert_eq!(NEXT_POWER_OF_TWO_B, 2); - assert_eq!(NEXT_POWER_OF_TWO_C, 4); - assert_eq!(NEXT_POWER_OF_TWO_D, 128); - - assert_eq!(CHECKED_NEXT_POWER_OF_TWO_A, Some(2)); - assert_eq!(CHECKED_NEXT_POWER_OF_TWO_B, Some(2)); - assert_eq!(CHECKED_NEXT_POWER_OF_TWO_C, Some(4)); - assert_eq!(CHECKED_NEXT_POWER_OF_TWO_D, Some(128)); - assert_eq!(CHECKED_NEXT_POWER_OF_TWO_E, None); - - assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_A, 2); - assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_B, 2); - assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_C, 4); - assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_D, 128); - assert_eq!(WRAPPING_NEXT_POWER_OF_TWO_E, 0); + assert!(!IS_POWER_OF_TWO_D); } From 5e44a24a49c2c49d90ef93d318407b7680414a21 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:42:39 -0500 Subject: [PATCH 06/14] Make checked int fns const --- src/libcore/num/mod.rs | 260 ++++++++++++++++++++++-- src/test/ui/consts/const-int-checked.rs | 57 ++++++ 2 files changed, 298 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/consts/const-int-checked.rs diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6cf2ac9000969..1034b8a692ca3 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -659,12 +659,25 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_add(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_add(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_add(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -683,12 +696,25 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_sub(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_sub(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -707,12 +733,25 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -732,7 +771,9 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_div(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -742,6 +783,21 @@ $EndFeature, " } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_div(self, rhs: Self) -> Option { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { + None + } else { + // SAFETY: div by zero and by INT_MIN have been checked above + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) + } + } + doc_comment! { concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0` or the division results in overflow. @@ -843,12 +899,23 @@ $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn checked_neg(self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(bootstrap)] + pub fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -866,12 +933,26 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} } } + + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_shl(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shl(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -889,12 +970,25 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_shr(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shr(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked absolute value. Computes `self.abs()`, returning `None` if `self == MIN`. @@ -912,7 +1006,9 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] - pub fn checked_abs(self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_abs(self) -> Option { if self.is_negative() { self.checked_neg() } else { @@ -921,6 +1017,18 @@ $EndFeature, " } } + /// No docs for bootstrap. + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[inline] + #[cfg(bootstrap)] + pub fn checked_abs(self) -> Option { + if self.is_negative() { + self.checked_neg() + } else { + Some(self) + } + } + doc_comment! { concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow occurred. @@ -1035,8 +1143,11 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] + #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] - pub fn saturating_neg(self) -> Self { + pub const fn saturating_neg(self) -> Self { intrinsics::saturating_sub(0, self) } } @@ -2782,12 +2893,25 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_add(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_add(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_add(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -2804,12 +2928,25 @@ assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_sub(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_sub(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -2826,12 +2963,25 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFe #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`. @@ -2848,7 +2998,9 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + 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 @@ -2858,6 +3010,21 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " } } + /// No docs for bootstrap. + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub 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 + // failure modes for division + rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }), + } + } + doc_comment! { concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0`. @@ -2900,7 +3067,9 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_rem(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -2911,6 +3080,22 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_rem(self, rhs: Self) -> Option { + if rhs == 0 { + None + } else { + // SAFETY: div by zero has been checked above and unsigned types have no other + // failure modes for division + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) + } + } + doc_comment! { concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` if `rhs == 0`. @@ -2952,12 +3137,23 @@ assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn checked_neg(self) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(bootstrap)] + pub fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -2974,12 +3170,25 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_shl(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shl(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -2996,12 +3205,25 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "const_int_checked")] + #[cfg(not(bootstrap))] + pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_shr(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shr(rhs); + if b {None} else {Some(a)} + } + doc_comment! { concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow occurred. @@ -3518,7 +3740,7 @@ $EndFeature, " #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); @@ -3808,7 +4030,7 @@ Basic usage: ```"), #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub fn pow(self, mut exp: u32) -> Self { diff --git a/src/test/ui/consts/const-int-checked.rs b/src/test/ui/consts/const-int-checked.rs new file mode 100644 index 0000000000000..de9d29b7fa672 --- /dev/null +++ b/src/test/ui/consts/const-int-checked.rs @@ -0,0 +1,57 @@ +// run-pass +#![feature(const_int_checked)] + +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 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); + + // Needs intrinsics::unchecked_div. + // 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); + + // Needs intrinsics::unchecked_rem. + // 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(); +} From 17ab2c476c1da902cb75c37588d07ebe7b97e5a7 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:47:10 -0500 Subject: [PATCH 07/14] Make wrapping int fns const With #49146 merged, these can be const; see #53718. --- src/libcore/num/mod.rs | 58 +++++++++++++++++-- .../ui/consts/const-int-wrapping-rpass.rs | 25 ++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1034b8a692ca3..3275f02ac8836 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1338,11 +1338,23 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_wrapping")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div(self, rhs: Self) -> Self { self.overflowing_div(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div(self, rhs: Self) -> Self { + self.overflowing_div(rhs).0 + } + doc_comment! { concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, wrapping around at the boundary of the type. @@ -1397,11 +1409,23 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_wrapping")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem(self, rhs: Self) -> Self { self.overflowing_rem(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem(self, rhs: Self) -> Self { + self.overflowing_rem(rhs).0 + } + doc_comment! { concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around at the boundary of the type. @@ -3422,7 +3446,7 @@ $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { intrinsics::wrapping_mul(self, rhs) @@ -3446,11 +3470,23 @@ Basic usage: #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_wrapping")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div(self, rhs: Self) -> Self { self / rhs } } + /// No docs for bootstrap. + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div(self, rhs: Self) -> Self { + self / rhs + } + doc_comment! { concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped division on unsigned types is just normal division. @@ -3496,11 +3532,23 @@ Basic usage: #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_wrapping")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem(self, rhs: Self) -> Self { self % rhs } } + /// No docs for bootstrap. + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem(self, rhs: Self) -> Self { + self % rhs + } + doc_comment! { concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped modulo calculation on unsigned types is diff --git a/src/test/ui/consts/const-int-wrapping-rpass.rs b/src/test/ui/consts/const-int-wrapping-rpass.rs index 2bbad99a52a90..40b22464e596f 100644 --- a/src/test/ui/consts/const-int-wrapping-rpass.rs +++ b/src/test/ui/consts/const-int-wrapping-rpass.rs @@ -1,4 +1,5 @@ // run-pass +#![feature(const_int_wrapping)] const ADD_A: u32 = 200u32.wrapping_add(55); const ADD_B: u32 = 200u32.wrapping_add(u32::max_value()); @@ -22,6 +23,18 @@ const ABS_POS: i32 = 10i32.wrapping_abs(); const ABS_NEG: i32 = (-10i32).wrapping_abs(); const ABS_MIN: i32 = i32::min_value().wrapping_abs(); +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); + fn main() { assert_eq!(ADD_A, 255); assert_eq!(ADD_B, 199); @@ -44,4 +57,16 @@ fn main() { assert_eq!(ABS_POS, 10); assert_eq!(ABS_NEG, 10); assert_eq!(ABS_MIN, i32::min_value()); + + assert_eq!(DIV_A, 4i8); + assert_eq!(DIV_B, 2i8); + assert_eq!(DIV_C, i8::min_value()); + assert_eq!(DIV_D, 4u8); + assert_eq!(DIV_E, 2u8); + + assert_eq!(REM_A, 0i8); + assert_eq!(REM_B, 2i8); + assert_eq!(REM_C, 0i8); + assert_eq!(REM_D, 0u8); + assert_eq!(REM_E, 2u8); } From e749327877a8c49e8939ecc6c8f32012c6dae222 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:49:57 -0500 Subject: [PATCH 08/14] Make saturating int fns const With #49146 merged, these can be const; see #53718. --- src/libcore/num/mod.rs | 49 +++++++- .../ui/consts/const-int-saturating-arith.rs | 110 +++++++++++++----- 2 files changed, 126 insertions(+), 33 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 3275f02ac8836..a88927f0a9c8c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1172,8 +1172,11 @@ $EndFeature, " ```"), #[unstable(feature = "saturating_neg", issue = "59983")] + #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] - pub fn saturating_abs(self) -> Self { + pub const fn saturating_abs(self) -> Self { if self.is_negative() { self.saturating_neg() } else { @@ -1202,14 +1205,38 @@ $EndFeature, " #[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(|| { + #[rustc_const_unstable(feature = "const_int_saturating")] + #[cfg(not(bootstrap))] + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(r) => r, + None => { + if (self < 0) == (rhs < 0) { + Self::max_value() + } else { + Self::min_value() + } + }, + } + } + } + + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(r) => r, + None => { if (self < 0) == (rhs < 0) { Self::max_value() } else { Self::min_value() } - }) + }, } } @@ -3351,11 +3378,23 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn saturating_mul(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_saturating")] + #[cfg(not(bootstrap))] + pub const fn saturating_mul(self, rhs: Self) -> Self { self.checked_mul(rhs).unwrap_or(Self::max_value()) } } + /// No docs for bootstrap. + #[stable(feature = "wrapping", since = "1.7.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn saturating_mul(self, rhs: Self) -> Self { + self.checked_mul(rhs).unwrap_or(Self::max_value()) + } + doc_comment! { concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the numeric bounds instead of overflowing. diff --git a/src/test/ui/consts/const-int-saturating-arith.rs b/src/test/ui/consts/const-int-saturating-arith.rs index d0a3eccd17763..fae273ea20bc8 100644 --- a/src/test/ui/consts/const-int-saturating-arith.rs +++ b/src/test/ui/consts/const-int-saturating-arith.rs @@ -1,34 +1,88 @@ // run-pass #![feature(const_saturating_int_methods)] +#![feature(const_int_saturating)] +#![feature(saturating_neg)] -const INT_U32_NO: u32 = (42 as u32).saturating_add(2); -const INT_U32: u32 = u32::max_value().saturating_add(1); -const INT_U128: u128 = u128::max_value().saturating_add(1); -const INT_I128: i128 = i128::max_value().saturating_add(1); -const INT_I128_NEG: i128 = i128::min_value().saturating_add(-1); - -const INT_U32_NO_SUB: u32 = (42 as u32).saturating_sub(2); -const INT_U32_SUB: u32 = (1 as u32).saturating_sub(2); -const INT_I32_NO_SUB: i32 = (-42 as i32).saturating_sub(2); -const INT_I32_NEG_SUB: i32 = i32::min_value().saturating_sub(1); -const INT_I32_POS_SUB: i32 = i32::max_value().saturating_sub(-1); -const INT_U128_SUB: u128 = (0 as u128).saturating_sub(1); -const INT_I128_NEG_SUB: i128 = i128::min_value().saturating_sub(1); -const INT_I128_POS_SUB: i128 = i128::max_value().saturating_sub(-1); +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(); fn main() { - assert_eq!(INT_U32_NO, 44); - assert_eq!(INT_U32, u32::max_value()); - assert_eq!(INT_U128, u128::max_value()); - assert_eq!(INT_I128, i128::max_value()); - assert_eq!(INT_I128_NEG, i128::min_value()); - - assert_eq!(INT_U32_NO_SUB, 40); - assert_eq!(INT_U32_SUB, 0); - assert_eq!(INT_I32_NO_SUB, -44); - assert_eq!(INT_I32_NEG_SUB, i32::min_value()); - assert_eq!(INT_I32_POS_SUB, i32::max_value()); - assert_eq!(INT_U128_SUB, 0); - assert_eq!(INT_I128_NEG_SUB, i128::min_value()); - assert_eq!(INT_I128_POS_SUB, i128::max_value()); + assert_eq!(ADD_INT_U32_NO, 44); + assert_eq!(ADD_INT_U32, u32::max_value()); + assert_eq!(ADD_INT_U128, u128::max_value()); + assert_eq!(ADD_INT_I128, i128::max_value()); + assert_eq!(ADD_INT_I128_NEG, i128::min_value()); + + assert_eq!(SUB_INT_U32_NO, 40); + assert_eq!(SUB_INT_U32, 0); + assert_eq!(SUB_INT_I32_NO, -44); + assert_eq!(SUB_INT_I32_NEG, i32::min_value()); + assert_eq!(SUB_INT_I32_POS, i32::max_value()); + assert_eq!(SUB_INT_U128, 0); + assert_eq!(SUB_INT_I128_NEG, i128::min_value()); + assert_eq!(SUB_INT_I128_POS, i128::max_value()); + + assert_eq!(MUL_INT_U32_NO, 84); + assert_eq!(MUL_INT_U32, 2); + assert_eq!(MUL_INT_I32_NO, -84); + assert_eq!(MUL_INT_I32_NEG, i32::min_value()); + assert_eq!(MUL_INT_I32_POS, i32::max_value()); + assert_eq!(MUL_INT_U128, 0); + assert_eq!(MUL_INT_I128_NEG, i128::min_value()); + assert_eq!(MUL_INT_I128_POS, i128::max_value()); + + assert_eq!(NEG_INT_I8, 42); + assert_eq!(NEG_INT_I8_B, i8::max_value()); + assert_eq!(NEG_INT_I32, i32::max_value()); + assert_eq!(NEG_INT_I32_B, i32::min_value() + 1); + assert_eq!(NEG_INT_I128, i128::max_value()); + assert_eq!(NEG_INT_I128_B, i128::min_value() + 1); + + assert_eq!(ABS_INT_I8_A, 4i8); + assert_eq!(ABS_INT_I8_B, -4i8); + assert_eq!(ABS_INT_I8_C, i8::max_value()); + assert_eq!(ABS_INT_I32_A, 4i32); + assert_eq!(ABS_INT_I32_B, -4i32); + assert_eq!(ABS_INT_I32_C, i32::max_value()); + assert_eq!(ABS_INT_I128_A, 4i128); + assert_eq!(ABS_INT_I128_B, -4i128); + assert_eq!(ABS_INT_I128_C, i128::max_value()); } From 5909f54cf223585686a00362bb6dd40dedbb85e0 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 00:56:03 -0500 Subject: [PATCH 09/14] Make Euclidean int fns const With #49146 merged, these can be const; see #53718. --- src/libcore/num/mod.rs | 249 ++++++++++++++++++++-- src/test/ui/consts/const-int-euclidean.rs | 51 +++++ 2 files changed, 285 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/consts/const-int-euclidean.rs diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a88927f0a9c8c..70118e8c0a9f5 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -816,7 +816,9 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -825,6 +827,20 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_div_euclid(self, rhs: Self) -> Option { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { + None + } else { + Some(self.div_euclid(rhs)) + } + } + doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -874,7 +890,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { @@ -883,6 +901,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_rem_euclid(self, rhs: Self) -> Option { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`. @@ -1406,11 +1438,23 @@ assert_eq!((-128i8).wrapping_div_euclid(-1), -128); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self.overflowing_div_euclid(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 + } + doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the boundary of the type. @@ -1476,11 +1520,23 @@ assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self.overflowing_rem_euclid(rhs).0 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 + } + doc_comment! { concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary of the type. @@ -1807,7 +1863,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { @@ -1816,6 +1874,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (self, true) + } else { + (self.div_euclid(rhs), false) + } + } + doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -1890,7 +1962,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { @@ -1899,6 +1973,20 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + if self == Self::min_value() && rhs == -1 { + (0, true) + } else { + (self.rem_euclid(rhs), false) + } + } + doc_comment! { concat!("Negates self, overflowing if this is equal to the minimum value. @@ -2130,7 +2218,9 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + 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 } @@ -2139,6 +2229,21 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn div_euclid(self, rhs: Self) -> Self { + let q = self / rhs; + if self % rhs < 0 { + return if rhs > 0 { q - 1 } else { q + 1 } + } + q + } + doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. @@ -2169,7 +2274,9 @@ assert_eq!((-a).rem_euclid(-b), 1); without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2183,6 +2290,26 @@ assert_eq!((-a).rem_euclid(-b), 1); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0 { + if rhs < 0 { + r - rhs + } else { + r + rhs + } + } else { + r + } + } + doc_comment! { concat!("Computes the absolute value of `self`. @@ -3092,7 +3219,9 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -3101,6 +3230,20 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_div_euclid(self, rhs: Self) -> Option { + if rhs == 0 { + None + } else { + Some(self.div_euclid(rhs)) + } + } + doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` @@ -3163,7 +3306,9 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { @@ -3172,6 +3317,20 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn checked_rem_euclid(self, rhs: Self) -> Option { + if rhs == 0 { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` unless `self == 0`. @@ -3547,11 +3706,23 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self / rhs + } + doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`. Wrapped remainder calculation on unsigned types is @@ -3610,11 +3781,23 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[cfg(bootstrap)] + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + /// Wrapping (modular) negation. Computes `-self`, /// wrapping around at the boundary of the type. /// @@ -3900,11 +4083,22 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) + } + doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -3971,11 +4165,23 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } + /// No docs for bootstrap. + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg(bootstrap)] + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) + } + doc_comment! { concat!("Negates self in an overflowing fashion. @@ -4166,11 +4372,24 @@ assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn div_euclid(self, rhs: Self) -> Self { self / rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn div_euclid(self, rhs: Self) -> Self { + self / rhs + } + doc_comment! { concat!("Calculates the least remainder of `self (mod rhs)`. diff --git a/src/test/ui/consts/const-int-euclidean.rs b/src/test/ui/consts/const-int-euclidean.rs new file mode 100644 index 0000000000000..447d0ef39d344 --- /dev/null +++ b/src/test/ui/consts/const-int-euclidean.rs @@ -0,0 +1,51 @@ +// run-pass +#![feature(const_int_euclidean)] +#![feature(saturating_neg)] + +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 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); +} From 70488cf247c9a8fa5096dffa92bb0733a6817ca4 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Mon, 2 Dec 2019 23:42:31 -0500 Subject: [PATCH 10/14] Make Option.transpose and Option.flatten const --- src/libcore/option.rs | 24 ++++++++++++++++++++++++ src/test/ui/consts/const-option.rs | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 3526bdc9aa045..b1287c0cecf89 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1396,6 +1396,20 @@ impl Option> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + pub const fn transpose(self) -> Result, E> { + match self { + Some(Ok(x)) => Ok(Some(x)), + Some(Err(e)) => Err(e), + None => Ok(None), + } + } + + /// No docs for bootstrap. + #[inline] + #[stable(feature = "transpose_result", since = "1.33.0")] + #[cfg(bootstrap)] pub fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -1834,6 +1848,16 @@ impl Option> { /// ``` #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_option_match")] + #[cfg(not(bootstrap))] + pub const fn flatten(self) -> Option { + self.and_then(convert::identity) + } + + /// No docs for bootstrap. + #[inline] + #[stable(feature = "option_flattening", since = "1.40.0")] + #[cfg(bootstrap)] pub fn flatten(self) -> Option { self.and_then(convert::identity) } diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs index 831e48c39bfc6..77d2252050fba 100644 --- a/src/test/ui/consts/const-option.rs +++ b/src/test/ui/consts/const-option.rs @@ -117,4 +117,12 @@ assert_same_const! { const XOR_B: Option = SOME.xor(None); const XOR_C: Option = NONE.xor(Some(1)); const XOR_D: Option = NONE.xor(None); + + const TRANSPOSE_A: Result, bool> = Some(Ok(2)).transpose(); + const TRANSPOSE_B: Result, bool> = Some(Err(false)).transpose(); + const TRANSPOSE_C: Result, bool> = None.transpose(); + + const FLATTEN_A: Option = Some(Some(2)).flatten(); + const FLATTEN_B: Option = Some(None).flatten(); + const FLATTEN_C: Option = None.flatten(); } From 48c9f1e811ea7f4469d38a2f91a2f9cfb69877ba Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 17:06:52 -0500 Subject: [PATCH 11/14] Make rem_euclid const The implementation of rem_euclid for signed integers was const, but I'd forgotten to mark rem_euclid on unsigned integers as const as well, hence the failing test. --- src/libcore/num/mod.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 70118e8c0a9f5..993474ebc3763 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2232,7 +2232,7 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 /// No docs for bootstrap. #[stable(feature = "euclidean_division", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] #[cfg(bootstrap)] @@ -4414,11 +4414,24 @@ assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn rem_euclid(self, rhs: Self) -> Self { + #[rustc_const_unstable(feature = "const_int_euclidean")] + #[cfg(not(bootstrap))] + pub const fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } + /// No docs for bootstrap. + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + #[cfg(bootstrap)] + pub fn rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + doc_comment! { concat!("Returns `true` if and only if `self == 2^k` for some `k`. From 5744fe15aeb96271cb194654c3051a0df12d16dc Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 3 Dec 2019 22:51:08 -0500 Subject: [PATCH 12/14] Revert: Make functional Option fns const const fns with generic trait bounds aren't allowed yet; from @oli-obk: > please undo all constifications for functions that take generic things > with trait bounds (other than Sized), these require > rust-lang/rfcs#2632 first --- src/libcore/option.rs | 106 ----------------------------- src/test/ui/consts/const-option.rs | 70 ------------------- 2 files changed, 176 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index b1287c0cecf89..a0bbef8672467 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -479,19 +479,6 @@ impl Option { /// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn unwrap_or_else T>(self, f: F) -> T { - match self { - Some(x) => x, - None => f(), - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_else T>(self, f: F) -> T { @@ -521,19 +508,6 @@ impl Option { /// /// assert_eq!(maybe_some_len, Some(13)); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn map U>(self, f: F) -> Option { - match self { - Some(x) => Some(f(x)), - None => None, - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map U>(self, f: F) -> Option { @@ -555,19 +529,6 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.map_or(42, |v| v.len()), 42); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn map_or U>(self, default: U, f: F) -> U { - match self { - Some(t) => f(t), - None => default, - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map_or U>(self, default: U, f: F) -> U { @@ -591,19 +552,6 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { - match self { - Some(t) => f(t), - None => default(), - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { @@ -676,19 +624,6 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.ok_or_else(|| 0), Err(0)); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn ok_or_else E>(self, err: F) -> Result { - match self { - Some(v) => Ok(v), - None => Err(err()), - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn ok_or_else E>(self, err: F) -> Result { @@ -807,19 +742,6 @@ impl Option { /// assert_eq!(Some(2).and_then(nope).and_then(sq), None); /// assert_eq!(None.and_then(sq).and_then(sq), None); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn and_then Option>(self, f: F) -> Option { - match self { - Some(x) => f(x), - None => None, - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn and_then Option>(self, f: F) -> Option { @@ -855,21 +777,6 @@ impl Option { /// [`None`]: #variant.None /// [`Some(t)`]: #variant.Some /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "option_filter", since = "1.27.0")] - pub const fn filter bool>(self, predicate: P) -> Self { - if let Some(x) = self { - if predicate(&x) { - return Some(x); - } - } - None - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "option_filter", since = "1.27.0")] pub fn filter bool>(self, predicate: P) -> Self { @@ -943,19 +850,6 @@ impl Option { /// assert_eq!(None.or_else(vikings), Some("vikings")); /// assert_eq!(None.or_else(nobody), None); /// ``` - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn or_else Option>(self, f: F) -> Option { - match self { - Some(_) => self, - None => f(), - } - } - - /// No docs for bootstrap. - #[cfg(bootstrap)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or_else Option>(self, f: F) -> Option { diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs index 77d2252050fba..89bfe050c6825 100644 --- a/src/test/ui/consts/const-option.rs +++ b/src/test/ui/consts/const-option.rs @@ -12,46 +12,6 @@ macro_rules! assert_same_const { } } -// These functions let us use the functional interfaces of Option (like unwrap_or_else, map_or, -// map, etc.) without using closures, which aren't implemented in const contexts yet; see -// https://github.com/rust-lang/rust/issues/63997 - -const fn is_zero(i: i32) -> bool { - i == 0i32 -} - -const fn get_zero() -> i32 { - 0 -} - -const fn get_false() -> bool { - false -} - -const fn get_some() -> Option { - Some(2) -} - -const fn get_none() -> Option { - None -} - -const fn is_pos(i: &i32) -> bool { - i.is_positive() -} - -const fn is_neg(i: &i32) -> bool { - i.is_negative() -} - -const fn i32_to_some(i: i32) -> Option { - Some(i * 2) -} - -const fn i32_to_none(_i: i32) -> Option { - None -} - assert_same_const! { const SOME: Option = Some(3); const NONE: Option = None; @@ -70,49 +30,19 @@ assert_same_const! { const UNWRAP_OR_A: i32 = SOME.unwrap_or(0); const UNWRAP_OR_B: i32 = NONE.unwrap_or(0); - const UNWRAP_OR_ELSE_A: i32 = SOME.unwrap_or_else(get_zero); - const UNWRAP_OR_ELSE_B: i32 = NONE.unwrap_or_else(get_zero); - - const MAP_A: Option = SOME.map(is_zero); - const MAP_B: Option = NONE.map(is_zero); - - const MAP_OR_A: bool = SOME.map_or(false, is_zero); - const MAP_OR_B: bool = NONE.map_or(false, is_zero); - - const MAP_OR_ELSE_A: bool = SOME.map_or_else(get_false, is_zero); - const MAP_OR_ELSE_B: bool = NONE.map_or_else(get_false, is_zero); - const OK_OR_A: Result = SOME.ok_or(false); const OK_OR_B: Result = NONE.ok_or(false); - const OK_OR_ELSE_A: Result = SOME.ok_or_else(get_false); - const OK_OR_ELSE_B: Result = NONE.ok_or_else(get_false); - const AND_A: Option = SOME.and(Some(true)); const AND_B: Option = SOME.and(None); const AND_C: Option = NONE.and(Some(true)); const AND_D: Option = NONE.and(None); - const AND_THEN_A: Option = SOME.and_then(i32_to_some); - const AND_THEN_B: Option = SOME.and_then(i32_to_none); - const AND_THEN_C: Option = NONE.and_then(i32_to_some); - const AND_THEN_D: Option = NONE.and_then(i32_to_none); - - const FILTER_A: Option = SOME.filter(is_pos); - const FILTER_B: Option = SOME.filter(is_neg); - const FILTER_C: Option = NONE.filter(is_pos); - const FILTER_D: Option = NONE.filter(is_neg); - const OR_A: Option = SOME.or(Some(1)); const OR_B: Option = SOME.or(None); const OR_C: Option = NONE.or(Some(1)); const OR_D: Option = NONE.or(None); - const OR_ELSE_A: Option = SOME.or_else(get_some); - const OR_ELSE_B: Option = SOME.or_else(get_none); - const OR_ELSE_C: Option = NONE.or_else(get_some); - const OR_ELSE_D: Option = NONE.or_else(get_none); - const XOR_A: Option = SOME.xor(Some(1)); const XOR_B: Option = SOME.xor(None); const XOR_C: Option = NONE.xor(Some(1)); From 8c1f72604ae9680c6f8ad09116429195f4d96520 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Wed, 4 Dec 2019 00:01:40 -0500 Subject: [PATCH 13/14] Revert: Make Option.flatten const Option.flatten relies on Option.and_then, which has a generic trait bound and can't be const yet. From @oli-obk: > please undo all constifications for functions that take generic things > with trait bounds (other than Sized), these require > rust-lang/rfcs#2632 first --- src/libcore/option.rs | 10 ---------- src/test/ui/consts/const-option.rs | 4 ---- 2 files changed, 14 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a0bbef8672467..922eb333de25e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1742,16 +1742,6 @@ impl Option> { /// ``` #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] - pub const fn flatten(self) -> Option { - self.and_then(convert::identity) - } - - /// No docs for bootstrap. - #[inline] - #[stable(feature = "option_flattening", since = "1.40.0")] - #[cfg(bootstrap)] pub fn flatten(self) -> Option { self.and_then(convert::identity) } diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs index 89bfe050c6825..91b01bb4fd0c7 100644 --- a/src/test/ui/consts/const-option.rs +++ b/src/test/ui/consts/const-option.rs @@ -51,8 +51,4 @@ assert_same_const! { const TRANSPOSE_A: Result, bool> = Some(Ok(2)).transpose(); const TRANSPOSE_B: Result, bool> = Some(Err(false)).transpose(); const TRANSPOSE_C: Result, bool> = None.transpose(); - - const FLATTEN_A: Option = Some(Some(2)).flatten(); - const FLATTEN_B: Option = Some(None).flatten(); - const FLATTEN_C: Option = None.flatten(); } From 72489216e94c7672d80568b3e2415efd223729c5 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Thu, 19 Dec 2019 17:30:25 -0500 Subject: [PATCH 14/14] Delete bootstrap fns, factor out assert_same_const - New boostrap compiler! Delete the non-const bootstrap copies of the fns. - Factor the assert_same_const! macro to src/test/ui/consts/auxiliary/const_assert_lib.rs and apply the fix Oli suggested, > In order to prevent promotion from making this test useless because > it ends up promoting the assert argument --- src/libcore/lib.rs | 2 +- src/libcore/num/mod.rs | 563 ------------------ src/libcore/option.rs | 123 ---- .../ui/consts/auxiliary/const_assert_lib.rs | 17 + src/test/ui/consts/const-int-euclidean.rs | 13 +- src/test/ui/consts/const-int-nonzero.rs | 13 +- src/test/ui/consts/const-option.rs | 13 +- 7 files changed, 27 insertions(+), 717 deletions(-) create mode 100644 src/test/ui/consts/auxiliary/const_assert_lib.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 21e97e4d55e28..5c47ce9c2781e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -128,7 +128,7 @@ #![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(associated_type_bounds)] -#![cfg_attr(not(bootstrap), feature(const_if_match))] +#![feature(const_if_match)] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 993474ebc3763..285fee71c0a68 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -71,7 +71,6 @@ assert_eq!(size_of::>(), size_of::<", s #[$stability] #[inline] #[rustc_const_unstable(feature = "const_int_nonzero")] - #[cfg(not(bootstrap))] pub const fn new(n: $Int) -> Option { if n != 0 { // SAFETY: we just checked that there's no `0` @@ -81,19 +80,6 @@ assert_eq!(size_of::>(), size_of::<", s } } - /// No docs for bootstrap. - #[$stability] - #[inline] - #[cfg(bootstrap)] - pub fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } - } - /// Returns the value as a primitive type. #[$stability] #[inline] @@ -660,24 +646,12 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -697,24 +671,12 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -734,24 +696,12 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -772,7 +722,6 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_div(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None @@ -783,21 +732,6 @@ $EndFeature, " } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_div(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::min_value() && rhs == -1) { - None - } else { - // SAFETY: div by zero and by INT_MIN have been checked above - Some(unsafe { intrinsics::unchecked_div(self, rhs) }) - } - } - doc_comment! { concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0` or the division results in overflow. @@ -817,7 +751,6 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None @@ -827,20 +760,6 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_div_euclid(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::min_value() && rhs == -1) { - None - } else { - Some(self.div_euclid(rhs)) - } - } - doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -891,7 +810,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None @@ -901,20 +819,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::min_value() && rhs == -1) { - None - } else { - Some(self.rem_euclid(rhs)) - } - } - doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`. @@ -932,22 +836,12 @@ $EndFeature, " #[stable(feature = "wrapping", since = "1.7.0")] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[inline] - #[cfg(bootstrap)] - pub fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -966,7 +860,6 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} @@ -974,17 +867,6 @@ $EndFeature, " } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -1003,24 +885,12 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked absolute value. Computes `self.abs()`, returning `None` if `self == MIN`. @@ -1039,7 +909,6 @@ $EndFeature, " #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_abs(self) -> Option { if self.is_negative() { self.checked_neg() @@ -1049,18 +918,6 @@ $EndFeature, " } } - /// No docs for bootstrap. - #[stable(feature = "no_panic_abs", since = "1.13.0")] - #[inline] - #[cfg(bootstrap)] - pub fn checked_abs(self) -> Option { - if self.is_negative() { - self.checked_neg() - } else { - Some(self) - } - } - doc_comment! { concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow occurred. @@ -1238,7 +1095,6 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_saturating")] - #[cfg(not(bootstrap))] pub const fn saturating_mul(self, rhs: Self) -> Self { match self.checked_mul(rhs) { Some(r) => r, @@ -1253,25 +1109,6 @@ $EndFeature, " } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn saturating_mul(self, rhs: Self) -> Self { - match self.checked_mul(rhs) { - Some(r) => r, - None => { - if (self < 0) == (rhs < 0) { - Self::max_value() - } else { - Self::min_value() - } - }, - } - } - doc_comment! { concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the numeric bounds instead of overflowing. @@ -1398,22 +1235,11 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_wrapping")] - #[cfg(not(bootstrap))] pub const fn wrapping_div(self, rhs: Self) -> Self { self.overflowing_div(rhs).0 } } - /// No docs for bootstrap. - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_div(self, rhs: Self) -> Self { - self.overflowing_div(rhs).0 - } - doc_comment! { concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, wrapping around at the boundary of the type. @@ -1439,22 +1265,11 @@ assert_eq!((-128i8).wrapping_div_euclid(-1), -128); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self.overflowing_div_euclid(rhs).0 } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { - self.overflowing_div_euclid(rhs).0 - } - doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the boundary of the type. @@ -1481,22 +1296,11 @@ $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_wrapping")] - #[cfg(not(bootstrap))] pub const fn wrapping_rem(self, rhs: Self) -> Self { self.overflowing_rem(rhs).0 } } - /// No docs for bootstrap. - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_rem(self, rhs: Self) -> Self { - self.overflowing_rem(rhs).0 - } - doc_comment! { concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around at the boundary of the type. @@ -1521,22 +1325,11 @@ assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self.overflowing_rem_euclid(rhs).0 } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self.overflowing_rem_euclid(rhs).0 - } - doc_comment! { concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary of the type. @@ -1814,7 +1607,6 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_overflowing")] - #[cfg(not(bootstrap))] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) @@ -1824,20 +1616,6 @@ $EndFeature, " } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { - if self == Self::min_value() && rhs == -1 { - (self, true) - } else { - (self / rhs, false) - } - } - doc_comment! { concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. @@ -1864,7 +1642,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) @@ -1874,20 +1651,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::min_value() && rhs == -1 { - (self, true) - } else { - (self.div_euclid(rhs), false) - } - } - doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -1914,7 +1677,6 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_overflowing")] - #[cfg(not(bootstrap))] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) @@ -1924,20 +1686,6 @@ $EndFeature, " } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - if self == Self::min_value() && rhs == -1 { - (0, true) - } else { - (self % rhs, false) - } - } - doc_comment! { concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. @@ -1963,7 +1711,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) @@ -1973,21 +1720,6 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::min_value() && rhs == -1 { - (0, true) - } else { - (self.rem_euclid(rhs), false) - } - } - - doc_comment! { concat!("Negates self, overflowing if this is equal to the minimum value. @@ -2219,7 +1951,6 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 #[inline] #[rustc_inherit_overflow_checks] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { @@ -2229,22 +1960,6 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - #[cfg(bootstrap)] - pub fn div_euclid(self, rhs: Self) -> Self { - let q = self / rhs; - if self % rhs < 0 { - return if rhs > 0 { q - 1 } else { q + 1 } - } - q - } - - doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. @@ -2275,7 +1990,6 @@ assert_eq!((-a).rem_euclid(-b), 1); #[inline] #[rustc_inherit_overflow_checks] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { @@ -2290,26 +2004,6 @@ assert_eq!((-a).rem_euclid(-b), 1); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - #[cfg(bootstrap)] - pub fn rem_euclid(self, rhs: Self) -> Self { - let r = self % rhs; - if r < 0 { - if rhs < 0 { - r - rhs - } else { - r + rhs - } - } else { - r - } - } - doc_comment! { concat!("Computes the absolute value of `self`. @@ -3072,24 +2766,12 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -3107,24 +2789,12 @@ assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -3142,24 +2812,12 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFe without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`. @@ -3177,7 +2835,6 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_div(self, rhs: Self) -> Option { match rhs { 0 => None, @@ -3188,21 +2845,6 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " } } - /// No docs for bootstrap. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub 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 - // failure modes for division - rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }), - } - } - doc_comment! { concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0`. @@ -3220,7 +2862,6 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None @@ -3230,21 +2871,6 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_div_euclid(self, rhs: Self) -> Option { - if rhs == 0 { - None - } else { - Some(self.div_euclid(rhs)) - } - } - - doc_comment! { concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0`. @@ -3262,7 +2888,6 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_rem(self, rhs: Self) -> Option { if rhs == 0 { None @@ -3274,22 +2899,6 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_rem(self, rhs: Self) -> Option { - if rhs == 0 { - None - } else { - // SAFETY: div by zero has been checked above and unsigned types have no other - // failure modes for division - Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) - } - } - doc_comment! { concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` if `rhs == 0`. @@ -3307,7 +2916,6 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None @@ -3317,20 +2925,6 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { - if rhs == 0 { - None - } else { - Some(self.rem_euclid(rhs)) - } - } - doc_comment! { concat!("Checked negation. Computes `-self`, returning `None` unless `self == 0`. @@ -3348,22 +2942,12 @@ assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " #[stable(feature = "wrapping", since = "1.7.0")] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[inline] - #[cfg(bootstrap)] - pub fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -3381,24 +2965,12 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is larger than or equal to the number of bits in `self`. @@ -3416,24 +2988,12 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_checked")] - #[cfg(not(bootstrap))] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); if b {None} else {Some(a)} } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if b {None} else {Some(a)} - } - doc_comment! { concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow occurred. @@ -3538,22 +3098,11 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_saturating")] - #[cfg(not(bootstrap))] pub const fn saturating_mul(self, rhs: Self) -> Self { self.checked_mul(rhs).unwrap_or(Self::max_value()) } } - /// No docs for bootstrap. - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn saturating_mul(self, rhs: Self) -> Self { - self.checked_mul(rhs).unwrap_or(Self::max_value()) - } - doc_comment! { concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the numeric bounds instead of overflowing. @@ -3669,22 +3218,11 @@ Basic usage: without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_wrapping")] - #[cfg(not(bootstrap))] pub const fn wrapping_div(self, rhs: Self) -> Self { self / rhs } } - /// No docs for bootstrap. - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_div(self, rhs: Self) -> Self { - self / rhs - } - doc_comment! { concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped division on unsigned types is just normal division. @@ -3707,22 +3245,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { - self / rhs - } - doc_comment! { concat!("Wrapping (modular) remainder. Computes `self % rhs`. Wrapped remainder calculation on unsigned types is @@ -3743,22 +3270,11 @@ Basic usage: without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_wrapping")] - #[cfg(not(bootstrap))] pub const fn wrapping_rem(self, rhs: Self) -> Self { self % rhs } } - /// No docs for bootstrap. - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_rem(self, rhs: Self) -> Self { - self % rhs - } - doc_comment! { concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped modulo calculation on unsigned types is @@ -3782,22 +3298,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); without modifying the original"] #[inline] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[cfg(bootstrap)] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self % rhs - } - /// Wrapping (modular) negation. Computes `-self`, /// wrapping around at the boundary of the type. /// @@ -4041,22 +3546,11 @@ Basic usage #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_overflowing")] - #[cfg(not(bootstrap))] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } - doc_comment! { concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. @@ -4084,21 +3578,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } - doc_comment! { concat!("Calculates the remainder when `self` is divided by `rhs`. @@ -4123,22 +3607,11 @@ Basic usage #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_overflowing")] - #[cfg(not(bootstrap))] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } - doc_comment! { concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. @@ -4166,22 +3639,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg(bootstrap)] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } - doc_comment! { concat!("Negates self in an overflowing fashion. @@ -4373,24 +3835,11 @@ assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer #[inline] #[rustc_inherit_overflow_checks] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn div_euclid(self, rhs: Self) -> Self { self / rhs } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - #[cfg(bootstrap)] - pub fn div_euclid(self, rhs: Self) -> Self { - self / rhs - } - - doc_comment! { concat!("Calculates the least remainder of `self (mod rhs)`. @@ -4415,23 +3864,11 @@ assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer #[inline] #[rustc_inherit_overflow_checks] #[rustc_const_unstable(feature = "const_int_euclidean")] - #[cfg(not(bootstrap))] pub const fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } - /// No docs for bootstrap. - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - #[cfg(bootstrap)] - pub fn rem_euclid(self, rhs: Self) -> Self { - self % rhs - } - doc_comment! { concat!("Returns `true` if and only if `self == 2^k` for some `k`. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 922eb333de25e..ad404307cc40a 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -184,7 +184,6 @@ impl Option { /// /// [`Some`]: #variant.Some #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -195,18 +194,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_some(&self) -> bool { - match *self { - Some(_) => true, - None => false, - } - } - /// Returns `true` if the option is a [`None`] value. /// /// # Examples @@ -221,7 +208,6 @@ impl Option { /// /// [`None`]: #variant.None #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[must_use = "if you intended to assert that this doesn't have a value, consider \ `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"] #[inline] @@ -230,16 +216,6 @@ impl Option { !self.is_some() } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[must_use = "if you intended to assert that this doesn't have a value, consider \ - `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_none(&self) -> bool { - !self.is_some() - } - /// Returns `true` if the option is a [`Some`] value containing the given value. /// /// # Examples @@ -294,7 +270,6 @@ impl Option { /// println!("still can print text: {:?}", text); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn as_ref(&self) -> Option<&T> { @@ -304,17 +279,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_ref(&self) -> Option<&T> { - match *self { - Some(ref x) => Some(x), - None => None, - } - } - /// Converts from `&mut Option` to `Option<&mut T>`. /// /// # Examples @@ -380,7 +344,6 @@ impl Option { /// x.expect("the world is ending"); // panics with `the world is ending` /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn expect(self, msg: &str) -> T { @@ -390,17 +353,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn expect(self, msg: &str) -> T { - match self { - Some(val) => val, - None => expect_failed(msg), - } - } - /// Moves the value `v` out of the `Option` if it is [`Some(v)`]. /// /// In general, because this function may panic, its use is discouraged. @@ -449,7 +401,6 @@ impl Option { /// assert_eq!(None.unwrap_or("bike"), "bike"); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn unwrap_or(self, default: T) -> T { @@ -459,17 +410,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { - match self { - Some(x) => x, - None => default, - } - } - /// Returns the contained value or computes it from a closure. /// /// # Examples @@ -585,7 +525,6 @@ impl Option { /// assert_eq!(x.ok_or(0), Err(0)); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn ok_or(self, err: E) -> Result { @@ -595,17 +534,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn ok_or(self, err: E) -> Result { - match self { - Some(v) => Ok(v), - None => Err(err), - } - } - /// Transforms the `Option` into a [`Result`], mapping [`Some(v)`] to /// [`Ok(v)`] and [`None`] to [`Err(err())`]. /// @@ -703,7 +631,6 @@ impl Option { /// assert_eq!(x.and(y), None); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn and(self, optb: Option) -> Option { @@ -713,17 +640,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn and(self, optb: Option) -> Option { - match self { - Some(_) => optb, - None => None, - } - } - /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the /// wrapped value and returns the result. /// @@ -816,7 +732,6 @@ impl Option { /// assert_eq!(x.or(y), None); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn or(self, optb: Option) -> Option { @@ -826,17 +741,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn or(self, optb: Option) -> Option { - match self { - Some(_) => self, - None => optb, - } - } - /// Returns the option if it contains a value, otherwise calls `f` and /// returns the result. /// @@ -884,7 +788,6 @@ impl Option { /// assert_eq!(x.xor(y), None); /// ``` #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] #[inline] #[stable(feature = "option_xor", since = "1.37.0")] pub const fn xor(self, optb: Option) -> Option { @@ -895,18 +798,6 @@ impl Option { } } - /// No docs for bootstrap. - #[cfg(bootstrap)] - #[inline] - #[stable(feature = "option_xor", since = "1.37.0")] - pub fn xor(self, optb: Option) -> Option { - match (self, optb) { - (Some(a), None) => Some(a), - (None, Some(b)) => Some(b), - _ => None, - } - } - ///////////////////////////////////////////////////////////////////////// // Entry-like operations to insert if None and return a reference ///////////////////////////////////////////////////////////////////////// @@ -1291,7 +1182,6 @@ impl Option> { #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] #[rustc_const_unstable(feature = "const_option_match")] - #[cfg(not(bootstrap))] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -1300,19 +1190,6 @@ impl Option> { } } - /// No docs for bootstrap. - #[inline] - #[stable(feature = "transpose_result", since = "1.33.0")] - #[cfg(bootstrap)] - pub fn transpose(self) -> Result, E> { - match self { - Some(Ok(x)) => Ok(Some(x)), - Some(Err(e)) => Err(e), - None => Ok(None), - } - } -} - // This is a separate function to reduce the code size of .expect() itself. #[inline(never)] #[cold] diff --git a/src/test/ui/consts/auxiliary/const_assert_lib.rs b/src/test/ui/consts/auxiliary/const_assert_lib.rs new file mode 100644 index 0000000000000..f6ca2d65f080e --- /dev/null +++ b/src/test/ui/consts/auxiliary/const_assert_lib.rs @@ -0,0 +1,17 @@ +/// Given a block of const bindings, asserts that their values (calculated at runtime) are the +/// same as their values (calculated at compile-time). +macro_rules! assert_same_const { + ($(const $ident:ident: $ty:ty = $exp:expr;)+) => { + $(const $ident: $ty = $exp;)+ + + pub fn main() { + $({ + // Assign the expr to a variable at runtime; otherwise, the argument is + // calculated at compile-time, making the test useless. + let tmp = $exp; + assert_eq!(tmp, $ident); + })+ + } + } +} + diff --git a/src/test/ui/consts/const-int-euclidean.rs b/src/test/ui/consts/const-int-euclidean.rs index 447d0ef39d344..6b4ce6df01fe1 100644 --- a/src/test/ui/consts/const-int-euclidean.rs +++ b/src/test/ui/consts/const-int-euclidean.rs @@ -1,17 +1,10 @@ // run-pass +// aux-build:const_assert_lib.rs +use const_assert_lib::assert_same_const; + #![feature(const_int_euclidean)] #![feature(saturating_neg)] -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 CHECKED_DIV_I32_A: Option = 5i32.checked_div_euclid(7777); const CHECKED_DIV_I8_A: Option = (-127 as i8).checked_div_euclid(-99); diff --git a/src/test/ui/consts/const-int-nonzero.rs b/src/test/ui/consts/const-int-nonzero.rs index 31391875fe68d..049ab36090471 100644 --- a/src/test/ui/consts/const-int-nonzero.rs +++ b/src/test/ui/consts/const-int-nonzero.rs @@ -1,4 +1,7 @@ // run-pass +// aux-build:const_assert_lib.rs +use const_assert_lib::assert_same_const; + #![feature(const_int_nonzero)] use std::num::{ @@ -8,16 +11,6 @@ use std::num::{ NonZeroUsize, }; -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 NON_ZERO_NEW_1: Option = NonZeroI8::new(1); const NON_ZERO_NEW_2: Option = NonZeroI8::new(0); diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs index 91b01bb4fd0c7..eadca29984d0b 100644 --- a/src/test/ui/consts/const-option.rs +++ b/src/test/ui/consts/const-option.rs @@ -1,17 +1,10 @@ // run-pass +// aux-build:const_assert_lib.rs +use const_assert_lib::assert_same_const; + #![feature(const_option_match)] #![feature(option_result_contains)] -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 SOME: Option = Some(3); const NONE: Option = None;