about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2022-09-20 14:20:21 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2022-09-20 14:20:21 -0700
commit585bcc69807b3730e3de11c5dbceccbab12e874d (patch)
tree5d12b949c0311b7c41d28a8b5e0d858a237739fa /library/core/src
parentc773c134c949661874d76313280e76cc3dd60975 (diff)
downloadrust-585bcc69807b3730e3de11c5dbceccbab12e874d.tar.gz
rust-585bcc69807b3730e3de11c5dbceccbab12e874d.zip
Add `ptr::Alignment` type
Essentially no new code here, just exposing the previously-`pub(crate)` `ValidAlign` type under the name from the ACP.
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/mem/mod.rs9
-rw-r--r--library/core/src/ptr/alignment.rs (renamed from library/core/src/mem/valid_align.rs)130
-rw-r--r--library/core/src/ptr/mod.rs4
3 files changed, 90 insertions, 53 deletions
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index d2dd2941d59..3ccab15a365 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -21,11 +21,10 @@ mod maybe_uninit;
 #[stable(feature = "maybe_uninit", since = "1.36.0")]
 pub use maybe_uninit::MaybeUninit;
 
-mod valid_align;
-// For now this type is left crate-local.  It could potentially make sense to expose
-// it publicly, as it would be a nice parameter type for methods which need to take
-// alignment as a parameter, such as `Layout::padding_needed_for`.
-pub(crate) use valid_align::ValidAlign;
+// FIXME: This is left here for now to avoid complications around pending reverts.
+// Once <https://github.com/rust-lang/rust/issues/101899> is fully resolved,
+// this should be removed and the references in `alloc::Layout` updated.
+pub(crate) use ptr::Alignment as ValidAlign;
 
 mod transmutability;
 #[unstable(feature = "transmutability", issue = "99571")]
diff --git a/library/core/src/mem/valid_align.rs b/library/core/src/ptr/alignment.rs
index 32b2afb72b0..5e7628c5a18 100644
--- a/library/core/src/mem/valid_align.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -1,4 +1,4 @@
-use crate::convert::TryFrom;
+use crate::convert::{TryFrom, TryInto};
 use crate::intrinsics::assert_unsafe_precondition;
 use crate::num::NonZeroUsize;
 use crate::{cmp, fmt, hash, mem, num};
@@ -8,16 +8,43 @@ use crate::{cmp, fmt, hash, mem, num};
 ///
 /// Note that particularly large alignments, while representable in this type,
 /// are likely not to be supported by actual allocators and linkers.
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-pub(crate) struct ValidAlign(ValidAlignEnum);
+pub struct Alignment(AlignmentEnum);
 
-// ValidAlign is `repr(usize)`, but via extra steps.
-const _: () = assert!(mem::size_of::<ValidAlign>() == mem::size_of::<usize>());
-const _: () = assert!(mem::align_of::<ValidAlign>() == mem::align_of::<usize>());
+// Alignment is `repr(usize)`, but via extra steps.
+const _: () = assert!(mem::size_of::<Alignment>() == mem::size_of::<usize>());
+const _: () = assert!(mem::align_of::<Alignment>() == mem::align_of::<usize>());
 
