@@ -6,21 +6,12 @@ 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 :: ptr;
9
10
use crate :: str:: FromStr ;
10
11
11
12
use super :: from_str_radix;
12
13
use super :: { IntErrorKind , ParseIntError } ;
13
14
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
15
/// A marker trait for primitive types which can be zero.
25
16
///
26
17
/// This is an implementation detail for <code>[NonZero]\<T></code> which may disappear or be replaced at any time.
@@ -34,38 +25,70 @@ mod private {
34
25
issue = "none"
35
26
) ]
36
27
#[ const_trait]
37
- pub unsafe trait ZeroablePrimitive : Sized + Copy + private:: Sealed { }
28
+ pub unsafe trait ZeroablePrimitive : Sized + Copy + private:: Sealed {
29
+ #[ doc( hidden) ]
30
+ type NonZeroInner : Sized + Copy ;
31
+ }
38
32
39
33
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 { }
34
+ ( $( $NonZeroInner: ident ( $primitive: ty ) ) ,+ $( , ) ?) => {
35
+ mod private {
36
+ #[ unstable(
37
+ feature = "nonzero_internals" ,
38
+ reason = "implementation detail which may disappear or be replaced at any time" ,
39
+ issue = "none"
40
+ ) ]
41
+ #[ const_trait]
42
+ pub trait Sealed { }
43
+
44
+ $(
45
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
46
+ #[ repr( transparent) ]
47
+ #[ rustc_layout_scalar_valid_range_start( 1 ) ]
48
+ #[ rustc_nonnull_optimization_guaranteed]
49
+ #[ unstable(
50
+ feature = "nonzero_internals" ,
51
+ reason = "implementation detail which may disappear or be replaced at any time" ,
52
+ issue = "none"
53
+ ) ]
54
+ pub struct $NonZeroInner( $primitive) ;
55
+ ) +
56
+ }
57
+
58
+ $(
59
+ #[ unstable(
60
+ feature = "nonzero_internals" ,
61
+ reason = "implementation detail which may disappear or be replaced at any time" ,
62
+ issue = "none"
63
+ ) ]
64
+ impl const private:: Sealed for $primitive { }
65
+
66
+ #[ unstable(
67
+ feature = "nonzero_internals" ,
68
+ reason = "implementation detail which may disappear or be replaced at any time" ,
69
+ issue = "none"
70
+ ) ]
71
+ unsafe impl const ZeroablePrimitive for $primitive {
72
+ type NonZeroInner = private:: $NonZeroInner;
73
+ }
74
+ ) +
54
75
} ;
55
76
}
56
77
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 ) ;
78
+ impl_zeroable_primitive ! (
79
+ NonZeroU8Inner ( u8 ) ,
80
+ NonZeroU16Inner ( u16 ) ,
81
+ NonZeroU32Inner ( u32 ) ,
82
+ NonZeroU64Inner ( u64 ) ,
83
+ NonZeroU128Inner ( u128 ) ,
84
+ NonZeroUsizeInner ( usize ) ,
85
+ NonZeroI8Inner ( i8 ) ,
86
+ NonZeroI16Inner ( i16 ) ,
87
+ NonZeroI32Inner ( i32 ) ,
88
+ NonZeroI64Inner ( i64 ) ,
89
+ NonZeroI128Inner ( i128 ) ,
90
+ NonZeroIsizeInner ( isize ) ,
91
+ ) ;
69
92
70
93
/// A value that is known not to equal zero.
71
94
///
@@ -80,10 +103,8 @@ impl_zeroable_primitive!(isize);
80
103
/// ```
81
104
#[ unstable( feature = "generic_nonzero" , issue = "120257" ) ]
82
105
#[ repr( transparent) ]
83
- #[ rustc_layout_scalar_valid_range_start( 1 ) ]
84
- #[ rustc_nonnull_optimization_guaranteed]
85
106
#[ rustc_diagnostic_item = "NonZero" ]
86
- pub struct NonZero < T : ZeroablePrimitive > ( T ) ;
107
+ pub struct NonZero < T : ZeroablePrimitive > ( T :: NonZeroInner ) ;
87
108
88
109
macro_rules! impl_nonzero_fmt {
89
110
( $Trait: ident) => {
@@ -114,8 +135,7 @@ where
114
135
{
115
136
#[ inline]
116
137
fn clone ( & self ) -> Self {
117
- // SAFETY: The contained value is non-zero.
118
- unsafe { Self ( self . 0 ) }
138
+ Self ( self . 0 )
119
139
}
120
140
}
121
141
@@ -188,19 +208,19 @@ where
188
208
#[ inline]
189
209
fn max ( self , other : Self ) -> Self {
190
210
// SAFETY: The maximum of two non-zero values is still non-zero.
191
- unsafe { Self ( self . get ( ) . max ( other. get ( ) ) ) }
211
+ unsafe { Self :: new_unchecked ( self . get ( ) . max ( other. get ( ) ) ) }
192
212
}
193
213
194
214
#[ inline]
195
215
fn min ( self , other : Self ) -> Self {
196
216
// SAFETY: The minimum of two non-zero values is still non-zero.
197
- unsafe { Self ( self . get ( ) . min ( other. get ( ) ) ) }
217
+ unsafe { Self :: new_unchecked ( self . get ( ) . min ( other. get ( ) ) ) }
198
218
}
199
219
200
220
#[ inline]
201
221
fn clamp ( self , min : Self , max : Self ) -> Self {
202
222
// 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 ( ) ) ) }
223
+ unsafe { Self :: new_unchecked ( self . get ( ) . clamp ( min. get ( ) , max. get ( ) ) ) }
204
224
}
205
225
}
206
226
@@ -240,7 +260,7 @@ where
240
260
#[ inline]
241
261
fn bitor ( self , rhs : Self ) -> Self :: Output {
242
262
// SAFETY: Bitwise OR of two non-zero values is still non-zero.
243
- unsafe { Self ( self . get ( ) | rhs. get ( ) ) }
263
+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs. get ( ) ) }
244
264
}
245
265
}
246
266
@@ -254,7 +274,7 @@ where
254
274
#[ inline]
255
275
fn bitor ( self , rhs : T ) -> Self :: Output {
256
276
// SAFETY: Bitwise OR of a non-zero value with anything is still non-zero.
257
- unsafe { Self ( self . get ( ) | rhs) }
277
+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs) }
258
278
}
259
279
}
260
280
@@ -268,7 +288,7 @@ where
268
288
#[ inline]
269
289
fn bitor ( self , rhs : NonZero < T > ) -> Self :: Output {
270
290
// SAFETY: Bitwise OR of anything with a non-zero value is still non-zero.
271
- unsafe { NonZero ( self | rhs. get ( ) ) }
291
+ unsafe { NonZero :: new_unchecked ( self | rhs. get ( ) ) }
272
292
}
273
293
}
274
294
@@ -346,7 +366,7 @@ where
346
366
pub fn from_mut ( n : & mut T ) -> Option < & mut Self > {
347
367
// SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
348
368
// the same layout and size as `T`, with `0` representing `None`.
349
- let opt_n = unsafe { & mut * ( n as * mut T as * mut Option < Self > ) } ;
369
+ let opt_n = unsafe { & mut * ( ptr :: from_mut ( n ) . cast :: < Option < Self > > ( ) ) } ;
350
370
351
371
opt_n. as_mut ( )
352
372
}
@@ -390,12 +410,17 @@ where
390
410
// memory somewhere. If the value of `self` was from by-value argument
391
411
// of some not-inlined function, LLVM don't have range metadata
392
412
// to understand that the value cannot be zero.
393
- match Self :: new ( self . 0 ) {
394
- Some ( Self ( n) ) => n,
413
+ //
414
+ // SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
415
+ match unsafe { intrinsics:: transmute_unchecked ( self ) } {
395
416
None => {
396
417
// SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
397
418
unsafe { intrinsics:: unreachable ( ) }
398
419
}
420
+ Some ( Self ( inner) ) => {
421
+ // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
422
+ unsafe { intrinsics:: transmute_unchecked ( inner) }
423
+ }
399
424
}
400
425
}
401
426
}
0 commit comments