1- use crate :: convert:: TryFrom ;
1+ use crate :: convert:: { TryFrom , TryInto } ;
22use crate :: intrinsics:: assert_unsafe_precondition;
33use crate :: num:: NonZeroUsize ;
44use crate :: { cmp, fmt, hash, mem, num} ;
@@ -8,134 +8,168 @@ use crate::{cmp, fmt, hash, mem, num};
88///
99/// Note that particularly large alignments, while representable in this type,
1010/// are likely not to be supported by actual allocators and linkers.
11+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
1112#[ derive( Copy , Clone ) ]
1213#[ repr( transparent) ]
13- pub ( crate ) struct ValidAlign ( ValidAlignEnum ) ;
14+ pub struct Alignment ( AlignmentEnum ) ;
1415
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 >( ) ) ;
1819
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`.
2148 ///
2249 /// # Safety
2350 ///
2451 /// `align` must be a power of two.
2552 ///
2653 /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
2754 /// It must *not* be zero.
55+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
2856 #[ inline]
29- pub ( crate ) const unsafe fn new_unchecked ( align : usize ) -> Self {
57+ pub const unsafe fn new_unchecked ( align : usize ) -> Self {
3058 // SAFETY: Precondition passed to the caller.
3159 unsafe { assert_unsafe_precondition ! ( ( align: usize ) => align. is_power_of_two( ) ) } ;
3260
3361 // SAFETY: By precondition, this must be a power of two, and
3462 // our variants encompass all possible powers of two.
35- unsafe { mem:: transmute :: < usize , ValidAlign > ( align) }
63+ unsafe { mem:: transmute :: < usize , Alignment > ( align) }
3664 }
3765
66+ /// Returns the alignment as a [`NonZeroUsize`]
67+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
3868 #[ inline]
39- pub ( crate ) const fn as_usize ( self ) -> usize {
69+ pub const fn as_usize ( self ) -> usize {
4070 self . 0 as usize
4171 }
4272
73+ /// Returns the alignment as a [`usize`]
74+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
4375 #[ inline]
44- pub ( crate ) const fn as_nonzero ( self ) -> NonZeroUsize {
76+ pub const fn as_nonzero ( self ) -> NonZeroUsize {
4577 // SAFETY: All the discriminants are non-zero.
4678 unsafe { NonZeroUsize :: new_unchecked ( self . as_usize ( ) ) }
4779 }
4880
49- /// Returns the base 2 logarithm of the alignment.
81+ /// Returns the base- 2 logarithm of the alignment.
5082 ///
5183 /// 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" ) ]
5295 #[ inline]
53- pub ( crate ) fn log2 ( self ) -> u32 {
96+ pub fn log2 ( self ) -> u32 {
5497 self . as_nonzero ( ) . trailing_zeros ( )
5598 }
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- }
6399}
64100
65- impl fmt:: Debug for ValidAlign {
101+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
102+ impl fmt:: Debug for Alignment {
66103 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
67104 write ! ( f, "{:?} (1 << {:?})" , self . as_nonzero( ) , self . log2( ) )
68105 }
69106}
70107
71- impl TryFrom < NonZeroUsize > for ValidAlign {
108+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
109+ impl TryFrom < NonZeroUsize > for Alignment {
72110 type Error = num:: TryFromIntError ;
73111
74112 #[ 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 ( )
82115 }
83116}
84117
85- impl TryFrom < usize > for ValidAlign {
118+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
119+ impl TryFrom < usize > for Alignment {
86120 type Error = num:: TryFromIntError ;
87121
88122 #[ 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 ( ( ) ) )
96125 }
97126}
98127
99- impl cmp:: Eq for ValidAlign { }
128+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
129+ impl cmp:: Eq for Alignment { }
100130
101- impl cmp:: PartialEq for ValidAlign {
131+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
132+ impl cmp:: PartialEq for Alignment {
102133 #[ inline]
103134 fn eq ( & self , other : & Self ) -> bool {
104135 self . as_nonzero ( ) == other. as_nonzero ( )
105136 }
106137}
107138
108- impl cmp:: Ord for ValidAlign {
139+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
140+ impl cmp:: Ord for Alignment {
109141 #[ inline]
110142 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
111143 self . as_nonzero ( ) . cmp ( & other. as_nonzero ( ) )
112144 }
113145}
114146
115- impl cmp:: PartialOrd for ValidAlign {
147+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
148+ impl cmp:: PartialOrd for Alignment {
116149 #[ inline]
117150 fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
118151 Some ( self . cmp ( other) )
119152 }
120153}
121154
122- impl hash:: Hash for ValidAlign {
155+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
156+ impl hash:: Hash for Alignment {
123157 #[ inline]
124158 fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
125159 self . as_nonzero ( ) . hash ( state)
126160 }
127161}
128162
129163#[ cfg( target_pointer_width = "16" ) ]
130- type ValidAlignEnum = ValidAlignEnum16 ;
164+ type AlignmentEnum = AlignmentEnum16 ;
131165#[ cfg( target_pointer_width = "32" ) ]
132- type ValidAlignEnum = ValidAlignEnum32 ;
166+ type AlignmentEnum = AlignmentEnum32 ;
133167#[ cfg( target_pointer_width = "64" ) ]
134- type ValidAlignEnum = ValidAlignEnum64 ;
168+ type AlignmentEnum = AlignmentEnum64 ;
135169
136170#[ derive( Copy , Clone ) ]
137171#[ repr( u16 ) ]
138- enum ValidAlignEnum16 {
172+ enum AlignmentEnum16 {
139173 _Align1Shl0 = 1 << 0 ,
140174 _Align1Shl1 = 1 << 1 ,
141175 _Align1Shl2 = 1 << 2 ,
@@ -156,7 +190,7 @@ enum ValidAlignEnum16 {
156190
157191#[ derive( Copy , Clone ) ]
158192#[ repr( u32 ) ]
159- enum ValidAlignEnum32 {
193+ enum AlignmentEnum32 {
160194 _Align1Shl0 = 1 << 0 ,
161195 _Align1Shl1 = 1 << 1 ,
162196 _Align1Shl2 = 1 << 2 ,
@@ -193,7 +227,7 @@ enum ValidAlignEnum32 {
193227
194228#[ derive( Copy , Clone ) ]
195229#[ repr( u64 ) ]
196- enum ValidAlignEnum64 {
230+ enum AlignmentEnum64 {
197231 _Align1Shl0 = 1 << 0 ,
198232 _Align1Shl1 = 1 << 1 ,
199233 _Align1Shl2 = 1 << 2 ,
0 commit comments