Skip to content

Commit cf74423

Browse files
committed
Make NonZero constructors generic.
1 parent 0f55e1b commit cf74423

File tree

1 file changed

+81
-74
lines changed

1 file changed

+81
-74
lines changed

Diff for: library/core/src/num/nonzero.rs

+81-74
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Definitions of integer that is known not to equal zero.
22
3-
use crate::cmp::Ordering;
3+
use crate::cmp::{Ordering, PartialEq};
44
use crate::fmt;
55
use crate::hash::{Hash, Hasher};
66
#[cfg(bootstrap)]
@@ -32,7 +32,10 @@ mod private {
3232
issue = "none"
3333
)]
3434
#[const_trait]
35-
pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {}
35+
pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {
36+
#[doc(hidden)]
37+
const ZERO: Self;
38+
}
3639

3740
macro_rules! impl_zeroable_primitive {
3841
($primitive:ty) => {
@@ -48,7 +51,9 @@ macro_rules! impl_zeroable_primitive {
4851
reason = "implementation detail which may disappear or be replaced at any time",
4952
issue = "none"
5053
)]
51-
impl const ZeroablePrimitive for $primitive {}
54+
impl const ZeroablePrimitive for $primitive {
55+
const ZERO: Self = 0;
56+
}
5257
};
5358
}
5459

@@ -83,6 +88,79 @@ impl_zeroable_primitive!(isize);
8388
#[rustc_diagnostic_item = "NonZero"]
8489
pub struct NonZero<T: ZeroablePrimitive>(T);
8590

