Skip to content

Commit ffebb44

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

File tree

3 files changed

+157
-8
lines changed

3 files changed

+157
-8
lines changed

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

+155-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,155 @@ 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+
#[allow(unused_unsafe)]
84+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
85+
unsafe {
86+
Self(self.0)
87+
}
88+
}
89+
}
90+
91+
#[$stability]
92+
impl PartialEq for $Ty {
93+
#[inline]
94+
fn eq(&self, other: &Self) -> bool {
95+
#[allow(unused_unsafe)]
96+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
97+
unsafe {
98+
self.0 == other.0
99+
}
100+
}
101+
102+
#[inline]
103+
fn ne(&self, other: &Self) -> bool {
104+
#[allow(unused_unsafe)]
105+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
106+
unsafe {
107+
self.0 != other.0
108+
}
109+
}
110+
}
111+
112+
#[$stability]
113+
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
114+
impl StructuralPartialEq for $Ty {}
115+
116+
#[$stability]
117+
impl PartialOrd for $Ty {
118+
#[inline]
119+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
120+
#[allow(unused_unsafe)]
121+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
122+
unsafe {
123+
self.0.partial_cmp(&other.0)
124+
}
125+
}
126+
127+
#[inline]
128+
fn lt(&self, other: &Self) -> bool {
129+
#[allow(unused_unsafe)]
130+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
131+
unsafe {
132+
self.0 < other.0
133+
}
134+
}
135+
136+
#[inline]
137+
fn le(&self, other: &Self) -> bool {
138+
#[allow(unused_unsafe)]
139+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
140+
unsafe {
141+
self.0 <= other.0
142+
}
143+
}
144+
145+
#[inline]
146+
fn gt(&self, other: &Self) -> bool {
147+
#[allow(unused_unsafe)]
148+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
149+
unsafe {
150+
self.0 > other.0
151+
}
152+
}
153+
154+
#[inline]
155+
fn ge(&self, other: &Self) -> bool {
156+
#[allow(unused_unsafe)]
157+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
158+
unsafe {
159+
self.0 >= other.0
160+
}
161+
}
162+
}
163+
164+
#[$stability]
165+
impl Ord for $Ty {
166+
fn cmp(&self, other: &Self) -> Ordering {
167+
#[allow(unused_unsafe)]
168+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
169+
unsafe {
170+
self.0.cmp(&other.0)
171+
}
172+
}
173+
174+
fn max(self, other: Self) -> Self {
175+
#[allow(unused_unsafe)]
176+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values,
177+
// and the maximum of two non-zero values is still non-zero.
178+
unsafe {
179+
Self(self.0.max(other.0))
180+
}
181+
}
182+
183+
fn min(self, other: Self) -> Self {
184+
#[allow(unused_unsafe)]
185+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values,
186+
// and the minimum of two non-zero values is still non-zero.
187+
unsafe {
188+
Self(self.0.min(other.0))
189+
}
190+
}
191+
192+
fn clamp(self, min: Self, max: Self) -> Self {
193+
#[allow(unused_unsafe)]
194+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values, and
195+
// a non-zero value clamped between two non-zero values is still non-zero.
196+
unsafe {
197+
Self(self.0.clamp(min.0, max.0))
198+
}
199+
}
200+
}
201+
202+
#[$stability]
203+
impl Hash for $Ty {
204+
#[inline]
205+
fn hash<H>(&self, state: &mut H)
206+
where
207+
H: Hasher,
208+
{
209+
// SAFETY: A `NonZero` is guaranteed to only contain primitive non-zero values.
210+
#[allow(unused_unsafe)]
211+
unsafe {
212+
self.0.hash(state)
213+
}
214+
}
215+
}
216+
};
217+
}
218+
74219
macro_rules! impl_nonzero_fmt {
75220
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
76221
$(
@@ -128,13 +273,15 @@ macro_rules! nonzero_integer {
128273
///
129274
/// [null pointer optimization]: crate::option#representation
130275
#[$stability]
131-
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
276+
#[derive(Copy, Eq)]
132277
#[repr(transparent)]
133278
#[rustc_layout_scalar_valid_range_start(1)]
134279
#[rustc_nonnull_optimization_guaranteed]
135280
#[rustc_diagnostic_item = stringify!($Ty)]
136281
pub struct $Ty($Int);
137282

283+
impl_nonzero_traits!(#[$stability] $Ty);
284+
138285
impl $Ty {
139286
/// Creates a non-zero without checking whether the value is non-zero.
140287
/// This results in undefined behaviour if the value is zero.

Diff for: 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

Diff for: 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)