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,178 @@ 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- #[ derive( Copy , Clone ) ]
11+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
12+ #[ derive( Copy , Clone , Eq , PartialEq ) ]
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+ fn _alignment_can_be_structurally_matched ( a : Alignment ) -> bool {
21+ matches ! ( a, Alignment :: MIN )
22+ }
23+
24+ impl Alignment {
25+ /// The smallest possible alignment, 1.
26+ ///
27+ /// All addresses are always aligned at least this much.
28+ ///
29+ /// # Examples
30+ ///
31+ /// ```
32+ /// #![feature(ptr_alignment_type)]
33+ /// use std::ptr::Alignment;
34+ ///
35+ /// assert_eq!(Alignment::MIN.as_usize(), 1);
36+ /// ```
37+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
38+ pub const MIN : Self = Self ( AlignmentEnum :: _Align1Shl0) ;
39+
40+ /// Returns the alignment for a type.
41+ ///
42+ /// This provides the same numerical value as [`mem::align_of`],
43+ /// but in an `Alignment` instead of a `usize.
44+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
45+ #[ inline]
46+ pub const fn of < T > ( ) -> Self {
47+ // SAFETY: rustc ensures that type alignment is always a power of two.
48+ unsafe { Alignment :: new_unchecked ( mem:: align_of :: < T > ( ) ) }
49+ }
50+
51+ /// Creates an `Alignment` from a `usize`, or returns `None` if it's
52+ /// not a power of two.
53+ ///
54+ /// Note that `0` is not a power of two, nor a valid alignment.
55+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
56+ #[ inline]
57+ pub const fn new ( align : usize ) -> Option < Self > {
58+ if align. is_power_of_two ( ) {
59+ // SAFETY: Just checked it only has one bit set
60+ Some ( unsafe { Self :: new_unchecked ( align) } )
61+ } else {
62+ None
63+ }
64+ }
65+
66+ /// Creates an `Alignment` from a power-of-two `usize`.
2167 ///
2268 /// # Safety
2369 ///
2470 /// `align` must be a power of two.
2571 ///
2672 /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
2773 /// It must *not* be zero.
74+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
75+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
2876 #[ inline]
29- pub ( crate ) const unsafe fn new_unchecked ( align : usize ) -> Self {
77+ pub const unsafe fn new_unchecked ( align : usize ) -> Self {
3078 // SAFETY: Precondition passed to the caller.
3179 unsafe { assert_unsafe_precondition ! ( ( align: usize ) => align. is_power_of_two( ) ) } ;
3280
3381 // SAFETY: By precondition, this must be a power of two, and
3482 // our variants encompass all possible powers of two.
35- unsafe { mem:: transmute :: < usize , ValidAlign > ( align) }
83+ unsafe { mem:: transmute :: < usize , Alignment > ( align) }
3684 }
3785
86+ /// Returns the alignment as a [`NonZeroUsize`]
87+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
88+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
3889 #[ inline]
39- pub ( crate ) const fn as_usize ( self ) -> usize {
90+ pub const fn as_usize ( self ) -> usize {
4091 self . 0 as usize
4192 }
4293
94+ /// Returns the alignment as a [`usize`]
95+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
4396 #[ inline]
44- pub ( crate ) const fn as_nonzero ( self ) -> NonZeroUsize {
97+ pub const fn as_nonzero ( self ) -> NonZeroUsize {
4598 // SAFETY: All the discriminants are non-zero.
4699 unsafe { NonZeroUsize :: new_unchecked ( self . as_usize ( ) ) }
47100 }
48101
49- /// Returns the base 2 logarithm of the alignment.
102+ /// Returns the base- 2 logarithm of the alignment.
50103 ///
51104 /// This is always exact, as `self` represents a power of two.
105+ ///
106+ /// # Examples
107+ ///
108+ /// ```
109+ /// #![feature(ptr_alignment_type)]
110+ /// use std::ptr::Alignment;
111+ ///
112+ /// assert_eq!(Alignment::of::<u8>().log2(), 0);
113+ /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
114+ /// ```
115+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
52116 #[ inline]
53- pub ( crate ) fn log2 ( self ) -> u32 {
117+ pub fn log2 ( self ) -> u32 {
54118 self . as_nonzero ( ) . trailing_zeros ( )
55119 }
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- }
63120}
64121
65- impl fmt:: Debug for ValidAlign {
122+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
123+ impl fmt:: Debug for Alignment {
66124 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
67125 write ! ( f, "{:?} (1 << {:?})" , self . as_nonzero( ) , self . log2( ) )
68126 }
69127}
70128
71- impl TryFrom < NonZeroUsize > for ValidAlign {
129+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
130+ impl TryFrom < NonZeroUsize > for Alignment {
72131 type Error = num:: TryFromIntError ;
73132
74133 #[ 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- }
134+ fn try_from ( align : NonZeroUsize ) -> Result < Alignment , Self :: Error > {
135+ align. get ( ) . try_into ( )
82136 }
83137}
84138
85- impl TryFrom < usize > for ValidAlign {
139+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
140+ impl TryFrom < usize > for Alignment {
86141 type Error = num:: TryFromIntError ;
87142
88143 #[ 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- }
96- }
97- }
98-
99- impl cmp:: Eq for ValidAlign { }
100-
101- impl cmp:: PartialEq for ValidAlign {
102- #[ inline]
103- fn eq ( & self , other : & Self ) -> bool {
104- self . as_nonzero ( ) == other. as_nonzero ( )
144+ fn try_from ( align : usize ) -> Result < Alignment , Self :: Error > {
145+ Self :: new ( align) . ok_or ( num:: TryFromIntError ( ( ) ) )
105146 }
106147}
107148
108- impl cmp:: Ord for ValidAlign {
149+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
150+ impl cmp:: Ord for Alignment {
109151 #[ inline]
110152 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
111153 self . as_nonzero ( ) . cmp ( & other. as_nonzero ( ) )
112154 }
113155}
114156
115- impl cmp:: PartialOrd for ValidAlign {
157+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
158+ impl cmp:: PartialOrd for Alignment {
116159 #[ inline]
117160 fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
118161 Some ( self . cmp ( other) )
119162 }
120163}
121164
122- impl hash:: Hash for ValidAlign {
165+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
166+ impl hash:: Hash for Alignment {
123167 #[ inline]
124168 fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
125169 self . as_nonzero ( ) . hash ( state)
126170 }
127171}
128172
129173#[ cfg( target_pointer_width = "16" ) ]
130- type ValidAlignEnum = ValidAlignEnum16 ;
174+ type AlignmentEnum = AlignmentEnum16 ;
131175#[ cfg( target_pointer_width = "32" ) ]
132- type ValidAlignEnum = ValidAlignEnum32 ;
176+ type AlignmentEnum = AlignmentEnum32 ;
133177#[ cfg( target_pointer_width = "64" ) ]
134- type ValidAlignEnum = ValidAlignEnum64 ;
178+ type AlignmentEnum = AlignmentEnum64 ;
135179
136- #[ derive( Copy , Clone ) ]
180+ #[ derive( Copy , Clone , Eq , PartialEq ) ]
137181#[ repr( u16 ) ]
138- enum ValidAlignEnum16 {
182+ enum AlignmentEnum16 {
139183 _Align1Shl0 = 1 << 0 ,
140184 _Align1Shl1 = 1 << 1 ,
141185 _Align1Shl2 = 1 << 2 ,
@@ -154,9 +198,9 @@ enum ValidAlignEnum16 {
154198 _Align1Shl15 = 1 << 15 ,
155199}
156200
157- #[ derive( Copy , Clone ) ]
201+ #[ derive( Copy , Clone , Eq , PartialEq ) ]
158202#[ repr( u32 ) ]
159- enum ValidAlignEnum32 {
203+ enum AlignmentEnum32 {
160204 _Align1Shl0 = 1 << 0 ,
161205 _Align1Shl1 = 1 << 1 ,
162206 _Align1Shl2 = 1 << 2 ,
@@ -191,9 +235,9 @@ enum ValidAlignEnum32 {
191235 _Align1Shl31 = 1 << 31 ,
192236}
193237
194- #[ derive( Copy , Clone ) ]
238+ #[ derive( Copy , Clone , Eq , PartialEq ) ]
195239#[ repr( u64 ) ]
196- enum ValidAlignEnum64 {
240+ enum AlignmentEnum64 {
197241 _Align1Shl0 = 1 << 0 ,
198242 _Align1Shl1 = 1 << 1 ,
199243 _Align1Shl2 = 1 << 2 ,
0 commit comments