@@ -4,23 +4,15 @@ use crate::cmp::Ordering;
44use crate :: fmt;
55use crate :: hash:: { Hash , Hasher } ;
66use crate :: intrinsics;
7- use crate :: marker:: StructuralPartialEq ;
7+ use crate :: marker:: { Freeze , StructuralPartialEq } ;
88use crate :: ops:: { BitOr , BitOrAssign , Div , Neg , Rem } ;
9+ use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
10+ use crate :: ptr;
911use crate :: str:: FromStr ;
1012
1113use super :: from_str_radix;
1214use super :: { IntErrorKind , ParseIntError } ;
1315
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-
2416/// A marker trait for primitive types which can be zero.
2517///
2618/// 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 {
3426 issue = "none"
3527) ]
3628#[ 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+ }
3833
3934macro_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+ ) +
5476 } ;
5577}
5678
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+ ) ;
6993
7094/// A value that is known not to equal zero.
7195///
@@ -80,10 +104,9 @@ impl_zeroable_primitive!(isize);
80104/// ```
81105#[ unstable( feature = "generic_nonzero" , issue = "120257" ) ]
82106#[ repr( transparent) ]
83- #[ rustc_layout_scalar_valid_range_start( 1 ) ]
84107#[ rustc_nonnull_optimization_guaranteed]
85108#[ rustc_diagnostic_item = "NonZero" ]
86- pub struct NonZero < T : ZeroablePrimitive > ( T ) ;
109+ pub struct NonZero < T : ZeroablePrimitive > ( T :: NonZeroInner ) ;
87110
88111macro_rules! impl_nonzero_fmt {
89112 ( $Trait: ident) => {
@@ -107,15 +130,34 @@ impl_nonzero_fmt!(Octal);
107130impl_nonzero_fmt ! ( LowerHex ) ;
108131impl_nonzero_fmt ! ( UpperHex ) ;
109132
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 ! ( unsafe Freeze ) ;
147+ impl_nonzero_auto_trait ! ( RefUnwindSafe ) ;
148+ impl_nonzero_auto_trait ! ( unsafe Send ) ;
149+ impl_nonzero_auto_trait ! ( unsafe Sync ) ;
150+ impl_nonzero_auto_trait ! ( Unpin ) ;
151+ impl_nonzero_auto_trait ! ( UnwindSafe ) ;
152+
110153#[ stable( feature = "nonzero" , since = "1.28.0" ) ]
111154impl < T > Clone for NonZero < T >
112155where
113156 T : ZeroablePrimitive ,
114157{
115158 #[ inline]
116159 fn clone ( & self ) -> Self {
117- // SAFETY: The contained value is non-zero.
118- unsafe { Self ( self . 0 ) }
160+ Self ( self . 0 )
119161 }
120162}
121163
@@ -188,19 +230,19 @@ where
188230 #[ inline]
189231 fn max ( self , other : Self ) -> Self {
190232 // SAFETY: The maximum of two non-zero values is still non-zero.
191- unsafe { Self ( self . get ( ) . max ( other. get ( ) ) ) }
233+ unsafe { Self :: new_unchecked ( self . get ( ) . max ( other. get ( ) ) ) }
192234 }
193235
194236 #[ inline]
195237 fn min ( self , other : Self ) -> Self {
196238 // SAFETY: The minimum of two non-zero values is still non-zero.
197- unsafe { Self ( self . get ( ) . min ( other. get ( ) ) ) }
239+ unsafe { Self :: new_unchecked ( self . get ( ) . min ( other. get ( ) ) ) }
198240 }
199241
200242 #[ inline]
201243 fn clamp ( self , min : Self , max : Self ) -> Self {
202244 // 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 ( ) ) ) }
245+ unsafe { Self :: new_unchecked ( self . get ( ) . clamp ( min. get ( ) , max. get ( ) ) ) }
204246 }
205247}
206248
@@ -240,7 +282,7 @@ where
240282 #[ inline]
241283 fn bitor ( self , rhs : Self ) -> Self :: Output {
242284 // SAFETY: Bitwise OR of two non-zero values is still non-zero.
243- unsafe { Self ( self . get ( ) | rhs. get ( ) ) }
285+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs. get ( ) ) }
244286 }
245287}
246288
@@ -254,7 +296,7 @@ where
254296 #[ inline]
255297 fn bitor ( self , rhs : T ) -> Self :: Output {
256298 // SAFETY: Bitwise OR of a non-zero value with anything is still non-zero.
257- unsafe { Self ( self . get ( ) | rhs) }
299+ unsafe { Self :: new_unchecked ( self . get ( ) | rhs) }
258300 }
259301}
260302
@@ -268,7 +310,7 @@ where
268310 #[ inline]
269311 fn bitor ( self , rhs : NonZero < T > ) -> Self :: Output {
270312 // SAFETY: Bitwise OR of anything with a non-zero value is still non-zero.
271- unsafe { NonZero ( self | rhs. get ( ) ) }
313+ unsafe { NonZero :: new_unchecked ( self | rhs. get ( ) ) }
272314 }
273315}
274316
@@ -346,7 +388,7 @@ where
346388 pub fn from_mut ( n : & mut T ) -> Option < & mut Self > {
347389 // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
348390 // 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 > ) } ;
391+ let opt_n = unsafe { & mut * ( ptr :: from_mut ( n ) . cast :: < Option < Self > > ( ) ) } ;
350392
351393 opt_n. as_mut ( )
352394 }
@@ -390,12 +432,17 @@ where
390432 // memory somewhere. If the value of `self` was from by-value argument
391433 // of some not-inlined function, LLVM don't have range metadata
392434 // to understand that the value cannot be zero.
393- match Self :: new ( self . 0 ) {
394- Some ( Self ( n) ) => n,
435+ //
436+ // SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
437+ match unsafe { intrinsics:: transmute_unchecked ( self ) } {
395438 None => {
396439 // SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
397440 unsafe { intrinsics:: unreachable ( ) }
398441 }
442+ Some ( Self ( inner) ) => {
443+ // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
444+ unsafe { intrinsics:: transmute_unchecked ( inner) }
445+ }
399446 }
400447 }
401448}
0 commit comments