Rollup merge of #102072 - scottmcm:ptr-alignment-type, r=thomcc
Add `ptr::Alignment` type Essentially no new code here, just exposing the previously-`pub(crate)` `ValidAlign` type under the name from the ACP. ACP: https://github.com/rust-lang/libs-team/issues/108 Tracking Issue: https://github.com/rust-lang/rust/issues/102070 r? ``@ghost``
This commit is contained in:
commit
38db483af7
@ -64,6 +64,7 @@ impl Layout {
|
|||||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||||
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
||||||
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
||||||
if !align.is_power_of_two() {
|
if !align.is_power_of_two() {
|
||||||
return Err(LayoutError);
|
return Err(LayoutError);
|
||||||
@ -113,6 +114,7 @@ impl Layout {
|
|||||||
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
|
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
||||||
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
||||||
// SAFETY: the caller is required to uphold the preconditions.
|
// SAFETY: the caller is required to uphold the preconditions.
|
||||||
unsafe { Layout { size, align: ValidAlign::new_unchecked(align) } }
|
unsafe { Layout { size, align: ValidAlign::new_unchecked(align) } }
|
||||||
@ -133,6 +135,7 @@ impl Layout {
|
|||||||
#[must_use = "this returns the minimum alignment, \
|
#[must_use = "this returns the minimum alignment, \
|
||||||
without modifying the layout"]
|
without modifying the layout"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
||||||
pub const fn align(&self) -> usize {
|
pub const fn align(&self) -> usize {
|
||||||
self.align.as_usize()
|
self.align.as_usize()
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,7 @@
|
|||||||
#![feature(core_panic)]
|
#![feature(core_panic)]
|
||||||
#![feature(duration_consts_float)]
|
#![feature(duration_consts_float)]
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
|
#![feature(ptr_alignment_type)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(slice_split_at_unchecked)]
|
#![feature(slice_split_at_unchecked)]
|
||||||
|
@ -21,11 +21,10 @@ mod maybe_uninit;
|
|||||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||||
pub use maybe_uninit::MaybeUninit;
|
pub use maybe_uninit::MaybeUninit;
|
||||||
|
|
||||||
mod valid_align;
|
// FIXME: This is left here for now to avoid complications around pending reverts.
|
||||||
// For now this type is left crate-local. It could potentially make sense to expose
|
// Once <https://github.com/rust-lang/rust/issues/101899> is fully resolved,
|
||||||
// it publicly, as it would be a nice parameter type for methods which need to take
|
// this should be removed and the references in `alloc::Layout` updated.
|
||||||
// alignment as a parameter, such as `Layout::padding_needed_for`.
|
pub(crate) use ptr::Alignment as ValidAlign;
|
||||||
pub(crate) use valid_align::ValidAlign;
|
|
||||||
|
|
||||||
mod transmutability;
|
mod transmutability;
|
||||||
#[unstable(feature = "transmutability", issue = "99571")]
|
#[unstable(feature = "transmutability", issue = "99571")]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::convert::TryFrom;
|
use crate::convert::{TryFrom, TryInto};
|
||||||
use crate::intrinsics::assert_unsafe_precondition;
|
use crate::intrinsics::assert_unsafe_precondition;
|
||||||
use crate::num::NonZeroUsize;
|
use crate::num::NonZeroUsize;
|
||||||
use crate::{cmp, fmt, hash, mem, num};
|
use crate::{cmp, fmt, hash, mem, num};
|
||||||
@ -8,16 +8,62 @@ use crate::{cmp, fmt, hash, mem, num};
|
|||||||
///
|
///
|
||||||
/// Note that particularly large alignments, while representable in this type,
|
/// Note that particularly large alignments, while representable in this type,
|
||||||
/// are likely not to be supported by actual allocators and linkers.
|
/// are likely not to be supported by actual allocators and linkers.
|
||||||
#[derive(Copy, Clone)]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub(crate) struct ValidAlign(ValidAlignEnum);
|
pub struct Alignment(AlignmentEnum);
|
||||||
|
|
||||||
// ValidAlign is `repr(usize)`, but via extra steps.
|
// Alignment is `repr(usize)`, but via extra steps.
|
||||||
const _: () = assert!(mem::size_of::<ValidAlign>() == mem::size_of::<usize>());
|
const _: () = assert!(mem::size_of::<Alignment>() == mem::size_of::<usize>());
|
||||||
const _: () = assert!(mem::align_of::<ValidAlign>() == mem::align_of::<usize>());
|
const _: () = assert!(mem::align_of::<Alignment>() == mem::align_of::<usize>());
|
||||||
|
|
||||||
impl ValidAlign {
|
fn _alignment_can_be_structurally_matched(a: Alignment) -> bool {
|
||||||
/// Creates a `ValidAlign` from a power-of-two `usize`.
|
matches!(a, Alignment::MIN)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Alignment {
|
||||||
|
/// The smallest possible alignment, 1.
|
||||||
|
///
|
||||||
|
/// All addresses are always aligned at least this much.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ptr_alignment_type)]
|
||||||
|
/// use std::ptr::Alignment;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Alignment::MIN.as_usize(), 1);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
|
||||||
|
|
||||||
|
/// 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 const 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
@ -25,101 +71,99 @@ impl ValidAlign {
|
|||||||
///
|
///
|
||||||
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
|
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
|
||||||
/// It must *not* be zero.
|
/// It must *not* be zero.
|
||||||
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[inline]
|
#[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.
|
// SAFETY: Precondition passed to the caller.
|
||||||
unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
|
unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
|
||||||
|
|
||||||
// SAFETY: By precondition, this must be a power of two, and
|
// SAFETY: By precondition, this must be a power of two, and
|
||||||
// our variants encompass all possible powers of two.
|
// 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")]
|
||||||
|
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) const fn as_usize(self) -> usize {
|
pub const fn as_usize(self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the alignment as a [`usize`]
|
||||||
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) const fn as_nonzero(self) -> NonZeroUsize {
|
pub const fn as_nonzero(self) -> NonZeroUsize {
|
||||||
// SAFETY: All the discriminants are non-zero.
|
// SAFETY: All the discriminants are non-zero.
|
||||||
unsafe { NonZeroUsize::new_unchecked(self.as_usize()) }
|
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.
|
/// 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]
|
#[inline]
|
||||||
pub(crate) fn log2(self) -> u32 {
|
pub fn log2(self) -> u32 {
|
||||||
self.as_nonzero().trailing_zeros()
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
|
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;
|
type Error = num::TryFromIntError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_from(align: NonZeroUsize) -> Result<ValidAlign, Self::Error> {
|
fn try_from(align: NonZeroUsize) -> Result<Alignment, Self::Error> {
|
||||||
if align.is_power_of_two() {
|
align.get().try_into()
|
||||||
// SAFETY: Just checked for power-of-two
|
|
||||||
unsafe { Ok(ValidAlign::new_unchecked(align.get())) }
|
|
||||||
} else {
|
|
||||||
Err(num::TryFromIntError(()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<usize> for ValidAlign {
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
impl TryFrom<usize> for Alignment {
|
||||||
type Error = num::TryFromIntError;
|
type Error = num::TryFromIntError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_from(align: usize) -> Result<ValidAlign, Self::Error> {
|
fn try_from(align: usize) -> Result<Alignment, Self::Error> {
|
||||||
if align.is_power_of_two() {
|
Self::new(align).ok_or(num::TryFromIntError(()))
|
||||||
// SAFETY: Just checked for power-of-two
|
|
||||||
unsafe { Ok(ValidAlign::new_unchecked(align)) }
|
|
||||||
} else {
|
|
||||||
Err(num::TryFromIntError(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl cmp::Eq for ValidAlign {}
|
|
||||||
|
|
||||||
impl cmp::PartialEq for ValidAlign {
|
|
||||||
#[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]
|
#[inline]
|
||||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||||
self.as_nonzero().cmp(&other.as_nonzero())
|
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]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hash::Hash for ValidAlign {
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
impl hash::Hash for Alignment {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
self.as_nonzero().hash(state)
|
self.as_nonzero().hash(state)
|
||||||
@ -127,15 +171,15 @@ impl hash::Hash for ValidAlign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
#[cfg(target_pointer_width = "16")]
|
||||||
type ValidAlignEnum = ValidAlignEnum16;
|
type AlignmentEnum = AlignmentEnum16;
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
type ValidAlignEnum = ValidAlignEnum32;
|
type AlignmentEnum = AlignmentEnum32;
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
type ValidAlignEnum = ValidAlignEnum64;
|
type AlignmentEnum = AlignmentEnum64;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
enum ValidAlignEnum16 {
|
enum AlignmentEnum16 {
|
||||||
_Align1Shl0 = 1 << 0,
|
_Align1Shl0 = 1 << 0,
|
||||||
_Align1Shl1 = 1 << 1,
|
_Align1Shl1 = 1 << 1,
|
||||||
_Align1Shl2 = 1 << 2,
|
_Align1Shl2 = 1 << 2,
|
||||||
@ -154,9 +198,9 @@ enum ValidAlignEnum16 {
|
|||||||
_Align1Shl15 = 1 << 15,
|
_Align1Shl15 = 1 << 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
enum ValidAlignEnum32 {
|
enum AlignmentEnum32 {
|
||||||
_Align1Shl0 = 1 << 0,
|
_Align1Shl0 = 1 << 0,
|
||||||
_Align1Shl1 = 1 << 1,
|
_Align1Shl1 = 1 << 1,
|
||||||
_Align1Shl2 = 1 << 2,
|
_Align1Shl2 = 1 << 2,
|
||||||
@ -191,9 +235,9 @@ enum ValidAlignEnum32 {
|
|||||||
_Align1Shl31 = 1 << 31,
|
_Align1Shl31 = 1 << 31,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
enum ValidAlignEnum64 {
|
enum AlignmentEnum64 {
|
||||||
_Align1Shl0 = 1 << 0,
|
_Align1Shl0 = 1 << 0,
|
||||||
_Align1Shl1 = 1 << 1,
|
_Align1Shl1 = 1 << 1,
|
||||||
_Align1Shl2 = 1 << 2,
|
_Align1Shl2 = 1 << 2,
|
@ -377,6 +377,10 @@ use crate::intrinsics::{
|
|||||||
|
|
||||||
use crate::mem::{self, MaybeUninit};
|
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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::intrinsics::copy_nonoverlapping;
|
pub use crate::intrinsics::copy_nonoverlapping;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user