Skip to content

Commit 585bcc6

Browse files
committed
Add ptr::Alignment type
Essentially no new code here, just exposing the previously-`pub(crate)` `ValidAlign` type under the name from the ACP.
1 parent c773c13 commit 585bcc6

File tree

3 files changed

+90
-53
lines changed

3 files changed

+90
-53
lines changed

library/core/src/mem/mod.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ mod maybe_uninit;
2121
#[stable(feature = "maybe_uninit", since = "1.36.0")]
2222
pub use maybe_uninit::MaybeUninit;
2323

24-
mod valid_align;
25-
// For now this type is left crate-local. It could potentially make sense to expose
26-
// it publicly, as it would be a nice parameter type for methods which need to take
27-
// alignment as a parameter, such as `Layout::padding_needed_for`.
28-
pub(crate) use valid_align::ValidAlign;
24+
// FIXME: This is left here for now to avoid complications around pending reverts.
25+
// Once <https://github.com/rust-lang/rust/issues/101899> is fully resolved,
26+
// this should be removed and the references in `alloc::Layout` updated.
27+
pub(crate) use ptr::Alignment as ValidAlign;
2928

3029
mod transmutability;
3130
#[unstable(feature = "transmutability", issue = "99571")]

library/core/src/mem/valid_align.rs renamed to library/core/src/ptr/alignment.rs

+82-48
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::convert::TryFrom;
1+
use crate::convert::{TryFrom, TryInto};
22
use crate::intrinsics::assert_unsafe_precondition;
33
use crate::num::NonZeroUsize;
44
use 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,

library/core/src/ptr/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ use crate::intrinsics::{
377377

378378
use crate::mem::{self, MaybeUninit};
379379

380+
mod alignment;
381+
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
382+
pub use alignment::Alignment;
383+
380384
#[stable(feature = "rust1", since = "1.0.0")]
381385
#[doc(inline)]
382386
pub use crate::intrinsics::copy_nonoverlapping;

0 commit comments

Comments
 (0)