diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2aa3226af8960..b0c93316301c4 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -120,6 +120,13 @@ #![feature(const_slice_len)] #![feature(const_str_as_bytes)] #![feature(const_str_len)] +#![feature(const_let)] +#![feature(const_int_rotate)] +#![feature(const_int_wrapping)] +#![feature(const_int_sign)] +#![feature(const_int_conversion)] +#![feature(const_transmute)] +#![feature(reverse_bits)] #![feature(non_exhaustive)] #[prelude_import] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index fc405881b28da..19d3ad2024713 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -338,6 +338,14 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn rotate_left(self, n: u32) -> Self { + (self as $UnsignedT).rotate_left(n) as Self + } + doc_comment! { concat!("Shifts the bits to the left by a specified amount, `n`, wrapping the truncated bits to the end of the resulting integer. @@ -355,12 +363,22 @@ let m = ", $rot_result, "; assert_eq!(n.rotate_left(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] - pub fn rotate_left(self, n: u32) -> Self { + #[cfg(not(stage0))] + pub const fn rotate_left(self, n: u32) -> Self { (self as $UnsignedT).rotate_left(n) as Self } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn rotate_right(self, n: u32) -> Self { + (self as $UnsignedT).rotate_right(n) as Self + } + doc_comment! { concat!("Shifts the bits to the right by a specified amount, `n`, wrapping the truncated bits to the beginning of the resulting @@ -379,11 +397,14 @@ let m = ", $rot_op, "; assert_eq!(n.rotate_right(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] - pub fn rotate_right(self, n: u32) -> Self { + #[cfg(not(stage0))] + pub const fn rotate_right(self, n: u32) -> Self { (self as $UnsignedT).rotate_right(n) as Self } } + doc_comment! { concat!("Reverses the byte order of the integer. @@ -406,6 +427,14 @@ assert_eq!(m, ", $swapped, "); } } + /// no docs here + #[unstable(feature = "reverse_bits", issue = "48763")] + #[inline] + #[cfg(stage0)] + pub fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + doc_comment! { concat!("Reverses the bit pattern of the integer. @@ -422,8 +451,10 @@ let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), #[unstable(feature = "reverse_bits", issue = "48763")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn reverse_bits(self) -> Self { + #[cfg(not(stage0))] + pub const fn reverse_bits(self) -> Self { (self as $UnsignedT).reverse_bits() as Self } } @@ -973,6 +1004,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_add(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -988,14 +1029,26 @@ assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!( $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_add(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_add(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_add(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_sub(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of the type. @@ -1011,14 +1064,26 @@ stringify!($SelfT), "::max_value());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_sub(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_sub(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_sub(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_mul(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at the boundary of the type. @@ -1033,8 +1098,10 @@ assert_eq!(11i8.wrapping_mul(12), -124);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_mul(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_mul(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_mul(self, rhs) } @@ -1177,6 +1244,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shl(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. @@ -1196,14 +1273,26 @@ assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shl(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shl(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shr(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. @@ -1223,8 +1312,10 @@ assert_eq!((-128i16).wrapping_shr(64), -128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shr(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shr(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -1302,6 +1393,18 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::add_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -1319,9 +1422,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1330,6 +1435,18 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($Sel } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::sub_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` - `rhs` @@ -1347,9 +1464,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1358,6 +1477,18 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($Sel } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::mul_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates the multiplication of `self` and `rhs`. @@ -1373,9 +1504,11 @@ Basic usage: assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1545,6 +1678,14 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self left by `rhs` bits. @@ -1561,13 +1702,23 @@ Basic usage: assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self right by `rhs` bits. @@ -1584,9 +1735,11 @@ Basic usage: assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } } @@ -1850,6 +2003,12 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn is_positive(self) -> bool { self > 0 } + doc_comment! { concat!("Returns `true` if `self` is positive and `false` if the number is zero or negative. @@ -1864,10 +2023,18 @@ assert!(!(-10", stringify!($SelfT), ").is_positive());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_sign")] #[inline] - pub fn is_positive(self) -> bool { self > 0 } + #[cfg(not(stage0))] + pub const fn is_positive(self) -> bool { self > 0 } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn is_negative(self) -> bool { self < 0 } + doc_comment! { concat!("Returns `true` if `self` is negative and `false` if the number is zero or positive. @@ -1882,8 +2049,18 @@ assert!(!10", stringify!($SelfT), ".is_negative());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_sign")] #[inline] - pub fn is_negative(self) -> bool { self < 0 } + #[cfg(not(stage0))] + pub const fn is_negative(self) -> bool { self < 0 } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() } /// Return the memory representation of this integer as a byte array in @@ -1898,11 +2075,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + /// Return the memory representation of this integer as a byte array in /// little-endian byte order. /// @@ -1915,11 +2102,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + unsafe { mem::transmute(self) } + } + /// Return the memory representation of this integer as a byte array in /// native byte order. /// @@ -1939,11 +2136,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x80, 0, 0, 0]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + /// Create an integer value from its representation as a byte array in /// big endian. /// @@ -1956,11 +2163,21 @@ $EndFeature, " /// assert_eq!(int, 0x12_34_56_78); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + /// Create an integer value from its representation as a byte array in /// little endian. /// @@ -1973,11 +2190,21 @@ $EndFeature, " /// assert_eq!(int, 0x78_56_34_12); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + unsafe { mem::transmute(bytes) } + } + /// Create an integer value from its memory representation as a byte /// array in native endianness. /// @@ -1997,8 +2224,10 @@ $EndFeature, " /// assert_eq!(int, i32::min_value()); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } } } @@ -2217,6 +2446,16 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn rotate_left(self, n: u32) -> Self { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> (($BITS - n) % $BITS)) + } + doc_comment! { concat!("Shifts the bits to the left by a specified amount, `n`, wrapping the truncated bits to the end of the resulting integer. @@ -2234,14 +2473,24 @@ let m = ", $rot_result, "; assert_eq!(n.rotate_left(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] - pub fn rotate_left(self, n: u32) -> Self { - // Protect against undefined behaviour for over-long bit shifts - let n = n % $BITS; - (self << n) | (self >> (($BITS - n) % $BITS)) + #[cfg(not(stage0))] + pub const fn rotate_left(self, n: u32) -> Self { + (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS)) } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn rotate_right(self, n: u32) -> Self { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << (($BITS - n) % $BITS)) + } + doc_comment! { concat!("Shifts the bits to the right by a specified amount, `n`, wrapping the truncated bits to the beginning of the resulting @@ -2260,11 +2509,11 @@ let m = ", $rot_op, "; assert_eq!(n.rotate_right(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] #[inline] - pub fn rotate_right(self, n: u32) -> Self { - // Protect against undefined behaviour for over-long bit shifts - let n = n % $BITS; - (self >> n) | (self << (($BITS - n) % $BITS)) + #[cfg(not(stage0))] + pub const fn rotate_right(self, n: u32) -> Self { + (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS)) } } @@ -2290,6 +2539,14 @@ assert_eq!(m, ", $swapped, "); } } + /// no docs here + #[unstable(feature = "reverse_bits", issue = "48763")] + #[inline] + #[cfg(stage0)] + pub fn reverse_bits(self) -> Self { + unsafe { intrinsics::bitreverse(self as $ActualT) as Self } + } + doc_comment! { concat!("Reverses the bit pattern of the integer. @@ -2306,8 +2563,10 @@ let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), #[unstable(feature = "reverse_bits", issue = "48763")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn reverse_bits(self) -> Self { + #[cfg(not(stage0))] + pub const fn reverse_bits(self) -> Self { unsafe { intrinsics::bitreverse(self as $ActualT) as Self } } } @@ -2795,6 +3054,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_add(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -2809,14 +3078,26 @@ assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_add(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_add(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_add(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_sub(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of the type. @@ -2831,14 +3112,26 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_sub(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_sub(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_sub(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_mul(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + /// Wrapping (modular) multiplication. Computes `self * /// rhs`, wrapping around at the boundary of the type. /// @@ -2854,8 +3147,10 @@ $EndFeature, " /// assert_eq!(25u8.wrapping_mul(12), 44); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_mul(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_mul(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_mul(self, rhs) } @@ -2976,6 +3271,16 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); self.overflowing_neg().0 } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shl(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any high-order bits of `rhs` that @@ -2997,14 +3302,26 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shl(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shl(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shr(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any high-order bits of `rhs` that @@ -3026,8 +3343,10 @@ Basic usage: assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shr(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shr(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -3072,6 +3391,18 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::add_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -3089,9 +3420,11 @@ Basic usage assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3100,6 +3433,18 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndF } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::sub_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` - `rhs` @@ -3118,9 +3463,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3129,6 +3476,18 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::mul_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean @@ -3146,9 +3505,11 @@ $EndFeature, " /// assert_eq!(5u32.overflowing_mul(2), (10, false)); /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true)); /// ``` - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3286,6 +3647,14 @@ assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!( } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self left by `rhs` bits. @@ -3303,13 +3672,23 @@ Basic usage ", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false)); assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self right by `rhs` bits. @@ -3327,9 +3706,11 @@ Basic usage ", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false)); assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } } @@ -3571,6 +3952,14 @@ $EndFeature, " } } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + /// Return the memory representation of this integer as a byte array in /// big-endian (network) byte order. /// @@ -3583,11 +3972,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + /// Return the memory representation of this integer as a byte array in /// little-endian byte order. /// @@ -3600,11 +3999,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + unsafe { mem::transmute(self) } + } + /// Return the memory representation of this integer as a byte array in /// native byte order. /// @@ -3624,11 +4033,21 @@ $EndFeature, " /// assert_eq!(bytes, [0x80, 0, 0, 0]); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(not(stage0))] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + /// Create an integer value from its representation as a byte array in /// big endian. /// @@ -3641,11 +4060,21 @@ $EndFeature, " /// assert_eq!(int, 0x12_34_56_78); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + /// Create an integer value from its representation as a byte array in /// little endian. /// @@ -3658,11 +4087,21 @@ $EndFeature, " /// assert_eq!(int, 0x78_56_34_12); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) } + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + unsafe { mem::transmute(bytes) } + } + /// Create an integer value from its memory representation as a byte /// array in native endianness. /// @@ -3682,8 +4121,10 @@ $EndFeature, " /// assert_eq!(int, i32::min_value()); /// ``` #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] - pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(not(stage0))] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } } } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index e8fd43afa1c7a..8cdb0e37f5507 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -15,6 +15,7 @@ use syntax::symbol::Symbol; use rustc::ty; use rustc::ty::layout::{LayoutOf, Primitive}; +use rustc::mir::BinOp; use rustc::mir::interpret::{ EvalResult, EvalErrorKind, Scalar, }; @@ -39,6 +40,7 @@ fn numeric_intrinsic<'tcx>( "ctlz" => bits.leading_zeros() as u128 - extra, "cttz" => (bits << extra).trailing_zeros() as u128 - extra, "bswap" => (bits << extra).swap_bytes(), + "bitreverse" => (bits << extra).reverse_bits(), _ => bug!("not a numeric intrinsic: {}", name), }; Ok(Scalar::from_uint(bits_out, size)) @@ -76,7 +78,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let id_val = Scalar::from_uint(type_id, dest.layout.size); self.write_scalar(id_val, dest)?; } - "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => { + | "ctpop" + | "cttz" + | "cttz_nonzero" + | "ctlz" + | "ctlz_nonzero" + | "bswap" + | "bitreverse" => { let ty = substs.type_at(0); let layout_of = self.layout_of(ty)?; let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?; @@ -94,6 +102,33 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { }; self.write_scalar(out_val, dest)?; } + | "overflowing_add" + | "overflowing_sub" + | "overflowing_mul" + | "unchecked_shl" + | "unchecked_shr" + | "add_with_overflow" + | "sub_with_overflow" + | "mul_with_overflow" => { + let lhs = self.read_value(args[0])?; + let rhs = self.read_value(args[1])?; + let (bin_op, ignore_overflow) = match intrinsic_name { + "overflowing_add" => (BinOp::Add, true), + "overflowing_sub" => (BinOp::Sub, true), + "overflowing_mul" => (BinOp::Mul, true), + "unchecked_shl" => (BinOp::Shl, true), + "unchecked_shr" => (BinOp::Shr, true), + "add_with_overflow" => (BinOp::Add, false), + "sub_with_overflow" => (BinOp::Sub, false), + "mul_with_overflow" => (BinOp::Mul, false), + _ => bug!("Already checked for int ops") + }; + if ignore_overflow { + self.binop_ignore_overflow(bin_op, lhs, rhs, dest)?; + } else { + self.binop_with_overflow(bin_op, lhs, rhs, dest)?; + } + } "transmute" => { // Go through an allocation, to make sure the completely different layouts // do not pose a problem. (When the user transmutes through a union, diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f91ff3642cd10..d744414f52305 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -38,6 +38,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(slice_concat_ext)] #![feature(if_while_or_patterns)] #![feature(try_from)] +#![feature(reverse_bits)] #![recursion_limit="256"] diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a3bca6de6c2d7..fe23fe9a547ce 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -826,11 +826,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { | "min_align_of" | "type_id" | "bswap" + | "bitreverse" | "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" - | "ctlz_nonzero" => is_const_fn = Some(def_id), + | "ctlz_nonzero" + | "overflowing_add" + | "overflowing_sub" + | "overflowing_mul" + | "unchecked_shl" + | "unchecked_shr" + | "add_with_overflow" + | "sub_with_overflow" + | "mul_with_overflow" => is_const_fn = Some(def_id), "transmute" => { if self.mode != Mode::Fn { is_const_fn = Some(def_id); diff --git a/src/test/run-pass/const-int-conversion.rs b/src/test/run-pass/const-int-conversion.rs new file mode 100644 index 0000000000000..790c62288d38b --- /dev/null +++ b/src/test/run-pass/const-int-conversion.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_int_conversion, const_int_ops, reverse_bits, int_to_from_bytes)] + +const REVERSE: u32 = 0x12345678_u32.reverse_bits(); +const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]); +const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]); +const FROM_NE_BYTES: i32 = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])); +const TO_BE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_be_bytes(); +const TO_LE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_le_bytes(); +const TO_NE_BYTES: [u8; 4] = i32::min_value().to_be().to_ne_bytes(); + +fn ident(ident: T) -> T { + ident +} + +fn main() { + assert_eq!(REVERSE, ident(0x1e6a2c48)); + assert_eq!(FROM_BE_BYTES, ident(0x12_34_56_78)); + assert_eq!(FROM_LE_BYTES, ident(0x78_56_34_12)); + assert_eq!(FROM_NE_BYTES, ident(i32::min_value())); + assert_eq!(TO_BE_BYTES, ident([0x12, 0x34, 0x56, 0x78])); + assert_eq!(TO_LE_BYTES, ident([0x78, 0x56, 0x34, 0x12])); + assert_eq!(TO_NE_BYTES, ident([0x80, 0, 0, 0])); +} + diff --git a/src/test/run-pass/const-int-overflowing.rs b/src/test/run-pass/const-int-overflowing.rs new file mode 100644 index 0000000000000..0f8f230f456bd --- /dev/null +++ b/src/test/run-pass/const-int-overflowing.rs @@ -0,0 +1,47 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_int_overflowing)] + +const ADD_A: (u32, bool) = 5u32.overflowing_add(2); +const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1); + +const SUB_A: (u32, bool) = 5u32.overflowing_sub(2); +const SUB_B: (u32, bool) = 0u32.overflowing_sub(1); + +const MUL_A: (u32, bool) = 5u32.overflowing_mul(2); +const MUL_B: (u32, bool) = 1_000_000_000u32.overflowing_mul(10); + +const SHL_A: (u32, bool) = 0x1u32.overflowing_shl(4); +const SHL_B: (u32, bool) = 0x1u32.overflowing_shl(132); + +const SHR_A: (u32, bool) = 0x10u32.overflowing_shr(4); +const SHR_B: (u32, bool) = 0x10u32.overflowing_shr(132); + +fn ident(ident: T) -> T { + ident +} + +fn main() { + assert_eq!(ADD_A, ident((7, false))); + assert_eq!(ADD_B, ident((0, true))); + + assert_eq!(SUB_A, ident((3, false))); + assert_eq!(SUB_B, ident((u32::max_value(), true))); + + assert_eq!(MUL_A, ident((10, false))); + assert_eq!(MUL_B, ident((1410065408, true))); + + assert_eq!(SHL_A, ident((0x10, false))); + assert_eq!(SHL_B, ident((0x10, true))); + + assert_eq!(SHR_A, ident((0x1, false))); + assert_eq!(SHR_B, ident((0x1, true))); +} diff --git a/src/test/run-pass/const-int-rotate.rs b/src/test/run-pass/const-int-rotate.rs new file mode 100644 index 0000000000000..ee8e0b0b9dd7f --- /dev/null +++ b/src/test/run-pass/const-int-rotate.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_int_rotate)] + +const LEFT: u32 = 0x10000b3u32.rotate_left(8); +const RIGHT: u32 = 0xb301u32.rotate_right(8); + +fn ident(ident: T) -> T { + ident +} + +fn main() { + assert_eq!(LEFT, ident(0xb301)); + assert_eq!(RIGHT, ident(0x10000b3)); +} diff --git a/src/test/run-pass/const-int-sign.rs b/src/test/run-pass/const-int-sign.rs new file mode 100644 index 0000000000000..e095cfb000c5f --- /dev/null +++ b/src/test/run-pass/const-int-sign.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_int_sign)] + +const NEGATIVE_A: bool = (-10i32).is_negative(); +const NEGATIVE_B: bool = 10i32.is_negative(); +const POSITIVE_A: bool= (-10i32).is_positive(); +const POSITIVE_B: bool= 10i32.is_positive(); + +fn main() { + assert!(NEGATIVE_A); + assert!(!NEGATIVE_B); + assert!(!POSITIVE_A); + assert!(POSITIVE_B); +} diff --git a/src/test/run-pass/const-int-wrapping.rs b/src/test/run-pass/const-int-wrapping.rs new file mode 100644 index 0000000000000..ab7c98f9824ec --- /dev/null +++ b/src/test/run-pass/const-int-wrapping.rs @@ -0,0 +1,47 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_int_wrapping)] + +const ADD_A: u32 = 200u32.wrapping_add(55); +const ADD_B: u32 = 200u32.wrapping_add(u32::max_value()); + +const SUB_A: u32 = 100u32.wrapping_sub(100); +const SUB_B: u32 = 100u32.wrapping_sub(u32::max_value()); + +const MUL_A: u8 = 10u8.wrapping_mul(12); +const MUL_B: u8 = 25u8.wrapping_mul(12); + +const SHL_A: u32 = 1u32.wrapping_shl(7); +const SHL_B: u32 = 1u32.wrapping_shl(128); + +const SHR_A: u32 = 128u32.wrapping_shr(7); +const SHR_B: u32 = 128u32.wrapping_shr(128); + +fn ident(ident: T) -> T { + ident +} + +fn main() { + assert_eq!(ADD_A, ident(255)); + assert_eq!(ADD_B, ident(199)); + + assert_eq!(SUB_A, ident(0)); + assert_eq!(SUB_B, ident(101)); + + assert_eq!(MUL_A, ident(120)); + assert_eq!(MUL_B, ident(44)); + + assert_eq!(SHL_A, ident(128)); + assert_eq!(SHL_B, ident(1)); + + assert_eq!(SHR_A, ident(1)); + assert_eq!(SHR_B, ident(128)); +} diff --git a/src/test/ui/consts/const-int-conversion.rs b/src/test/ui/consts/const-int-conversion.rs new file mode 100644 index 0000000000000..0abe6b4a1e49f --- /dev/null +++ b/src/test/ui/consts/const-int-conversion.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(reverse_bits, int_to_from_bytes)] + +fn main() { + let x: &'static i32 = &(5_i32.reverse_bits()); + //~^ ERROR does not live long enough + let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); + //~^ ERROR does not live long enough + let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); + //~^ ERROR does not live long enough + let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); + //~^ ERROR does not live long enough + let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); + //~^ ERROR does not live long enough + let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); + //~^ ERROR does not live long enough + let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes()); + //~^ ERROR does not live long enough +} diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr new file mode 100644 index 0000000000000..fc2472a7b5879 --- /dev/null +++ b/src/test/ui/consts/const-int-conversion.stderr @@ -0,0 +1,80 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:14:28 + | +LL | let x: &'static i32 = &(5_i32.reverse_bits()); + | ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:16:28 + | +LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:18:28 + | +LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:20:28 + | +LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:22:29 + | +LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:24:29 + | +LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-conversion.rs:26:29 + | +LL | let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | //~^ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-int-overflowing.rs b/src/test/ui/consts/const-int-overflowing.rs new file mode 100644 index 0000000000000..7bff6b9adb0c7 --- /dev/null +++ b/src/test/ui/consts/const-int-overflowing.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); //~ ERROR does not live long enough + let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); //~ ERROR does not live long enough + let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough +} diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr new file mode 100644 index 0000000000000..e06fb6af1a643 --- /dev/null +++ b/src/test/ui/consts/const-int-overflowing.stderr @@ -0,0 +1,35 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-overflowing.rs:12:36 + | +LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-overflowing.rs:13:36 + | +LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-overflowing.rs:14:36 + | +LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-int-rotate.rs b/src/test/ui/consts/const-int-rotate.rs new file mode 100644 index 0000000000000..e6f05338c849e --- /dev/null +++ b/src/test/ui/consts/const-int-rotate.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x: &'static i32 = &(5_i32.rotate_left(3)); //~ ERROR does not live long enough + let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough +} diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr new file mode 100644 index 0000000000000..fa2f6255e01f2 --- /dev/null +++ b/src/test/ui/consts/const-int-rotate.stderr @@ -0,0 +1,24 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-rotate.rs:12:28 + | +LL | let x: &'static i32 = &(5_i32.rotate_left(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-rotate.rs:13:28 + | +LL | let y: &'static i32 = &(5_i32.rotate_right(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-int-sign.rs b/src/test/ui/consts/const-int-sign.rs new file mode 100644 index 0000000000000..1082c385cd402 --- /dev/null +++ b/src/test/ui/consts/const-int-sign.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x: &'static bool = &(5_i32.is_negative()); //~ ERROR does not live long enough + let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough +} diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr new file mode 100644 index 0000000000000..1d456287bd883 --- /dev/null +++ b/src/test/ui/consts/const-int-sign.stderr @@ -0,0 +1,24 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-sign.rs:12:29 + | +LL | let x: &'static bool = &(5_i32.is_negative()); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-sign.rs:13:29 + | +LL | let y: &'static bool = &(5_i32.is_positive()); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-int-wrapping.rs b/src/test/ui/consts/const-int-wrapping.rs new file mode 100644 index 0000000000000..bd11d5df232bd --- /dev/null +++ b/src/test/ui/consts/const-int-wrapping.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x: &'static i32 = &(5_i32.wrapping_add(3)); //~ ERROR does not live long enough + let y: &'static i32 = &(5_i32.wrapping_sub(3)); //~ ERROR does not live long enough + let z: &'static i32 = &(5_i32.wrapping_mul(3)); //~ ERROR does not live long enough + let a: &'static i32 = &(5_i32.wrapping_shl(3)); //~ ERROR does not live long enough + let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough +} diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr new file mode 100644 index 0000000000000..94974e09939bb --- /dev/null +++ b/src/test/ui/consts/const-int-wrapping.stderr @@ -0,0 +1,57 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-wrapping.rs:12:28 + | +LL | let x: &'static i32 = &(5_i32.wrapping_add(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-wrapping.rs:13:28 + | +LL | let y: &'static i32 = &(5_i32.wrapping_sub(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-wrapping.rs:14:28 + | +LL | let z: &'static i32 = &(5_i32.wrapping_mul(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-wrapping.rs:15:28 + | +LL | let a: &'static i32 = &(5_i32.wrapping_shl(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-int-wrapping.rs:16:28 + | +LL | let b: &'static i32 = &(5_i32.wrapping_shr(3)); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0597`.