3
3
use crate :: cmp:: Ordering ;
4
4
use crate :: fmt;
5
5
use crate :: hash:: { Hash , Hasher } ;
6
+ use crate :: intrinsics;
6
7
#[ cfg( bootstrap) ]
7
8
use crate :: marker:: StructuralEq ;
8
9
use crate :: marker:: StructuralPartialEq ;
9
10
use crate :: ops:: { BitOr , BitOrAssign , Div , Neg , Rem } ;
11
+ use crate :: ptr;
10
12
use crate :: str:: FromStr ;
11
13
12
14
use super :: from_str_radix;
13
15
use super :: { IntErrorKind , ParseIntError } ;
14
- use crate :: intrinsics;
15
16
16
17
mod private {
17
18
#[ unstable(
@@ -35,7 +36,7 @@ mod private {
35
36
pub trait ZeroablePrimitive : Sized + Copy + private:: Sealed { }
36
37
37
38
macro_rules! impl_zeroable_primitive {
38
- ( $NonZero : ident ( $ primitive: ty ) ) => {
39
+ ( $primitive: ty) => {
39
40
#[ unstable(
40
41
feature = "nonzero_internals" ,
41
42
reason = "implementation detail which may disappear or be replaced at any time" ,
@@ -52,18 +53,18 @@ macro_rules! impl_zeroable_primitive {
52
53
} ;
53
54
}
54
55
55
- impl_zeroable_primitive ! ( NonZeroU8 ( u8 ) ) ;
56
- impl_zeroable_primitive ! ( NonZeroU16 ( u16 ) ) ;
57
- impl_zeroable_primitive ! ( NonZeroU32 ( u32 ) ) ;
58
- impl_zeroable_primitive ! ( NonZeroU64 ( u64 ) ) ;
59
- impl_zeroable_primitive ! ( NonZeroU128 ( u128 ) ) ;
60
- impl_zeroable_primitive ! ( NonZeroUsize ( usize ) ) ;
61
- impl_zeroable_primitive ! ( NonZeroI8 ( i8 ) ) ;
62
- impl_zeroable_primitive ! ( NonZeroI16 ( i16 ) ) ;
63
- impl_zeroable_primitive ! ( NonZeroI32 ( i32 ) ) ;
64
- impl_zeroable_primitive ! ( NonZeroI64 ( i64 ) ) ;
65
- impl_zeroable_primitive ! ( NonZeroI128 ( i128 ) ) ;
66
- impl_zeroable_primitive ! ( NonZeroIsize ( isize ) ) ;
56
+ impl_zeroable_primitive ! ( u8 ) ;
57
+ impl_zeroable_primitive ! ( u16 ) ;
58
+ impl_zeroable_primitive ! ( u32 ) ;
59
+ impl_zeroable_primitive ! ( u64 ) ;
60
+ impl_zeroable_primitive ! ( u128 ) ;
61
+ impl_zeroable_primitive ! ( usize ) ;
62
+ impl_zeroable_primitive ! ( i8 ) ;
63
+ impl_zeroable_primitive ! ( i16 ) ;
64
+ impl_zeroable_primitive ! ( i32 ) ;
65
+ impl_zeroable_primitive ! ( i64 ) ;
66
+ impl_zeroable_primitive ! ( i128 ) ;
67
+ impl_zeroable_primitive ! ( isize ) ;
67
68
68
69
/// A value that is known not to equal zero.
69
70
///
@@ -83,6 +84,88 @@ impl_zeroable_primitive!(NonZeroIsize(isize));
83
84
#[ rustc_diagnostic_item = "NonZero" ]
84
85
pub struct NonZero < T : ZeroablePrimitive > ( T ) ;
85
86
87
+ impl < T > NonZero < T >
88
+ where
89
+ T : ZeroablePrimitive ,
90
+ {
91
+ /// Creates a non-zero if the given value is not zero.
92
+ #[ stable( feature = "nonzero" , since = "1.28.0" ) ]
93
+ #[ rustc_const_stable( feature = "const_nonzero_int_methods" , since = "1.47.0" ) ]
94
+ #[ rustc_allow_const_fn_unstable( const_refs_to_cell) ]
95
+ #[ must_use]
96
+ #[ inline]
97
+ pub const fn new ( n : T ) -> Option < Self > {
98
+ // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
99
+ // the same layout and size as `T`, with `0` representing `None`.
100
+ unsafe { ptr:: read ( ptr:: addr_of!( n) . cast ( ) ) }
101
+ }
102
+
103
+ /// Creates a non-zero without checking whether the value is non-zero.
104
+ /// This results in undefined behaviour if the value is zero.
105
+ ///
106
+ /// # Safety
107
+ ///
108
+ /// The value must not be zero.
109
+ #[ stable( feature = "nonzero" , since = "1.28.0" ) ]
110
+ #[ rustc_const_stable( feature = "nonzero" , since = "1.28.0" ) ]
111
+ #[ must_use]
112
+ #[ inline]
113
+ pub const unsafe fn new_unchecked ( n : T ) -> Self {
114
+ match Self :: new ( n) {
115
+ Some ( n) => n,
116
+ None => {
117
+ // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable.
118
+ unsafe {
119
+ intrinsics:: assert_unsafe_precondition!(
120
+ "NonZero::new_unchecked requires the argument to be non-zero" ,
121
+ ( ) => false ,
122
+ ) ;
123
+ intrinsics:: unreachable ( )
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ /// Converts a reference to a non-zero mutable reference
130
+ /// if the referenced value is not zero.
131
+ #[ unstable( feature = "nonzero_from_mut" , issue = "106290" ) ]
132
+ #[ must_use]
133
+ #[ inline]
134
+ pub fn from_mut ( n : & mut T ) -> Option < & mut Self > {
135
+ // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
136
+ // the same layout and size as `T`, with `0` representing `None`.
137
+ let opt_n = unsafe { & mut * ( n as * mut T as * mut Option < Self > ) } ;
138
+
139
+ opt_n. as_mut ( )
140
+ }
141
+
142
+ /// Converts a mutable reference to a non-zero mutable reference
143
+ /// without checking whether the referenced value is non-zero.
144
+ /// This results in undefined behavior if the referenced value is zero.
145
+ ///
146
+ /// # Safety
147
+ ///
148
+ /// The referenced value must not be zero.
149
+ #[ unstable( feature = "nonzero_from_mut" , issue = "106290" ) ]
150
+ #[ must_use]
151
+ #[ inline]
152
+ pub unsafe fn from_mut_unchecked ( n : & mut T ) -> & mut Self {
153
+ match Self :: from_mut ( n) {
154
+ Some ( n) => n,
155
+ None => {
156
+ // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable.
157
+ unsafe {
158
+ intrinsics:: assert_unsafe_precondition!(
159
+ "NonZero::from_mut_unchecked requires the argument to dereference as non-zero" ,
160
+ ( ) => false ,
161
+ ) ;
162
+ intrinsics:: unreachable ( )
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+
86
169
macro_rules! impl_nonzero_fmt {
87
170
( #[ $stability: meta] ( $( $Trait: ident ) ,+ ) for $Ty: ident ) => {
88
171
$(
@@ -100,7 +183,6 @@ macro_rules! impl_nonzero_fmt {
100
183
macro_rules! nonzero_integer {
101
184
(
102
185
#[ $stability: meta]
103
- #[ $const_new_unchecked_stability: meta]
104
186
Self = $Ty: ident,
105
187
Primitive = $signedness: ident $Int: ident,
106
188
$( UnsignedNonZero = $UnsignedNonZero: ident, ) ?
@@ -143,74 +225,6 @@ macro_rules! nonzero_integer {
143
225
pub type $Ty = NonZero <$Int>;
144
226
145
227
impl $Ty {
146
- /// Creates a non-zero without checking whether the value is non-zero.
147
- /// This results in undefined behaviour if the value is zero.
148
- ///
149
- /// # Safety
150
- ///
151
- /// The value must not be zero.
152
- #[ $stability]
153
- #[ $const_new_unchecked_stability]
154
- #[ must_use]
155
- #[ inline]
156
- pub const unsafe fn new_unchecked( n: $Int) -> Self {
157
- crate :: panic:: debug_assert_nounwind!(
158
- n != 0 ,
159
- concat!( stringify!( $Ty) , "::new_unchecked requires a non-zero argument" )
160
- ) ;
161
- // SAFETY: this is guaranteed to be safe by the caller.
162
- unsafe {
163
- Self ( n)
164
- }
165
- }
166
-
167
- /// Creates a non-zero if the given value is not zero.
168
- #[ $stability]
169
- #[ rustc_const_stable( feature = "const_nonzero_int_methods" , since = "1.47.0" ) ]
170
- #[ must_use]
171
- #[ inline]
172
- pub const fn new( n: $Int) -> Option <Self > {
173
- if n != 0 {
174
- // SAFETY: we just checked that there's no `0`
175
- Some ( unsafe { Self ( n) } )
176
- } else {
177
- None
178
- }
179
- }
180
-
181
- /// Converts a primitive mutable reference to a non-zero mutable reference
182
- /// without checking whether the referenced value is non-zero.
183
- /// This results in undefined behavior if `*n` is zero.
184
- ///
185
- /// # Safety
186
- /// The referenced value must not be currently zero.
187
- #[ unstable( feature = "nonzero_from_mut" , issue = "106290" ) ]
188
- #[ must_use]
189
- #[ inline]
190
- pub unsafe fn from_mut_unchecked( n: & mut $Int) -> & mut Self {
191
- // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero.
192
- unsafe {
193
- let n_alias = & mut * n;
194
- core:: intrinsics:: assert_unsafe_precondition!(
195
- concat!( stringify!( $Ty) , "::from_mut_unchecked requires the argument to dereference as non-zero" ) ,
196
- ( n_alias: & mut $Int) => * n_alias != 0
197
- ) ;
198
- & mut * ( n as * mut $Int as * mut Self )
199
- }
200
- }
201
-
202
- /// Converts a primitive mutable reference to a non-zero mutable reference
203
- /// if the referenced integer is not zero.
204
- #[ unstable( feature = "nonzero_from_mut" , issue = "106290" ) ]
205
- #[ must_use]
206
- #[ inline]
207
- pub fn from_mut( n: & mut $Int) -> Option <& mut Self > {
208
- // SAFETY: Self is repr(transparent), and the value is non-zero.
209
- // As long as the returned reference is alive,
210
- // the user cannot `*n = 0` directly.
211
- ( * n != 0 ) . then( || unsafe { & mut * ( n as * mut $Int as * mut Self ) } )
212
- }
213
-
214
228
/// Returns the value as a primitive type.
215
229
#[ $stability]
216
230
#[ inline]
@@ -724,7 +738,6 @@ macro_rules! nonzero_integer {
724
738
( Self = $Ty: ident, Primitive = unsigned $Int: ident $( , ) ?) => {
725
739
nonzero_integer! {
726
740
#[ stable( feature = "nonzero" , since = "1.28.0" ) ]
727
- #[ rustc_const_stable( feature = "nonzero" , since = "1.28.0" ) ]
728
741
Self = $Ty,
729
742
Primitive = unsigned $Int,
730
743
UnsignedPrimitive = $Int,
@@ -735,7 +748,6 @@ macro_rules! nonzero_integer {
735
748
( Self = $Ty: ident, Primitive = signed $Int: ident, $( $rest: tt) * ) => {
736
749
nonzero_integer! {
737
750
#[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ]
738
- #[ rustc_const_stable( feature = "signed_nonzero" , since = "1.34.0" ) ]
739
751
Self = $Ty,
740
752
Primitive = signed $Int,
741
753
$( $rest) *
@@ -757,7 +769,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
757
769
fn div( self , other: $Ty) -> $Int {
758
770
// SAFETY: div by zero is checked because `other` is a nonzero,
759
771
// and MIN/-1 is checked because `self` is an unsigned int.
760
- unsafe { crate :: intrinsics:: unchecked_div( self , other. get( ) ) }
772
+ unsafe { intrinsics:: unchecked_div( self , other. get( ) ) }
761
773
}
762
774
}
763
775
@@ -770,7 +782,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
770
782
fn rem( self , other: $Ty) -> $Int {
771
783
// SAFETY: rem by zero is checked because `other` is a nonzero,
772
784
// and MIN/-1 is checked because `self` is an unsigned int.
773
- unsafe { crate :: intrinsics:: unchecked_rem( self , other. get( ) ) }
785
+ unsafe { intrinsics:: unchecked_rem( self , other. get( ) ) }
774
786
}
775
787
}
776
788
} ;
0 commit comments