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