diff options
| author | John Millikin <john@john-millikin.com> | 2022-09-27 11:40:39 +0900 |
|---|---|---|
| committer | John Millikin <john@john-millikin.com> | 2023-04-20 14:27:29 +0900 |
| commit | 4e2797dd76363370eac74cc9480e7d8c0ff17b4b (patch) | |
| tree | 509fe2f357fc7270af5aa2a9cd9f65a6c2410c72 | |
| parent | dc730521efad6acf9b31fcc99c8a26789fa9a654 (diff) | |
| download | rust-4e2797dd76363370eac74cc9480e7d8c0ff17b4b.tar.gz rust-4e2797dd76363370eac74cc9480e7d8c0ff17b4b.zip | |
Implement `Neg` for signed non-zero integers.
Negating a non-zero integer currently requires unpacking to a
primitive and re-wrapping. Since negation of non-zero signed
integers always produces a non-zero result, it is safe to
implement `Neg` for `NonZeroI{N}`.
The new `impl` is marked as stable because trait implementations
for two stable types can't be marked unstable.
| -rw-r--r-- | library/core/src/num/nonzero.rs | 19 | ||||
| -rw-r--r-- | library/core/tests/nonzero.rs | 18 | ||||
| -rw-r--r-- | tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs | 12 |
3 files changed, 46 insertions, 3 deletions
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 54e03067d1c..fc9b07d29e2 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1,7 +1,7 @@ //! Definitions of integer that is known not to equal zero. use crate::fmt; -use crate::ops::{BitOr, BitOrAssign, Div, Rem}; +use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; use crate::str::FromStr; use super::from_str_radix; @@ -664,8 +664,7 @@ macro_rules! nonzero_signed_operations { /// assert_eq!(pos, pos.wrapping_abs()); /// assert_eq!(pos, neg.wrapping_abs()); /// assert_eq!(min, min.wrapping_abs()); - /// # // FIXME: add once Neg is implemented? - /// # // assert_eq!(max, (-max).wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); /// # Some(()) /// # } /// ``` @@ -868,6 +867,20 @@ macro_rules! nonzero_signed_operations { unsafe { $Ty::new_unchecked(result) } } } + + #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] + impl Neg for $Ty { + type Output = $Ty; + + #[inline] + fn neg(self) -> $Ty { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().neg()) } + } + } + + forward_ref_unop! { impl Neg, neg for $Ty, + #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] } )+ } } diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 96356b728e9..007f8442533 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -336,3 +336,21 @@ fn test_nonzero_uint_rem() { let x: u32 = 42u32 % nz; assert_eq!(x, 2u32); } + +#[test] +fn test_signed_nonzero_neg() { + assert_eq!((-NonZeroI8::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI8::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI16::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI16::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI32::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI32::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI64::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI64::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI128::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI128::new(-1).unwrap()).get(), 1); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs b/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs new file mode 100644 index 00000000000..565b7e86fc4 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to negate with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +#![allow(arithmetic_overflow)] + +use std::num::NonZeroI8; + +fn main() { + let _x = -NonZeroI8::new(i8::MIN).unwrap(); +} |