-impl ValidAlign {
-    /// Creates a `ValidAlign` from a power-of-two `usize`.
+impl Alignment {
+    /// Returns the alignment for a type.
+    ///
+    /// This provides the same numerical value as [`mem::align_of`],
+    /// but in an `Alignment` instead of a `usize.
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+    #[inline]
+    pub(crate) fn of<T>() -> Self {
+        // SAFETY: rustc ensures that type alignment is always a power of two.
+        unsafe { Alignment::new_unchecked(mem::align_of::<T>()) }
+    }
+
+    /// Creates an `Alignment` from a `usize`, or returns `None` if it's
+    /// not a power of two.
+    ///
+    /// Note that `0` is not a power of two, nor a valid alignment.
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+    #[inline]
+    pub const fn new(align: usize) -> Option<Self> {
+        if align.is_power_of_two() {
+            // SAFETY: Just checked it only has one bit set
+            Some(unsafe { Self::new_unchecked(align) })
+        } else {
+            None
+        }
+    }
+
+    /// Creates an `Alignment` from a power-of-two `usize`.
     ///
     /// # Safety
     ///
@@ -25,101 +52,108 @@ impl ValidAlign {
     ///
     /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
     /// It must *not* be zero.
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
-    pub(crate) const unsafe fn new_unchecked(align: usize) -> Self {
+    pub const unsafe fn new_unchecked(align: usize) -> Self {
         // SAFETY: Precondition passed to the caller.
         unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
 
         // SAFETY: By precondition, this must be a power of two, and
         // our variants encompass all possible powers of two.
-        unsafe { mem::transmute::<usize, ValidAlign>(align) }
+        unsafe { mem::transmute::<usize, Alignment>(align) }
     }
 
+    /// Returns the alignment as a [`NonZeroUsize`]
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
-    pub(crate) const fn as_usize(self) -> usize {
+    pub const fn as_usize(self) -> usize {
         self.0 as usize
     }
 
+    /// Returns the alignment as a [`usize`]
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
-    pub(crate) const fn as_nonzero(self) -> NonZeroUsize {
+    pub const fn as_nonzero(self) -> NonZeroUsize {
         // SAFETY: All the discriminants are non-zero.
         unsafe { NonZeroUsize::new_unchecked(self.as_usize()) }
     }
 
-    /// Returns the base 2 logarithm of the alignment.
+    /// Returns the base-2 logarithm of the alignment.
     ///
     /// This is always exact, as `self` represents a power of two.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ptr_alignment_type)]
+    /// use std::ptr::Alignment;
+    ///
+    /// assert_eq!(Alignment::of::<u8>().log2(), 0);
+    /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
+    /// ```
+    #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
-    pub(crate) fn log2(self) -> u32 {
+    pub fn log2(self) -> u32 {
         self.as_nonzero().trailing_zeros()
     }
-
-    /// Returns the alignment for a type.
-    #[inline]
-    pub(crate) fn of<T>() -> Self {
-        // SAFETY: rustc ensures that type alignment is always a power of two.
-        unsafe { ValidAlign::new_unchecked(mem::align_of::<T>()) }
-    }
 }
 
-impl fmt::Debug for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl fmt::Debug for Alignment {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
     }
 }
 
-impl TryFrom<NonZeroUsize> for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl TryFrom<NonZeroUsize> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
-    fn try_from(align: NonZeroUsize) -> Result<ValidAlign, Self::Error> {
-        if align.is_power_of_two() {
-            // SAFETY: Just checked for power-of-two
-            unsafe { Ok(ValidAlign::new_unchecked(align.get())) }
-        } else {
-            Err(num::TryFromIntError(()))
-        }
+    fn try_from(align: NonZeroUsize) -> Result<Alignment, Self::Error> {
+        align.get().try_into()
     }
 }
 
-impl TryFrom<usize> for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl TryFrom<usize> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
-    fn try_from(align: usize) -> Result<ValidAlign, Self::Error> {
-        if align.is_power_of_two() {
-            // SAFETY: Just checked for power-of-two
-            unsafe { Ok(ValidAlign::new_unchecked(align)) }
-        } else {
-            Err(num::TryFromIntError(()))
-        }
+    fn try_from(align: usize) -> Result<Alignment, Self::Error> {
+        Self::new(align).ok_or(num::TryFromIntError(()))
     }
 }
 
-impl cmp::Eq for ValidAlign {}
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::Eq for Alignment {}
 
-impl cmp::PartialEq for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::PartialEq for Alignment {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
         self.as_nonzero() == other.as_nonzero()
     }
 }
 
-impl cmp::Ord for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::Ord for Alignment {
     #[inline]
     fn cmp(&self, other: &Self) -> cmp::Ordering {
         self.as_nonzero().cmp(&other.as_nonzero())
     }
 }
 
-impl cmp::PartialOrd for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::PartialOrd for Alignment {
     #[inline]
     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
         Some(self.cmp(other))
     }
 }
 
-impl hash::Hash for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl hash::Hash for Alignment {
     #[inline]
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         self.as_nonzero().hash(state)
@@ -127,15 +161,15 @@ impl hash::Hash for ValidAlign {
 }
 
 #[cfg(target_pointer_width = "16")]
-type ValidAlignEnum = ValidAlignEnum16;
+type AlignmentEnum = AlignmentEnum16;
 #[cfg(target_pointer_width = "32")]
-type ValidAlignEnum = ValidAlignEnum32;
+type AlignmentEnum = AlignmentEnum32;
 #[cfg(target_pointer_width = "64")]
-type ValidAlignEnum = ValidAlignEnum64;
+type AlignmentEnum = AlignmentEnum64;
 
 #[derive(Copy, Clone)]
 #[repr(u16)]
-enum ValidAlignEnum16 {
+enum AlignmentEnum16 {
     _Align1Shl0 = 1 << 0,
     _Align1Shl1 = 1 << 1,
     _Align1Shl2 = 1 << 2,
@@ -156,7 +190,7 @@ enum ValidAlignEnum16 {
 
 #[derive(Copy, Clone)]
 #[repr(u32)]
-enum ValidAlignEnum32 {
+enum AlignmentEnum32 {
     _Align1Shl0 = 1 << 0,
     _Align1Shl1 = 1 << 1,
     _Align1Shl2 = 1 << 2,
@@ -193,7 +227,7 @@ enum ValidAlignEnum32 {
 
 #[derive(Copy, Clone)]
 #[repr(u64)]
-enum ValidAlignEnum64 {
+enum AlignmentEnum64 {
     _Align1Shl0 = 1 << 0,
     _Align1Shl1 = 1 << 1,
     _Align1Shl2 = 1 << 2,
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index e976abed774..8f94335b401 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -377,6 +377,10 @@ use crate::intrinsics::{
 
 use crate::mem::{self, MaybeUninit};
 
+mod alignment;
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+pub use alignment::Alignment;
+
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(inline)]
 pub use crate::intrinsics::copy_nonoverlapping;