@@ -6,21 +6,13 @@ use crate::hash::{Hash, Hasher};
66use crate :: intrinsics;
77use crate :: marker:: 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,33 @@ 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 ! ( 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+
110152#[ stable( feature = "nonzero" , since = "1.28.0" ) ]
111153impl < T > Clone for NonZero < T >
112154where
113155 T : ZeroablePrimitive ,
114156{
115157 #[ inline]
116158 fn clone ( & self ) -> Self {
117- // SAFETY: The contained value is non-zero.
118- unsafe { Self ( self . 0 ) }
159+ Self ( self . 0 )
119160 }
120161}
121162
@@ -188,19 +229,19 @@ where
188229 #[ inline]
189230 fn max ( self , other : Self ) -> Self {
190231 // 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 ( ) ) ) }
192233 }
193234
194235 #[ inline]
195236 fn min ( self , other : Self ) -> Self {
196237 // 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 ( ) ) ) }
198239 }
199240
200241 #[ inline]
201242 fn clamp ( self , min : Self , max : Self ) -> Self {
202243 // 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 ( ) ) ) }
204245 }
205246}
206247
@@ -240,7 +281,7 @@ where
240281 #[ inline]
241282 fn bitor ( self , rhs : Self ) -> Self :: Output {
242283 // 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 ( ) ) }
244285 }
245286}
246287
@@ -254,7 +295,7 @@ where
254295 #[ inline]
255296 fn bitor ( self , rhs : T ) -> Self :: Output {
256297 // 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) }
258299 }
259300}
260301
@@ -268,7 +309,7 @@ where
268309 #[ inline]
269310 fn bitor ( self , rhs : NonZero < T > ) -> Self :: Output {
270311 // 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 ( ) ) }
272313 }
273314}
274315
@@ -345,7 +386,7 @@ where
345386 pub fn from_mut ( n : & mut T ) -> Option < & mut Self > {
346387 // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
347388 // 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 > > ( ) ) } ;
349390
350391 opt_n. as_mut ( )
351392 }
@@ -388,12 +429,17 @@ where
388429 // memory somewhere. If the value of `self` was from by-value argument
389430 // of some not-inlined function, LLVM don't have range metadata
390431 // 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 ) } {
393435 None => {
394436 // SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
395437 unsafe { intrinsics:: unreachable ( ) }
396438 }
439+ Some ( Self ( inner) ) => {
440+ // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
441+ unsafe { intrinsics:: transmute_unchecked ( inner) }
442+ }
397443 }
398444 }
399445}
0 commit comments