diff options
| author | Yuki Okushi <jtitor@2k36.org> | 2023-04-20 17:03:23 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-20 17:03:23 +0900 |
| commit | df3aca2af634274b0997068fa81fe5d9cc04d860 (patch) | |
| tree | 71f7f26da4a3b85486a622895baffd5298f0a4b2 | |
| parent | 7fde08365c4c3cfc9a9f8a6a02693b789adbe6da (diff) | |
| parent | 4e2797dd76363370eac74cc9480e7d8c0ff17b4b (diff) | |
| download | rust-df3aca2af634274b0997068fa81fe5d9cc04d860.tar.gz rust-df3aca2af634274b0997068fa81fe5d9cc04d860.zip | |
Rollup merge of #102341 - jmillikin:nonzero-impl-neg, r=dtolnay
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 impls for two stable types can't be marked unstable.
See discussion on https://github.com/rust-lang/libs-team/issues/105 for additional context.
| -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(); +} |
