@@ -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