91+
impl<T> NonZero<T>
92+
where
93+
T: ZeroablePrimitive + PartialEq,
94+
{
95+
/// Creates a non-zero if the given value is not zero.
96+
#[stable(feature = "nonzero", since = "1.28.0")]
97+
#[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
98+
#[must_use]
99+
#[inline]
100+
pub const fn new(n: T) -> Option<Self> {
101+
if n == T::ZERO {
102+
return None;
103+
}
104+
105+
// SAFETY: We just checked that there's no `0`.
106+
Some(unsafe { Self(n) })
107+
}
108+
109+
/// Creates a non-zero without checking whether the value is non-zero.
110+
/// This results in undefined behaviour if the value is zero.
111+
///
112+
/// # Safety
113+
///
114+
/// The value must not be zero.
115+
#[stable(feature = "nonzero", since = "1.28.0")]
116+
#[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
117+
#[must_use]
118+
#[inline]
119+
pub const unsafe fn new_unchecked(n: T) -> Self {
120+
crate::panic::debug_assert_nounwind!(
121+
n != T::ZERO,
122+
"NonZero::new_unchecked requires a non-zero argument",
123+
);
124+
125+
// SAFETY: This is guaranteed to be safe by the caller.
126+
unsafe { Self(n) }
127+
}
128+
129+
/// Converts a reference to a non-zero mutable reference
130+
/// if the referenced value is not zero.
131+
#[unstable(feature = "nonzero_from_mut", issue = "106290")]
132+
#[must_use]
133+
#[inline]
134+
pub fn from_mut(n: &mut T) -> Option<&mut Self> {
135+
// SAFETY: Self is `repr(transparent)`, and the value is non-zero.
136+
// As long as the returned reference is alive,
137+
// the user cannot `*n = 0` directly.
138+
(*n != T::ZERO).then(|| unsafe { &mut *(n as *mut T as *mut Self) })
139+
}
140+
141+
/// Converts a mutable reference to a non-zero mutable reference
142+
/// without checking whether the referenced value is non-zero.
143+
/// This results in undefined behavior if the referenced value is zero.
144+
///
145+
/// # Safety
146+
///
147+
/// The referenced value must not be zero.
148+
#[unstable(feature = "nonzero_from_mut", issue = "106290")]
149+
#[must_use]
150+
#[inline]
151+
pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self {
152+
// SAFETY: Self is repr(transparent), and the value is assumed to be non-zero.
153+
unsafe {
154+
let n_alias = &mut *n;
155+
core::intrinsics::assert_unsafe_precondition!(
156+
"NonZero::from_mut_unchecked requires the argument to dereference as non-zero",
157+
[T: ZeroablePrimitive + PartialEq](n_alias: &mut T) => *n_alias != T::ZERO
158+
);
159+
&mut *(n as *mut T as *mut Self)
160+
}
161+
}
162+
}
163+
86164
macro_rules! impl_nonzero_fmt {
87165
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
88166
$(
@@ -100,7 +178,6 @@ macro_rules! impl_nonzero_fmt {
100178
macro_rules! nonzero_integer {
101179
(
102180
#[$stability:meta]
103-
#[$const_new_unchecked_stability:meta]
104181
Self = $Ty:ident,
105182
Primitive = $signedness:ident $Int:ident,
106183
$(UnsignedNonZero = $UnsignedNonZero:ident,)?
@@ -143,74 +220,6 @@ macro_rules! nonzero_integer {
143220
pub type $Ty = NonZero<$Int>;
144221

145222
impl $Ty {
146-
/// Creates a non-zero without checking whether the value is non-zero.
147-
/// This results in undefined behaviour if the value is zero.
148-
///
149-
/// # Safety
150-
///
151-
/// The value must not be zero.
152-
#[$stability]
153-
#[$const_new_unchecked_stability]
154-
#[must_use]
155-
#[inline]
156-
pub const unsafe fn new_unchecked(n: $Int) -> Self {
157-
crate::panic::debug_assert_nounwind!(
158-
n != 0,
159-
concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument")
160-
);
161-
// SAFETY: this is guaranteed to be safe by the caller.
162-
unsafe {
163-
Self(n)
164-
}
165-
}
166-
167-
/// Creates a non-zero if the given value is not zero.
168-
#[$stability]
169-
#[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
170-
#[must_use]
171-
#[inline]
172-
pub const fn new(n: $Int) -> Option<Self> {
173-
if n != 0 {
174-
// SAFETY: we just checked that there's no `0`
175-
Some(unsafe { Self(n) })
176-
} else {
177-
None
178-
}
179-
}
180-
181-
/// Converts a primitive mutable reference to a non-zero mutable reference
182-
/// without checking whether the referenced value is non-zero.
183-
/// This results in undefined behavior if `*n` is zero.
184-
///
185-
/// # Safety
186-
/// The referenced value must not be currently zero.
187-
#[unstable(feature = "nonzero_from_mut", issue = "106290")]
188-
#[must_use]
189-
#[inline]
190-
pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self {
191-
// SAFETY: Self is repr(transparent), and the value is assumed to be non-zero.
192-
unsafe {
193-
let n_alias = &mut *n;
194-
core::intrinsics::assert_unsafe_precondition!(
195-
concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"),
196-
(n_alias: &mut $Int) => *n_alias != 0
197-
);
198-
&mut *(n as *mut $Int as *mut Self)
199-
}
200-
}
201-
202-
/// Converts a primitive mutable reference to a non-zero mutable reference
203-
/// if the referenced integer is not zero.
204-
#[unstable(feature = "nonzero_from_mut", issue = "106290")]
205-
#[must_use]
206-
#[inline]
207-
pub fn from_mut(n: &mut $Int) -> Option<&mut Self> {
208-
// SAFETY: Self is repr(transparent), and the value is non-zero.
209-
// As long as the returned reference is alive,
210-
// the user cannot `*n = 0` directly.
211-
(*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) })
212-
}
213-
214223
/// Returns the value as a primitive type.
215224
#[$stability]
216225
#[inline]
@@ -724,7 +733,6 @@ macro_rules! nonzero_integer {
724733
(Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
725734
nonzero_integer! {
726735
#[stable(feature = "nonzero", since = "1.28.0")]
727-
#[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
728736
Self = $Ty,
729737
Primitive = unsigned $Int,
730738
UnsignedPrimitive = $Int,
@@ -735,7 +743,6 @@ macro_rules! nonzero_integer {
735743
(Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => {
736744
nonzero_integer! {
737745
#[stable(feature = "signed_nonzero", since = "1.34.0")]
738-
#[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")]
739746
Self = $Ty,
740747
Primitive = signed $Int,
741748
$($rest)*

0 commit comments

Comments
 (0)