Skip to content

Commit c1db5d7

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

File tree

3 files changed

+110
-8
lines changed

3 files changed

+110
-8
lines changed

library/core/src/num/nonzero.rs

+108-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,108 @@ 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+
#[$stability]
102+
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
103+
impl StructuralPartialEq for $Ty {}
104+
105+
#[$stability]
106+
impl PartialOrd for $Ty {
107+
#[inline]
108+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
109+
self.get().partial_cmp(&other.get())
110+
}
111+
112+
#[inline]
113+
fn lt(&self, other: &Self) -> bool {
114+
self.get() < other.get()
115+
}
116+
117+
#[inline]
118+
fn le(&self, other: &Self) -> bool {
119+
self.get() <= other.get()
120+
}
121+
122+
#[inline]
123+
fn gt(&self, other: &Self) -> bool {
124+
self.get() > other.get()
125+
}
126+
127+
#[inline]
128+
fn ge(&self, other: &Self) -> bool {
129+
self.get() >= other.get()
130+
}
131+
}
132+
133+
#[$stability]
134+
impl Ord for $Ty {
135+
#[inline]
136+
fn cmp(&self, other: &Self) -> Ordering {
137+
self.get().cmp(&other.get())
138+
}
139+
140+
#[inline]
141+
fn max(self, other: Self) -> Self {
142+
// SAFETY: The maximum of two non-zero values is still non-zero.
143+
unsafe { Self(self.get().max(other.get())) }
144+
}
145+
146+
#[inline]
147+
fn min(self, other: Self) -> Self {
148+
// SAFETY: The minimum of two non-zero values is still non-zero.
149+
unsafe { Self(self.get().min(other.get())) }
150+
}
151+
152+
#[inline]
153+
fn clamp(self, min: Self, max: Self) -> Self {
154+
// SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
155+
unsafe { Self(self.get().clamp(min.get(), max.get())) }
156+
}
157+
}
158+
159+
#[$stability]
160+
impl Hash for $Ty {
161+
#[inline]
162+
fn hash<H>(&self, state: &mut H)
163+
where
164+
H: Hasher,
165+
{
166+
self.get().hash(state)
167+
}
168+
}
169+
};
170+
}
171+
74172
macro_rules! impl_nonzero_fmt {
75173
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
76174
$(
@@ -128,13 +226,15 @@ macro_rules! nonzero_integer {
128226
///
129227
/// [null pointer optimization]: crate::option#representation
130228
#[$stability]
131-
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
229+
#[derive(Copy, Eq)]
132230
#[repr(transparent)]
133231
#[rustc_layout_scalar_valid_range_start(1)]
134232
#[rustc_nonnull_optimization_guaranteed]
135233
#[rustc_diagnostic_item = stringify!($Ty)]
136234
pub struct $Ty($Int);
137235

236+
impl_nonzero_traits!(#[$stability] $Ty);
237+
138238
impl $Ty {
139239
/// Creates a non-zero without checking whether the value is non-zero.
140240
/// 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)