@@ -6,21 +6,13 @@ use crate::hash::{Hash, Hasher};
6
6
use crate :: intrinsics;
7
7
use crate :: marker:: StructuralPartialEq ;
8
8
use crate :: ops:: { BitOr , BitOrAssign , Div , Neg , Rem } ;
9
+ use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
10
+ use crate :: ptr;
9
11
use crate :: str:: FromStr ;
10
12
11
13
use super :: from_str_radix;
12
14
use super :: { IntErrorKind , ParseIntError } ;
13
15
14
- mod private {
15
- #[ unstable(
16
- feature = "nonzero_internals" ,
17
- reason = "implementation detail which may disappear or be replaced at any time" ,
18
- issue = "none"
19
- ) ]
20
- #[ const_trait]
21
- pub trait Sealed { }
22
- }
23
-
24
16
/// A marker trait for primitive types which can be zero.
25
17
///
26
18
/// This is an implementation detail for <code>[NonZero]\<T></code> which may disappear or be replaced at any time.
@@ -34,38 +26,70 @@ mod private {
34
26
issue = "none"
35
27
) ]
36
28
#[ const_trait]
37
- pub unsafe trait ZeroablePrimitive : Sized + Copy + private:: Sealed { }
29
+ pub unsafe trait ZeroablePrimitive : Sized + Copy + private:: Sealed {
30
+ #[ doc( hidden) ]
31
+ type NonZeroInner : Sized + Copy ;
32
+ }
38
33
39
34
macro_rules! impl_zeroable_primitive {
40
- ( $primitive: ty) => {
41
- #[ unstable(
42
- feature = "nonzero_internals" ,
43
- reason = "implementation detail which may disappear or be replaced at any time" ,
44
- issue = "none"
45
- ) ]
46
- impl const private:: Sealed for $primitive { }
47
-
48
- #[ unstable(
49
- feature = "nonzero_internals" ,
50
- reason = "implementation detail which may disappear or be replaced at any time" ,
51
- issue = "none"
52
- ) ]
53
- unsafe impl const ZeroablePrimitive for $primitive { }
35
+ ( $( $NonZeroInner: ident ( $primitive: ty ) ) ,+ $( , ) ?) => {
36
+ mod private {
37
+ #[ unstable(
38
+ feature = "nonzero_internals" ,
39
+ reason = "implementation detail which may disappear or be replaced at any time" ,
40
+ issue = "none"
41
+ ) ]
42
+ #[ const_trait]
43
+ pub trait Sealed { }
44
+
45
+ $(
46
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
47
+ #[ repr( transparent) ]
48
+ #[ rustc_layout_scalar_valid_range_start( 1 ) ]
49
+ #[ rustc_nonnull_optimization_guaranteed]
50
+ #[ unstable(
51
+ feature = "nonzero_internals" ,
52
+ reason = "implementation detail which may disappear or be replaced at any time" ,
53
+ issue = "none"
54
+ ) ]
55
+ pub struct $NonZeroInner( $primitive) ;
56
+ ) +
57
+ }
58
+
59
+ $(
60
+ #[ unstable(
61
+ feature = "nonzero_internals" ,
62
+ reason = "implementation detail which may disappear or be replaced at any time" ,
63
+ issue = "none"
64
+ ) ]
65
+ impl const private:: Sealed for $primitive { }
66
+
67
+ #[ unstable(
68
+ feature = "nonzero_internals" ,
69
+ reason = "implementation detail which may disappear or be replaced at any time" ,
70
+ issue = "none"
71
+ ) ]
72
+ unsafe impl const ZeroablePrimitive for $primitive {
73
+ type NonZeroInner = private:: $NonZeroInner;
74
+ }
75
+ ) +
54
76
} ;
55
77
}
56
78
57
- impl_zeroable_primitive ! ( u8 ) ;
58
- impl_zeroable_primitive ! ( u16 ) ;
59
- impl_zeroable_primitive ! ( u32 ) ;
60
- impl_zeroable_primitive ! ( u64 ) ;
61
- impl_zeroable_primitive ! ( u128 ) ;
62
- impl_zeroable_primitive ! ( usize ) ;
63
- impl_zeroable_primitive ! ( i8 ) ;
64
- impl_zeroable_primitive ! ( i16 ) ;
65
- impl_zeroable_primitive ! ( i32 ) ;
66
- impl_zeroable_primitive ! ( i64 ) ;
67
- impl_zeroable_primitive ! ( i128 ) ;
68
- impl_zeroable_primitive ! ( isize ) ;
79
+ impl_zeroable_primitive ! (
80
+ NonZeroU8Inner ( u8 ) ,
81
+ NonZeroU16Inner ( u16 ) ,
82
+ NonZeroU32Inner ( u32 ) ,
83
+ NonZeroU64Inner ( u64 ) ,
84
+ NonZeroU128Inner ( u128 ) ,
85
+ NonZeroUsizeInner ( usize ) ,
86
+ NonZeroI8Inner ( i8 ) ,
87
+ NonZeroI16Inner ( i16 ) ,
88
+ NonZeroI32Inner ( i32 ) ,
89
+ NonZeroI64Inner ( i64 ) ,
90
+ NonZeroI128Inner ( i128 ) ,
91
+ NonZeroIsizeInner ( isize ) ,
92
+ ) ;
69
93
70
94
/// A value that is known not to equal zero.
71
95
///
@@ -80,10 +104,9 @@ impl_zeroable_primitive!(isize);
80
104
/// ```
81
105
#[ unstable( feature = "generic_nonzero" , issue = "120257" ) ]
82
106
#[ repr( transparent) ]
83
- #[ rustc_layout_scalar_valid_range_start( 1 ) ]
84
107
#[ rustc_nonnull_optimization_guaranteed]
85
108
#[ rustc_diagnostic_item = "NonZero" ]
86
- pub struct NonZero < T : ZeroablePrimitive > ( T ) ;
109
+ pub struct NonZero < T : ZeroablePrimitive > ( T :: NonZeroInner ) ;
87
110
88
111
macro_rules! impl_nonzero_fmt {
89
112
( $Trait: ident) => {
@@ -107,15 +130,33 @@ impl_nonzero_fmt!(Octal);
107
130
impl_nonzero_fmt ! ( LowerHex ) ;
108
131
impl_nonzero_fmt ! ( UpperHex ) ;
109
132
133
+ macro_rules! impl_nonzero_auto_trait {
134
+ ( unsafe $Trait: ident) => {
135
+ #[ stable( feature = "nonzero" , since = "1.28.0" ) ]
136
+ unsafe impl <T > $Trait for NonZero <T > where T : ZeroablePrimitive + $Trait { }
137
+ } ;
138
+ ( $Trait: ident) => {
139
+ #[ stable( feature = "nonzero" , since = "1.28.0" ) ]
140
+ impl <T > $Trait for NonZero <T > where T : ZeroablePrimitive + $Trait { }
141
+ } ;
142
+ }
143
+
144
+ // Implement auto-traits manually based on `T` to avoid docs exposing
145
+ // the `ZeroablePrimitive::NonZeroInner` implementation detail.
146
+ impl_nonzero_auto_trait ! ( RefUnwindSafe ) ;
147
+ impl_nonzero_auto_trait ! ( unsafe Send ) ;
148
+ impl_nonzero_auto_trait ! ( unsafe Sync ) ;
149
+ impl_nonzero_auto_trait ! ( Unpin ) ;
150
+ impl_nonzero_auto_trait ! ( UnwindSafe ) ;
151
+
110
152
#[ stable( feature = "nonzero" , since = "1.28.0" ) ]
111
153
impl < T > Clone for NonZero < T >
112
154
where
113
155
T : ZeroablePrimitive ,
114
156
{
115
157
#[ inline]
116
158
fn clone ( & self ) -> Self {
117
- // SAFETY: The contained value is non-zero.
118
- unsafe { Self ( self . 0 ) }
159
+ Self ( self . 0 )
119
160
}
120
161
}
121
162
@@ -188,19 +229,19 @@ where
188
229
#[ inline]
189
230
fn max ( self , other : Self ) -> Self {
190
231
// SAFETY: The maximum of two non-zero values is still non-zero.
191
- unsafe { Self ( self . get ( ) . max ( other. get ( ) ) ) }
232
+ unsafe { Self :: new_unchecked ( self . get ( ) . max ( other. get ( ) ) ) }
192
233
}
193
234
194
235
#[ inline]
195
236
fn min ( self , other : Self ) -> Self {
196
237
// SAFETY: The minimum of two non-zero values is still non-zero.
197
- unsafe { Self ( self . get ( ) . min ( other. get ( ) ) ) }
238
+ unsafe { Self :: new_unchecked ( self . get ( ) . min ( other. get ( ) ) ) }
198
239
}
199
240
200
241
#[ inline]
201
242
fn clamp ( self , min : Self , max : Self ) -> Self {
202
243
// SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
203
- unsafe { Self ( self . get ( ) . clamp ( min. get ( ) , max. get ( ) ) ) }
244
+ unsafe { Self :: new_unchecked ( self . get ( ) . clamp ( min. get ( ) , max. get ( ) ) ) }
204
245
}
205
246
}
206
247
@@ -240,7 +281,7 @@ where
240
281
#[ inline]
241
282
fn bitor ( self , rhs : Self ) -> Self :: Output {
242
283
// SAFETY: Bitwise OR of two non-zero values is still non-zero.
243
- unsafe { Self ( self . get ( ) | rhs. get ( ) ) }
284
+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs. get ( ) ) }
244
285
}
245
286
}
246
287
@@ -254,7 +295,7 @@ where
254
295
#[ inline]
255
296
fn bitor ( self , rhs : T ) -> Self :: Output {
256
297
// SAFETY: Bitwise OR of a non-zero value with anything is still non-zero.
257
- unsafe { Self ( self . get ( ) | rhs) }
298
+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs) }
258
299
}
259
300
}
260
301
@@ -268,7 +309,7 @@ where
268
309
#[ inline]
269
310
fn bitor ( self , rhs : NonZero < T > ) -> Self :: Output {
270
311
// SAFETY: Bitwise OR of anything with a non-zero value is still non-zero.
271
- unsafe { NonZero ( self | rhs. get ( ) ) }
312
+ unsafe { NonZero :: new_unchecked ( self | rhs. get ( ) ) }
272
313
}
273
314
}
274
315
@@ -345,7 +386,7 @@ where
345
386
pub fn from_mut ( n : & mut T ) -> Option < & mut Self > {
346
387
// SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
347
388
// the same layout and size as `T`, with `0` representing `None`.
348
- let opt_n = unsafe { & mut * ( n as * mut T as * mut Option < Self > ) } ;
389
+ let opt_n = unsafe { & mut * ( ptr :: from_mut ( n ) . cast :: < Option < Self > > ( ) ) } ;
349
390
350
391
opt_n. as_mut ( )
351
392
}
@@ -388,12 +429,17 @@ where
388
429
// memory somewhere. If the value of `self` was from by-value argument
389
430
// of some not-inlined function, LLVM don't have range metadata
390
431
// to understand that the value cannot be zero.
391
- match Self :: new ( self . 0 ) {
392
- Some ( Self ( n) ) => n,
432
+ //
433
+ // SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
434
+ match unsafe { intrinsics:: transmute_unchecked ( self ) } {
393
435
None => {
394
436
// SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
395
437
unsafe { intrinsics:: unreachable ( ) }
396
438
}
439
+ Some ( Self ( inner) ) => {
440
+ // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
441
+ unsafe { intrinsics:: transmute_unchecked ( inner) }
442
+ }
397
443
}
398
444
}
399
445
}
0 commit comments