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.
This commit is contained in:
parent
dc730521ef
commit
4e2797dd76
3 changed files with 46 additions and 3 deletions
|
@ -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")] }
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
12
tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs
Normal file
12
tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs
Normal file
|
@ -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();
|
||||
}
|
Loading…
Add table
Reference in a new issue