1
Fork 0

Use new pointer metadata API inside libcore instead of manual transmutes

This commit is contained in:
Simon Sapin 2021-01-18 17:18:13 +01:00
parent c0e3a1b096
commit 787f4de6ab
5 changed files with 100 additions and 42 deletions

View file

@ -673,6 +673,14 @@ mod impls {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Hash for *const T { impl<T: ?Sized> Hash for *const T {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
#[cfg(not(bootstrap))]
{
let (address, metadata) = self.to_raw_parts();
state.write_usize(address as usize);
metadata.hash(state);
}
#[cfg(bootstrap)]
{
if mem::size_of::<Self>() == mem::size_of::<usize>() { if mem::size_of::<Self>() == mem::size_of::<usize>() {
// Thin pointer // Thin pointer
state.write_usize(*self as *const () as usize); state.write_usize(*self as *const () as usize);
@ -689,10 +697,19 @@ mod impls {
} }
} }
} }
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Hash for *mut T { impl<T: ?Sized> Hash for *mut T {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
#[cfg(not(bootstrap))]
{
let (address, metadata) = self.to_raw_parts();
state.write_usize(address as usize);
metadata.hash(state);
}
#[cfg(bootstrap)]
{
if mem::size_of::<Self>() == mem::size_of::<usize>() { if mem::size_of::<Self>() == mem::size_of::<usize>() {
// Thin pointer // Thin pointer
state.write_usize(*self as *const () as usize); state.write_usize(*self as *const () as usize);
@ -710,3 +727,4 @@ mod impls {
} }
} }
} }
}

View file

@ -916,10 +916,15 @@ impl<T> *const [T] {
#[unstable(feature = "slice_ptr_len", issue = "71146")] #[unstable(feature = "slice_ptr_len", issue = "71146")]
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
pub const fn len(self) -> usize { pub const fn len(self) -> usize {
#[cfg(bootstrap)]
{
// SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout. // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
// Only `std` can make this guarantee. // Only `std` can make this guarantee.
unsafe { Repr { rust: self }.raw }.len unsafe { Repr { rust: self }.raw }.len
} }
#[cfg(not(bootstrap))]
metadata(self)
}
/// Returns a raw pointer to the slice's buffer. /// Returns a raw pointer to the slice's buffer.
/// ///

View file

@ -85,6 +85,8 @@ pub use crate::intrinsics::write_bytes;
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]
mod metadata; mod metadata;
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]
pub(crate) use metadata::PtrRepr;
#[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin}; pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
@ -226,6 +228,7 @@ pub const fn null_mut<T>() -> *mut T {
0 as *mut T 0 as *mut T
} }
#[cfg(bootstrap)]
#[repr(C)] #[repr(C)]
pub(crate) union Repr<T> { pub(crate) union Repr<T> {
pub(crate) rust: *const [T], pub(crate) rust: *const [T],
@ -233,12 +236,14 @@ pub(crate) union Repr<T> {
pub(crate) raw: FatPtr<T>, pub(crate) raw: FatPtr<T>,
} }
#[cfg(bootstrap)]
#[repr(C)] #[repr(C)]
pub(crate) struct FatPtr<T> { pub(crate) struct FatPtr<T> {
data: *const T, data: *const T,
pub(crate) len: usize, pub(crate) len: usize,
} }
#[cfg(bootstrap)]
// Manual impl needed to avoid `T: Clone` bound. // Manual impl needed to avoid `T: Clone` bound.
impl<T> Clone for FatPtr<T> { impl<T> Clone for FatPtr<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -246,6 +251,7 @@ impl<T> Clone for FatPtr<T> {
} }
} }
#[cfg(bootstrap)]
// Manual impl needed to avoid `T: Copy` bound. // Manual impl needed to avoid `T: Copy` bound.
impl<T> Copy for FatPtr<T> {} impl<T> Copy for FatPtr<T> {}
@ -273,11 +279,16 @@ impl<T> Copy for FatPtr<T> {}
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] { pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
#[cfg(bootstrap)]
{
// SAFETY: Accessing the value from the `Repr` union is safe since *const [T] // SAFETY: Accessing the value from the `Repr` union is safe since *const [T]
// and FatPtr have the same memory layouts. Only std can make this // and FatPtr have the same memory layouts. Only std can make this
// guarantee. // guarantee.
unsafe { Repr { raw: FatPtr { data, len } }.rust } unsafe { Repr { raw: FatPtr { data, len } }.rust }
} }
#[cfg(not(bootstrap))]
from_raw_parts(data.cast(), len)
}
/// Performs the same functionality as [`slice_from_raw_parts`], except that a /// Performs the same functionality as [`slice_from_raw_parts`], except that a
/// raw mutable slice is returned, as opposed to a raw immutable slice. /// raw mutable slice is returned, as opposed to a raw immutable slice.
@ -308,10 +319,15 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] { pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
#[cfg(bootstrap)]
{
// SAFETY: Accessing the value from the `Repr` union is safe since *mut [T] // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T]
// and FatPtr have the same memory layouts // and FatPtr have the same memory layouts
unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } unsafe { Repr { raw: FatPtr { data, len } }.rust_mut }
} }
#[cfg(not(bootstrap))]
from_raw_parts_mut(data.cast(), len)
}
/// Swaps the values at two mutable locations of the same type, without /// Swaps the values at two mutable locations of the same type, without
/// deinitializing either. /// deinitializing either.

View file

@ -1173,10 +1173,15 @@ impl<T> *mut [T] {
#[unstable(feature = "slice_ptr_len", issue = "71146")] #[unstable(feature = "slice_ptr_len", issue = "71146")]
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
pub const fn len(self) -> usize { pub const fn len(self) -> usize {
#[cfg(bootstrap)]
{
// SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout. // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
// Only `std` can make this guarantee. // Only `std` can make this guarantee.
unsafe { Repr { rust_mut: self }.raw }.len unsafe { Repr { rust_mut: self }.raw }.len
} }
#[cfg(not(bootstrap))]
metadata(self)
}
/// Returns a raw pointer to the slice's buffer. /// Returns a raw pointer to the slice's buffer.
/// ///

View file

@ -94,10 +94,24 @@ impl<T> [T] {
// SAFETY: const sound because we transmute out the length field as a usize (which it must be) // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
#[rustc_allow_const_fn_unstable(const_fn_union)] #[rustc_allow_const_fn_unstable(const_fn_union)]
pub const fn len(&self) -> usize { pub const fn len(&self) -> usize {
#[cfg(bootstrap)]
{
// SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout. // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
// Only `std` can make this guarantee. // Only `std` can make this guarantee.
unsafe { crate::ptr::Repr { rust: self }.raw.len } unsafe { crate::ptr::Repr { rust: self }.raw.len }
} }
#[cfg(not(bootstrap))]
{
// FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
// As of this writing this causes a "Const-stable functions can only call other
// const-stable functions" error.
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
// and PtrComponents<T> have the same memory layouts. Only std can make this
// guarantee.
unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
}
}
/// Returns `true` if the slice has a length of 0. /// Returns `true` if the slice has a length of 0.
/// ///