From cdea63058aa944ac56e9b7fee294a8f81c700fac Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 1 Sep 2018 15:05:55 +0200 Subject: [PATCH] rebase --- src/libcore/lib.rs | 7 + src/libcore/num/mod.rs | 552 ++++++++++++++++-- src/librustc_mir/interpret/intrinsics.rs | 37 +- src/librustc_mir/lib.rs | 1 + src/librustc_mir/transform/qualify_consts.rs | 11 +- src/test/run-pass/const-int-conversion.rs | 30 + src/test/run-pass/const-int-overflowing.rs | 43 ++ src/test/run-pass/const-int-rotate.rs | 19 + src/test/run-pass/const-int-sign.rs | 23 + src/test/run-pass/const-int-wrapping.rs | 43 ++ src/test/ui/consts/const-int-conversion.rs | 28 + .../ui/consts/const-int-conversion.stderr | 80 +++ src/test/ui/consts/const-int-overflowing.rs | 15 + .../ui/consts/const-int-overflowing.stderr | 35 ++ src/test/ui/consts/const-int-rotate.rs | 14 + src/test/ui/consts/const-int-rotate.stderr | 24 + src/test/ui/consts/const-int-sign.rs | 14 + src/test/ui/consts/const-int-sign.stderr | 24 + src/test/ui/consts/const-int-wrapping.rs | 17 + src/test/ui/consts/const-int-wrapping.stderr | 57 ++ 20 files changed, 1016 insertions(+), 58 deletions(-) create mode 100644 src/test/run-pass/const-int-conversion.rs create mode 100644 src/test/run-pass/const-int-overflowing.rs create mode 100644 src/test/run-pass/const-int-rotate.rs create mode 100644 src/test/run-pass/const-int-sign.rs create mode 100644 src/test/run-pass/const-int-wrapping.rs create mode 100644 src/test/ui/consts/const-int-conversion.rs create mode 100644 src/test/ui/consts/const-int-conversion.stderr create mode 100644 src/test/ui/consts/const-int-overflowing.rs create mode 100644 src/test/ui/consts/const-int-overflowing.stderr create mode 100644 src/test/ui/consts/const-int-rotate.rs create mode 100644 src/test/ui/consts/const-int-rotate.stderr create mode 100644 src/test/ui/consts/const-int-sign.rs create mode 100644 src/test/ui/consts/const-int-sign.stderr create mode 100644 src/test/ui/consts/const-int-wrapping.rs create mode 100644 src/test/ui/consts/const-int-wrapping.stderr diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2aa3226af89..b0c93316301 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 fc405881b28..3e6ec0b294c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -338,6 +338,14 @@ pub const fn trailing_zeros(self) -> u32 { } } + /// 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 @@ pub const fn trailing_zeros(self) -> u32 { 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 @@ pub fn rotate_left(self, n: u32) -> Self { 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 @@ pub const fn swap_bytes(self) -> Self { } } + /// 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 @@ pub const fn swap_bytes(self) -> Self { 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 @@ pub fn saturating_pow(self, exp: u32) -> Self { } } + /// 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 @@ pub fn saturating_pow(self, exp: u32) -> Self { $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 @@ pub fn wrapping_add(self, rhs: Self) -> Self { $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 @@ pub fn wrapping_sub(self, rhs: Self) -> Self { $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 @@ pub fn wrapping_neg(self) -> Self { } } + /// 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 @@ pub fn wrapping_neg(self) -> Self { $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 @@ pub fn wrapping_shl(self, rhs: u32) -> Self { $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 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self { } } + /// 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 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self { 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 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { 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 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { 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 @@ pub fn overflowing_neg(self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_neg(self) -> (Self, bool) { 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 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { 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 @@ pub fn signum(self) -> Self { } } + /// 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 @@ pub fn signum(self) -> Self { $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 @@ pub fn is_positive(self) -> bool { self > 0 } $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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub fn is_negative(self) -> bool { self < 0 } /// 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 @@ pub const fn trailing_zeros(self) -> u32 { } } + /// 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 @@ pub const fn trailing_zeros(self) -> u32 { 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 @@ pub fn rotate_left(self, n: u32) -> Self { 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 @@ pub const fn swap_bytes(self) -> Self { } } + /// 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 @@ pub const fn swap_bytes(self) -> Self { 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 @@ pub fn saturating_pow(self, exp: u32) -> Self { } } + /// 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 @@ pub fn saturating_pow(self, exp: u32) -> Self { $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 @@ pub fn wrapping_add(self, rhs: Self) -> Self { $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 @@ pub fn wrapping_sub(self, rhs: Self) -> Self { /// 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 @@ pub fn wrapping_neg(self) -> Self { 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 @@ pub fn wrapping_neg(self) -> Self { 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 @@ pub fn wrapping_shl(self, rhs: u32) -> Self { 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 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self { } } + /// 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 @@ pub fn wrapping_pow(self, mut exp: u32) -> Self { 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 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { 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 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { /// 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 @@ pub fn overflowing_neg(self) -> (Self, bool) { } } + /// 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 @@ pub fn overflowing_neg(self) -> (Self, bool) { ", $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,10 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { ", $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) { + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } } @@ -3571,6 +3951,14 @@ pub fn wrapping_next_power_of_two(self) -> Self { } } + /// 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 +3971,21 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 +3998,21 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 +4032,21 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 +4059,21 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 +4086,21 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 +4120,10 @@ pub fn wrapping_next_power_of_two(self) -> Self { /// 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 e8fd43afa1c..8cdb0e37f55 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 @@ pub fn emulate_intrinsic( 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 @@ pub fn emulate_intrinsic( }; 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 f91ff3642cd..d744414f523 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -38,6 +38,7 @@ #![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 a3bca6de6c2..fe23fe9a547 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -826,11 +826,20 @@ fn visit_terminator_kind(&mut self, | "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 00000000000..84d55b636ed --- /dev/null +++ b/src/test/run-pass/const-int-conversion.rs @@ -0,0 +1,30 @@ +// 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 main() { + assert_eq!(REVERSE, 0x1e6a2c48); + assert_eq!(FROM_BE_BYTES, 0x12_34_56_78); + assert_eq!(FROM_LE_BYTES, 0x78_56_34_12); + assert_eq!(FROM_NE_BYTES, i32::min_value()); + assert_eq!(TO_BE_BYTES, [0x12, 0x34, 0x56, 0x78]); + assert_eq!(TO_LE_BYTES, [0x78, 0x56, 0x34, 0x12]); + assert_eq!(TO_NE_BYTES, [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 00000000000..a89643a26a5 --- /dev/null +++ b/src/test/run-pass/const-int-overflowing.rs @@ -0,0 +1,43 @@ +// 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 main() { + assert_eq!(ADD_A, (7, false)); + assert_eq!(ADD_B, (0, true)); + + assert_eq!(SUB_A, (3, false)); + assert_eq!(SUB_B, (u32::max_value(), true)); + + assert_eq!(MUL_A, (10, false)); + assert_eq!(MUL_B, (1410065408, true)); + + assert_eq!(SHL_A, (0x10, false)); + assert_eq!(SHL_B, (0x10, true)); + + assert_eq!(SHR_A, (0x1, false)); + assert_eq!(SHR_B, (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 00000000000..8c0620c3278 --- /dev/null +++ b/src/test/run-pass/const-int-rotate.rs @@ -0,0 +1,19 @@ +// 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 main() { + assert_eq!(LEFT, 0xb301); + assert_eq!(RIGHT, 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 00000000000..e095cfb000c --- /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 00000000000..3469fe7a1dd --- /dev/null +++ b/src/test/run-pass/const-int-wrapping.rs @@ -0,0 +1,43 @@ +// 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 main() { + assert_eq!(ADD_A, 255); + assert_eq!(ADD_B, 199); + + assert_eq!(SUB_A, 0); + assert_eq!(SUB_B, 101); + + assert_eq!(MUL_A, 120); + assert_eq!(MUL_B, 44); + + assert_eq!(SHL_A, 128); + assert_eq!(SHL_B, 1); + + assert_eq!(SHR_A, 1); + assert_eq!(SHR_B, 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 00000000000..0abe6b4a1e4 --- /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 00000000000..fc2472a7b58 --- /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 00000000000..7bff6b9adb0 --- /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 00000000000..e06fb6af1a6 --- /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 00000000000..e6f05338c84 --- /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 00000000000..fa2f6255e01 --- /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 00000000000..1082c385cd4 --- /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 00000000000..1d456287bd8 --- /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 00000000000..bd11d5df232 --- /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 00000000000..94974e09939 --- /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`.