Skip to content

Commit 60a874f

Browse files
committed
Manually implement derived NonZero traits.
1 parent 227abac commit 60a874f

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

library/core/src/num/nonzero.rs

+107-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//! Definitions of integer that is known not to equal zero.
22
3+
use crate::cmp::Ordering;
34
use crate::fmt;
5+
use crate::hash::{Hash, Hasher};
6+
use crate::marker::StructuralPartialEq;
47
use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
58
use crate::str::FromStr;
69

@@ -31,13 +34,6 @@ pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {
3134
type NonZero;
3235
}
3336

34-
#[unstable(
35-
feature = "nonzero_internals",
36-
reason = "implementation detail which may disappear or be replaced at any time",
37-
issue = "none"
38-
)]
39-
pub(crate) type NonZero<T> = <T as ZeroablePrimitive>::NonZero;
40-
4137
macro_rules! impl_zeroable_primitive {
4238
($NonZero:ident ( $primitive:ty )) => {
4339
#[unstable(
@@ -71,6 +67,107 @@ impl_zeroable_primitive!(NonZeroI64(i64));
7167
impl_zeroable_primitive!(NonZeroI128(i128));
7268
impl_zeroable_primitive!(NonZeroIsize(isize));
7369

70+
#[unstable(
71+
feature = "nonzero_internals",
72+
reason = "implementation detail which may disappear or be replaced at any time",
73+
issue = "none"
74+
)]
75+
pub(crate) type NonZero<T> = <T as ZeroablePrimitive>::NonZero;
76+
77+
macro_rules! impl_nonzero_traits {
78+
(#[$stability:meta] $Ty:ty) => {
79+
#[$stability]
80+
impl Clone for $Ty {
81+
#[inline]
82+
fn clone(&self) -> Self {
83+
// SAFETY: The contained value is non-zero.
84+
unsafe { Self(self.get()) }
85+
}
86+
}
87+
88+
#[$stability]
89+
impl PartialEq for $Ty {
90+
#[inline]
91+
fn eq(&self, other: &Self) -> bool {
92+
self.get() == other.get()
93+
}
94+
95+
#[inline]
96+
fn ne(&self, other: &Self) -> bool {
97+
self.get() != other.get()
98+
}
99+
}
100+
101+
#[unstable(feature = "structural_match", issue = "31434")]
102+
impl StructuralPartialEq for $Ty {}
103+
104+
#[$stability]
105+
impl PartialOrd for $Ty {
106+
#[inline]
107+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
108+
self.get().partial_cmp(&other.get())
109+
}
110+
111+
#[inline]
112+
fn lt(&self, other: &Self) -> bool {
113+
self.get() < other.get()
114+
}
115+
116+
#[inline]
117+
fn le(&self, other: &Self) -> bool {
118+
self.get() <= other.get()
119+
}
120+
121+
#[inline]
122+
fn gt(&self, other: &Self) -> bool {
123+
self.get() > other.get()
124+
}
125+
126+
#[inline]
127+
fn ge(&self, other: &Self) -> bool {
128+
self.get() >= other.get()
129+
}
130+
}
131+
132+
#[$stability]
133+
impl Ord for $Ty {
134+
#[inline]
135+
fn cmp(&self, other: &Self) -> Ordering {
136+
self.get().cmp(&other.get())
137+
}
138+
139+
#[inline]
140+
fn max(self, other: Self) -> Self {
141+
// SAFETY: The maximum of two non-zero values is still non-zero.
142+
unsafe { Self(self.get().max(other.get())) }
143+
}
144+
145+
#[inline]
146+
fn min(self, other: Self) -> Self {
147+
// SAFETY: The minimum of two non-zero values is still non-zero.
148+
unsafe { Self(self.get().min(other.get())) }
149+
}
150+
151+
#[inline]
152+
fn clamp(self, min: Self, max: Self) -> Self {
153+
// SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
154+
unsafe { Self(self.get().clamp(min.get(), max.get())) }
155+
}
156+
}
157+
158+
#[$stability]
159+
impl Hash for $Ty {
160+
#[inline]
161+
fn hash<H>(&self, state: &mut H)
162+
where
163+
H: Hasher,
164+
{
165+
self.get().hash(state)
166+
}
167+
}
168+
};
169+
}
170+
74171
macro_rules! impl_nonzero_fmt {
75172
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
76173
$(
@@ -128,13 +225,15 @@ macro_rules! nonzero_integer {
128225
///
129226
/// [null pointer optimization]: crate::option#representation
130227
#[$stability]
131-
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
228+
#[derive(Copy, Eq)]
132229
#[repr(transparent)]
133230
#[rustc_layout_scalar_valid_range_start(1)]
134231
#[rustc_nonnull_optimization_guaranteed]
135232
#[rustc_diagnostic_item = stringify!($Ty)]
136233
pub struct $Ty($Int);
137234

235+
impl_nonzero_traits!(#[$stability] $Ty);
236+
138237
impl $Ty {
139238
/// Creates a non-zero without checking whether the value is non-zero.
140239
/// This results in undefined behaviour if the value is zero.

tests/ui/unsafe/ranged_ints3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cell::Cell;
55
#[rustc_layout_scalar_valid_range_start(1)]
66
#[repr(transparent)]
77
pub(crate) struct NonZero<T>(pub(crate) T);
8+
89
fn main() {
910
let mut x = unsafe { NonZero(Cell::new(1)) };
1011
let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability

tests/ui/unsafe/ranged_ints3_match.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cell::Cell;
55
#[rustc_layout_scalar_valid_range_start(1)]
66
#[repr(transparent)]
77
pub(crate) struct NonZero<T>(pub(crate) T);
8+
89
fn main() {
910
let mut x = unsafe { NonZero(Cell::new(1)) };
1011
match x {

0 commit comments

Comments
 (0)