1
- use crate :: convert:: TryFrom ;
1
+ use crate :: convert:: { TryFrom , TryInto } ;
2
2
use crate :: intrinsics:: assert_unsafe_precondition;
3
3
use crate :: num:: NonZeroUsize ;
4
4
use crate :: { cmp, fmt, hash, mem, num} ;
@@ -8,134 +8,168 @@ use crate::{cmp, fmt, hash, mem, num};
8
8
///
9
9
/// Note that particularly large alignments, while representable in this type,
10
10
/// are likely not to be supported by actual allocators and linkers.
11
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
11
12
#[ derive( Copy , Clone ) ]
12
13
#[ repr( transparent) ]
13
- pub ( crate ) struct ValidAlign ( ValidAlignEnum ) ;
14
+ pub struct Alignment ( AlignmentEnum ) ;
14
15
15
- // ValidAlign is `repr(usize)`, but via extra steps.
16
- const _: ( ) = assert ! ( mem:: size_of:: <ValidAlign >( ) == mem:: size_of:: <usize >( ) ) ;
17
- const _: ( ) = assert ! ( mem:: align_of:: <ValidAlign >( ) == mem:: align_of:: <usize >( ) ) ;
16
+ // Alignment is `repr(usize)`, but via extra steps.
17
+ const _: ( ) = assert ! ( mem:: size_of:: <Alignment >( ) == mem:: size_of:: <usize >( ) ) ;
18
+ const _: ( ) = assert ! ( mem:: align_of:: <Alignment >( ) == mem:: align_of:: <usize >( ) ) ;
18
19
19
- impl ValidAlign {
20
- /// Creates a `ValidAlign` from a power-of-two `usize`.
20
+ impl Alignment {
21
+ /// Returns the alignment for a type.
22
+ ///
23
+ /// This provides the same numerical value as [`mem::align_of`],
24
+ /// but in an `Alignment` instead of a `usize.
25
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
26
+ #[ inline]
27
+ pub ( crate ) fn of < T > ( ) -> Self {
28
+ // SAFETY: rustc ensures that type alignment is always a power of two.
29
+ unsafe { Alignment :: new_unchecked ( mem:: align_of :: < T > ( ) ) }
30
+ }
31
+
32
+ /// Creates an `Alignment` from a `usize`, or returns `None` if it's
33
+ /// not a power of two.
34
+ ///
35
+ /// Note that `0` is not a power of two, nor a valid alignment.
36
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
37
+ #[ inline]
38
+ pub const fn new ( align : usize ) -> Option < Self > {
39
+ if align. is_power_of_two ( ) {
40
+ // SAFETY: Just checked it only has one bit set
41
+ Some ( unsafe { Self :: new_unchecked ( align) } )
42
+ } else {
43
+ None
44
+ }
45
+ }
46
+
47
+ /// Creates an `Alignment` from a power-of-two `usize`.
21
48
///
22
49
/// # Safety
23
50
///
24
51
/// `align` must be a power of two.
25
52
///
26
53
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
27
54
/// It must *not* be zero.
55
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
28
56
#[ inline]
29
- pub ( crate ) const unsafe fn new_unchecked ( align : usize ) -> Self {
57
+ pub const unsafe fn new_unchecked ( align : usize ) -> Self {
30
58
// SAFETY: Precondition passed to the caller.
31
59
unsafe { assert_unsafe_precondition ! ( ( align: usize ) => align. is_power_of_two( ) ) } ;
32
60
33
61
// SAFETY: By precondition, this must be a power of two, and
34
62
// our variants encompass all possible powers of two.
35
- unsafe { mem:: transmute :: < usize , ValidAlign > ( align) }
63
+ unsafe { mem:: transmute :: < usize , Alignment > ( align) }
36
64
}
37
65
66
+ /// Returns the alignment as a [`NonZeroUsize`]
67
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
38
68
#[ inline]
39
- pub ( crate ) const fn as_usize ( self ) -> usize {
69
+ pub const fn as_usize ( self ) -> usize {
40
70
self . 0 as usize
41
71
}
42
72
73
+ /// Returns the alignment as a [`usize`]
74
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
43
75
#[ inline]
44
- pub ( crate ) const fn as_nonzero ( self ) -> NonZeroUsize {
76
+ pub const fn as_nonzero ( self ) -> NonZeroUsize {
45
77
// SAFETY: All the discriminants are non-zero.
46
78
unsafe { NonZeroUsize :: new_unchecked ( self . as_usize ( ) ) }
47
79
}
48
80
49
- /// Returns the base 2 logarithm of the alignment.
81
+ /// Returns the base- 2 logarithm of the alignment.
50
82
///
51
83
/// This is always exact, as `self` represents a power of two.
84
+ ///
85
+ /// # Examples
86
+ ///
87
+ /// ```
88
+ /// #![feature(ptr_alignment_type)]
89
+ /// use std::ptr::Alignment;
90
+ ///
91
+ /// assert_eq!(Alignment::of::<u8>().log2(), 0);
92
+ /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
93
+ /// ```
94
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
52
95
#[ inline]
53
- pub ( crate ) fn log2 ( self ) -> u32 {
96
+ pub fn log2 ( self ) -> u32 {
54
97
self . as_nonzero ( ) . trailing_zeros ( )
55
98
}
56
-
57
- /// Returns the alignment for a type.
58
- #[ inline]
59
- pub ( crate ) fn of < T > ( ) -> Self {
60
- // SAFETY: rustc ensures that type alignment is always a power of two.
61
- unsafe { ValidAlign :: new_unchecked ( mem:: align_of :: < T > ( ) ) }
62
- }
63
99
}
64
100
65
- impl fmt:: Debug for ValidAlign {
101
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
102
+ impl fmt:: Debug for Alignment {
66
103
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
67
104
write ! ( f, "{:?} (1 << {:?})" , self . as_nonzero( ) , self . log2( ) )
68
105
}
69
106
}
70
107
71
- impl TryFrom < NonZeroUsize > for ValidAlign {
108
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
109
+ impl TryFrom < NonZeroUsize > for Alignment {
72
110
type Error = num:: TryFromIntError ;
73
111
74
112
#[ inline]
75
- fn try_from ( align : NonZeroUsize ) -> Result < ValidAlign , Self :: Error > {
76
- if align. is_power_of_two ( ) {
77
- // SAFETY: Just checked for power-of-two
78
- unsafe { Ok ( ValidAlign :: new_unchecked ( align. get ( ) ) ) }
79
- } else {
80
- Err ( num:: TryFromIntError ( ( ) ) )
81
- }
113
+ fn try_from ( align : NonZeroUsize ) -> Result < Alignment , Self :: Error > {
114
+ align. get ( ) . try_into ( )
82
115
}
83
116
}
84
117
85
- impl TryFrom < usize > for ValidAlign {
118
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
119
+ impl TryFrom < usize > for Alignment {
86
120
type Error = num:: TryFromIntError ;
87
121
88
122
#[ inline]
89
- fn try_from ( align : usize ) -> Result < ValidAlign , Self :: Error > {
90
- if align. is_power_of_two ( ) {
91
- // SAFETY: Just checked for power-of-two
92
- unsafe { Ok ( ValidAlign :: new_unchecked ( align) ) }
93
- } else {
94
- Err ( num:: TryFromIntError ( ( ) ) )
95
- }
123
+ fn try_from ( align : usize ) -> Result < Alignment , Self :: Error > {
124
+ Self :: new ( align) . ok_or ( num:: TryFromIntError ( ( ) ) )
96
125
}
97
126
}
98
127
99
- impl cmp:: Eq for ValidAlign { }
128
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
129
+ impl cmp:: Eq for Alignment { }
100
130
101
- impl cmp:: PartialEq for ValidAlign {
131
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
132
+ impl cmp:: PartialEq for Alignment {
102
133
#[ inline]
103
134
fn eq ( & self , other : & Self ) -> bool {
104
135
self . as_nonzero ( ) == other. as_nonzero ( )
105
136
}
106
137
}
107
138
108
- impl cmp:: Ord for ValidAlign {
139
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
140
+ impl cmp:: Ord for Alignment {
109
141
#[ inline]
110
142
fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
111
143
self . as_nonzero ( ) . cmp ( & other. as_nonzero ( ) )
112
144
}
113
145
}
114
146
115
- impl cmp:: PartialOrd for ValidAlign {
147
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
148
+ impl cmp:: PartialOrd for Alignment {
116
149
#[ inline]
117
150
fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
118
151
Some ( self . cmp ( other) )
119
152
}
120
153
}
121
154
122
- impl hash:: Hash for ValidAlign {
155
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
156
+ impl hash:: Hash for Alignment {
123
157
#[ inline]
124
158
fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
125
159
self . as_nonzero ( ) . hash ( state)
126
160
}
127
161
}
128
162
129
163
#[ cfg( target_pointer_width = "16" ) ]
130
- type ValidAlignEnum = ValidAlignEnum16 ;
164
+ type AlignmentEnum = AlignmentEnum16 ;
131
165
#[ cfg( target_pointer_width = "32" ) ]
132
- type ValidAlignEnum = ValidAlignEnum32 ;
166
+ type AlignmentEnum = AlignmentEnum32 ;
133
167
#[ cfg( target_pointer_width = "64" ) ]
134
- type ValidAlignEnum = ValidAlignEnum64 ;
168
+ type AlignmentEnum = AlignmentEnum64 ;
135
169
136
170
#[ derive( Copy , Clone ) ]
137
171
#[ repr( u16 ) ]
138
- enum ValidAlignEnum16 {
172
+ enum AlignmentEnum16 {
139
173
_Align1Shl0 = 1 << 0 ,
140
174
_Align1Shl1 = 1 << 1 ,
141
175
_Align1Shl2 = 1 << 2 ,
@@ -156,7 +190,7 @@ enum ValidAlignEnum16 {
156
190
157
191
#[ derive( Copy , Clone ) ]
158
192
#[ repr( u32 ) ]
159
- enum ValidAlignEnum32 {
193
+ enum AlignmentEnum32 {
160
194
_Align1Shl0 = 1 << 0 ,
161
195
_Align1Shl1 = 1 << 1 ,
162
196
_Align1Shl2 = 1 << 2 ,
@@ -193,7 +227,7 @@ enum ValidAlignEnum32 {
193
227
194
228
#[ derive( Copy , Clone ) ]
195
229
#[ repr( u64 ) ]
196
- enum ValidAlignEnum64 {
230
+ enum AlignmentEnum64 {
197
231
_Align1Shl0 = 1 << 0 ,
198
232
_Align1Shl1 = 1 << 1 ,
199
233
_Align1Shl2 = 1 << 2 ,
0 commit comments