]>
Commit | Line | Data |
---|---|---|
2b03887a | 1 | use crate::convert::{TryFrom, TryInto}; |
f2b60f7d | 2 | use crate::intrinsics::assert_unsafe_precondition; |
04454e1e | 3 | use crate::num::NonZeroUsize; |
923072b8 | 4 | use crate::{cmp, fmt, hash, mem, num}; |
04454e1e FG |
5 | |
6 | /// A type storing a `usize` which is a power of two, and thus | |
7 | /// represents a possible alignment in the rust abstract machine. | |
8 | /// | |
9 | /// Note that particularly large alignments, while representable in this type, | |
10 | /// are likely not to be supported by actual allocators and linkers. | |
2b03887a | 11 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
487cf647 FG |
12 | #[derive(Copy, Clone, Eq)] |
13 | #[cfg_attr(bootstrap, derive(PartialEq))] | |
14 | #[cfg_attr(not(bootstrap), derive_const(PartialEq))] | |
04454e1e | 15 | #[repr(transparent)] |
2b03887a | 16 | pub struct Alignment(AlignmentEnum); |
04454e1e | 17 | |
2b03887a FG |
18 | // Alignment is `repr(usize)`, but via extra steps. |
19 | const _: () = assert!(mem::size_of::<Alignment>() == mem::size_of::<usize>()); | |
20 | const _: () = assert!(mem::align_of::<Alignment>() == mem::align_of::<usize>()); | |
04454e1e | 21 | |
2b03887a FG |
22 | fn _alignment_can_be_structurally_matched(a: Alignment) -> bool { |
23 | matches!(a, Alignment::MIN) | |
24 | } | |
25 | ||
26 | impl Alignment { | |
27 | /// The smallest possible alignment, 1. | |
28 | /// | |
29 | /// All addresses are always aligned at least this much. | |
30 | /// | |
31 | /// # Examples | |
32 | /// | |
33 | /// ``` | |
34 | /// #![feature(ptr_alignment_type)] | |
35 | /// use std::ptr::Alignment; | |
36 | /// | |
37 | /// assert_eq!(Alignment::MIN.as_usize(), 1); | |
38 | /// ``` | |
39 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
40 | pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0); | |
41 | ||
42 | /// Returns the alignment for a type. | |
43 | /// | |
44 | /// This provides the same numerical value as [`mem::align_of`], | |
45 | /// but in an `Alignment` instead of a `usize. | |
46 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
47 | #[inline] | |
48 | pub const fn of<T>() -> Self { | |
49 | // SAFETY: rustc ensures that type alignment is always a power of two. | |
50 | unsafe { Alignment::new_unchecked(mem::align_of::<T>()) } | |
51 | } | |
52 | ||
53 | /// Creates an `Alignment` from a `usize`, or returns `None` if it's | |
54 | /// not a power of two. | |
55 | /// | |
56 | /// Note that `0` is not a power of two, nor a valid alignment. | |
57 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
58 | #[inline] | |
59 | pub const fn new(align: usize) -> Option<Self> { | |
60 | if align.is_power_of_two() { | |
61 | // SAFETY: Just checked it only has one bit set | |
62 | Some(unsafe { Self::new_unchecked(align) }) | |
63 | } else { | |
64 | None | |
65 | } | |
66 | } | |
67 | ||
68 | /// Creates an `Alignment` from a power-of-two `usize`. | |
04454e1e FG |
69 | /// |
70 | /// # Safety | |
71 | /// | |
72 | /// `align` must be a power of two. | |
73 | /// | |
74 | /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. | |
75 | /// It must *not* be zero. | |
2b03887a FG |
76 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
77 | #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] | |
04454e1e | 78 | #[inline] |
2b03887a | 79 | pub const unsafe fn new_unchecked(align: usize) -> Self { |
f2b60f7d | 80 | // SAFETY: Precondition passed to the caller. |
2b03887a FG |
81 | unsafe { |
82 | assert_unsafe_precondition!( | |
83 | "Alignment::new_unchecked requires a power of two", | |
84 | (align: usize) => align.is_power_of_two() | |
85 | ) | |
86 | }; | |
04454e1e FG |
87 | |
88 | // SAFETY: By precondition, this must be a power of two, and | |
89 | // our variants encompass all possible powers of two. | |
2b03887a | 90 | unsafe { mem::transmute::<usize, Alignment>(align) } |
04454e1e FG |
91 | } |
92 | ||
2b03887a FG |
93 | /// Returns the alignment as a [`usize`] |
94 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
95 | #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] | |
f2b60f7d | 96 | #[inline] |
2b03887a | 97 | pub const fn as_usize(self) -> usize { |
f2b60f7d FG |
98 | self.0 as usize |
99 | } | |
100 | ||
2b03887a FG |
101 | /// Returns the alignment as a [`NonZeroUsize`] |
102 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
04454e1e | 103 | #[inline] |
2b03887a | 104 | pub const fn as_nonzero(self) -> NonZeroUsize { |
04454e1e | 105 | // SAFETY: All the discriminants are non-zero. |
f2b60f7d | 106 | unsafe { NonZeroUsize::new_unchecked(self.as_usize()) } |
04454e1e FG |
107 | } |
108 | ||
2b03887a | 109 | /// Returns the base-2 logarithm of the alignment. |
04454e1e FG |
110 | /// |
111 | /// This is always exact, as `self` represents a power of two. | |
2b03887a FG |
112 | /// |
113 | /// # Examples | |
114 | /// | |
115 | /// ``` | |
116 | /// #![feature(ptr_alignment_type)] | |
117 | /// use std::ptr::Alignment; | |
118 | /// | |
119 | /// assert_eq!(Alignment::of::<u8>().log2(), 0); | |
120 | /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); | |
121 | /// ``` | |
122 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] | |
04454e1e | 123 | #[inline] |
2b03887a | 124 | pub fn log2(self) -> u32 { |
04454e1e FG |
125 | self.as_nonzero().trailing_zeros() |
126 | } | |
127 | } | |
128 | ||
2b03887a FG |
129 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
130 | impl fmt::Debug for Alignment { | |
04454e1e FG |
131 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
132 | write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2()) | |
133 | } | |
134 | } | |
135 | ||
2b03887a FG |
136 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
137 | impl TryFrom<NonZeroUsize> for Alignment { | |
04454e1e FG |
138 | type Error = num::TryFromIntError; |
139 | ||
140 | #[inline] | |
2b03887a FG |
141 | fn try_from(align: NonZeroUsize) -> Result<Alignment, Self::Error> { |
142 | align.get().try_into() | |
04454e1e FG |
143 | } |
144 | } | |
145 | ||
2b03887a FG |
146 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
147 | impl TryFrom<usize> for Alignment { | |
04454e1e FG |
148 | type Error = num::TryFromIntError; |
149 | ||
150 | #[inline] | |
2b03887a FG |
151 | fn try_from(align: usize) -> Result<Alignment, Self::Error> { |
152 | Self::new(align).ok_or(num::TryFromIntError(())) | |
04454e1e FG |
153 | } |
154 | } | |
155 | ||
2b03887a FG |
156 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
157 | impl From<Alignment> for NonZeroUsize { | |
158 | #[inline] | |
159 | fn from(align: Alignment) -> NonZeroUsize { | |
160 | align.as_nonzero() | |
161 | } | |
162 | } | |
04454e1e | 163 | |
2b03887a FG |
164 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
165 | impl From<Alignment> for usize { | |
04454e1e | 166 | #[inline] |
2b03887a FG |
167 | fn from(align: Alignment) -> usize { |
168 | align.as_usize() | |
04454e1e FG |
169 | } |
170 | } | |
171 | ||
487cf647 | 172 | #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] |
2b03887a | 173 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
487cf647 | 174 | impl const cmp::Ord for Alignment { |
04454e1e FG |
175 | #[inline] |
176 | fn cmp(&self, other: &Self) -> cmp::Ordering { | |
487cf647 | 177 | self.as_nonzero().get().cmp(&other.as_nonzero().get()) |
04454e1e FG |
178 | } |
179 | } | |
180 | ||
487cf647 | 181 | #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] |
2b03887a | 182 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
487cf647 | 183 | impl const cmp::PartialOrd for Alignment { |
04454e1e FG |
184 | #[inline] |
185 | fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { | |
186 | Some(self.cmp(other)) | |
187 | } | |
188 | } | |
189 | ||
2b03887a FG |
190 | #[unstable(feature = "ptr_alignment_type", issue = "102070")] |
191 | impl hash::Hash for Alignment { | |
923072b8 FG |
192 | #[inline] |
193 | fn hash<H: hash::Hasher>(&self, state: &mut H) { | |
194 | self.as_nonzero().hash(state) | |
195 | } | |
196 | } | |
197 | ||
04454e1e | 198 | #[cfg(target_pointer_width = "16")] |
2b03887a | 199 | type AlignmentEnum = AlignmentEnum16; |
04454e1e | 200 | #[cfg(target_pointer_width = "32")] |
2b03887a | 201 | type AlignmentEnum = AlignmentEnum32; |
04454e1e | 202 | #[cfg(target_pointer_width = "64")] |
2b03887a | 203 | type AlignmentEnum = AlignmentEnum64; |
04454e1e | 204 | |
487cf647 FG |
205 | #[derive(Copy, Clone, Eq)] |
206 | #[cfg_attr(bootstrap, derive(PartialEq))] | |
207 | #[cfg_attr(not(bootstrap), derive_const(PartialEq))] | |
04454e1e | 208 | #[repr(u16)] |
2b03887a | 209 | enum AlignmentEnum16 { |
04454e1e FG |
210 | _Align1Shl0 = 1 << 0, |
211 | _Align1Shl1 = 1 << 1, | |
212 | _Align1Shl2 = 1 << 2, | |
213 | _Align1Shl3 = 1 << 3, | |
214 | _Align1Shl4 = 1 << 4, | |
215 | _Align1Shl5 = 1 << 5, | |
216 | _Align1Shl6 = 1 << 6, | |
217 | _Align1Shl7 = 1 << 7, | |
218 | _Align1Shl8 = 1 << 8, | |
219 | _Align1Shl9 = 1 << 9, | |
220 | _Align1Shl10 = 1 << 10, | |
221 | _Align1Shl11 = 1 << 11, | |
222 | _Align1Shl12 = 1 << 12, | |
223 | _Align1Shl13 = 1 << 13, | |
224 | _Align1Shl14 = 1 << 14, | |
225 | _Align1Shl15 = 1 << 15, | |
226 | } | |
227 | ||
487cf647 FG |
228 | #[derive(Copy, Clone, Eq)] |
229 | #[cfg_attr(bootstrap, derive(PartialEq))] | |
230 | #[cfg_attr(not(bootstrap), derive_const(PartialEq))] | |
04454e1e | 231 | #[repr(u32)] |
2b03887a | 232 | enum AlignmentEnum32 { |
04454e1e FG |
233 | _Align1Shl0 = 1 << 0, |
234 | _Align1Shl1 = 1 << 1, | |
235 | _Align1Shl2 = 1 << 2, | |
236 | _Align1Shl3 = 1 << 3, | |
237 | _Align1Shl4 = 1 << 4, | |
238 | _Align1Shl5 = 1 << 5, | |
239 | _Align1Shl6 = 1 << 6, | |
240 | _Align1Shl7 = 1 << 7, | |
241 | _Align1Shl8 = 1 << 8, | |
242 | _Align1Shl9 = 1 << 9, | |
243 | _Align1Shl10 = 1 << 10, | |
244 | _Align1Shl11 = 1 << 11, | |
245 | _Align1Shl12 = 1 << 12, | |
246 | _Align1Shl13 = 1 << 13, | |
247 | _Align1Shl14 = 1 << 14, | |
248 | _Align1Shl15 = 1 << 15, | |
249 | _Align1Shl16 = 1 << 16, | |
250 | _Align1Shl17 = 1 << 17, | |
251 | _Align1Shl18 = 1 << 18, | |
252 | _Align1Shl19 = 1 << 19, | |
253 | _Align1Shl20 = 1 << 20, | |
254 | _Align1Shl21 = 1 << 21, | |
255 | _Align1Shl22 = 1 << 22, | |
256 | _Align1Shl23 = 1 << 23, | |
257 | _Align1Shl24 = 1 << 24, | |
258 | _Align1Shl25 = 1 << 25, | |
259 | _Align1Shl26 = 1 << 26, | |
260 | _Align1Shl27 = 1 << 27, | |
261 | _Align1Shl28 = 1 << 28, | |
262 | _Align1Shl29 = 1 << 29, | |
263 | _Align1Shl30 = 1 << 30, | |
264 | _Align1Shl31 = 1 << 31, | |
265 | } | |
266 | ||
487cf647 FG |
267 | #[derive(Copy, Clone, Eq)] |
268 | #[cfg_attr(bootstrap, derive(PartialEq))] | |
269 | #[cfg_attr(not(bootstrap), derive_const(PartialEq))] | |
04454e1e | 270 | #[repr(u64)] |
2b03887a | 271 | enum AlignmentEnum64 { |
04454e1e FG |
272 | _Align1Shl0 = 1 << 0, |
273 | _Align1Shl1 = 1 << 1, | |
274 | _Align1Shl2 = 1 << 2, | |
275 | _Align1Shl3 = 1 << 3, | |
276 | _Align1Shl4 = 1 << 4, | |
277 | _Align1Shl5 = 1 << 5, | |
278 | _Align1Shl6 = 1 << 6, | |
279 | _Align1Shl7 = 1 << 7, | |
280 | _Align1Shl8 = 1 << 8, | |
281 | _Align1Shl9 = 1 << 9, | |
282 | _Align1Shl10 = 1 << 10, | |
283 | _Align1Shl11 = 1 << 11, | |
284 | _Align1Shl12 = 1 << 12, | |
285 | _Align1Shl13 = 1 << 13, | |
286 | _Align1Shl14 = 1 << 14, | |
287 | _Align1Shl15 = 1 << 15, | |
288 | _Align1Shl16 = 1 << 16, | |
289 | _Align1Shl17 = 1 << 17, | |
290 | _Align1Shl18 = 1 << 18, | |
291 | _Align1Shl19 = 1 << 19, | |
292 | _Align1Shl20 = 1 << 20, | |
293 | _Align1Shl21 = 1 << 21, | |
294 | _Align1Shl22 = 1 << 22, | |
295 | _Align1Shl23 = 1 << 23, | |
296 | _Align1Shl24 = 1 << 24, | |
297 | _Align1Shl25 = 1 << 25, | |
298 | _Align1Shl26 = 1 << 26, | |
299 | _Align1Shl27 = 1 << 27, | |
300 | _Align1Shl28 = 1 << 28, | |
301 | _Align1Shl29 = 1 << 29, | |
302 | _Align1Shl30 = 1 << 30, | |
303 | _Align1Shl31 = 1 << 31, | |
304 | _Align1Shl32 = 1 << 32, | |
305 | _Align1Shl33 = 1 << 33, | |
306 | _Align1Shl34 = 1 << 34, | |
307 | _Align1Shl35 = 1 << 35, | |
308 | _Align1Shl36 = 1 << 36, | |
309 | _Align1Shl37 = 1 << 37, | |
310 | _Align1Shl38 = 1 << 38, | |
311 | _Align1Shl39 = 1 << 39, | |
312 | _Align1Shl40 = 1 << 40, | |
313 | _Align1Shl41 = 1 << 41, | |
314 | _Align1Shl42 = 1 << 42, | |
315 | _Align1Shl43 = 1 << 43, | |
316 | _Align1Shl44 = 1 << 44, | |
317 | _Align1Shl45 = 1 << 45, | |
318 | _Align1Shl46 = 1 << 46, | |
319 | _Align1Shl47 = 1 << 47, | |
320 | _Align1Shl48 = 1 << 48, | |
321 | _Align1Shl49 = 1 << 49, | |
322 | _Align1Shl50 = 1 << 50, | |
323 | _Align1Shl51 = 1 << 51, | |
324 | _Align1Shl52 = 1 << 52, | |
325 | _Align1Shl53 = 1 << 53, | |
326 | _Align1Shl54 = 1 << 54, | |
327 | _Align1Shl55 = 1 << 55, | |
328 | _Align1Shl56 = 1 << 56, | |
329 | _Align1Shl57 = 1 << 57, | |
330 | _Align1Shl58 = 1 << 58, | |
331 | _Align1Shl59 = 1 << 59, | |
332 | _Align1Shl60 = 1 << 60, | |
333 | _Align1Shl61 = 1 << 61, | |
334 | _Align1Shl62 = 1 << 62, | |
335 | _Align1Shl63 = 1 << 63, | |
336 | } |