about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2021-01-18 17:18:13 +0100
committerSimon Sapin <simon.sapin@exyr.org>2021-02-15 14:27:34 +0100
commit787f4de6ab3150ea56e8a7cc872b60d55b0db27f (patch)
tree15d1be38182ee0f04abe088a7b06d1a28eb8dcca
parentc0e3a1b0968da04723ff326dc7def1d706c62377 (diff)
downloadrust-787f4de6ab3150ea56e8a7cc872b60d55b0db27f.tar.gz
rust-787f4de6ab3150ea56e8a7cc872b60d55b0db27f.zip
Use new pointer metadata API inside libcore instead of manual transmutes
-rw-r--r--library/core/src/hash/mod.rs70
-rw-r--r--library/core/src/ptr/const_ptr.rs11
-rw-r--r--library/core/src/ptr/mod.rs30
-rw-r--r--library/core/src/ptr/mut_ptr.rs11
-rw-r--r--library/core/src/slice/mod.rs20
5 files changed, 100 insertions, 42 deletions
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index f53ba981438..cd47f97496a 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -673,19 +673,28 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl<T: ?Sized> Hash for *const T {
         fn hash<H: Hasher>(&self, state: &mut H) {
-            if mem::size_of::<Self>() == mem::size_of::<usize>() {
-                // Thin pointer
-                state.write_usize(*self as *const () as usize);
-            } else {
-                // Fat pointer
-                // SAFETY: we are accessing the memory occupied by `self`
-                // which is guaranteed to be valid.
-                // This assumes a fat pointer can be represented by a `(usize, usize)`,
-                // which is safe to do in `std` because it is shipped and kept in sync
-                // with the implementation of fat pointers in `rustc`.
-                let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
-                state.write_usize(a);
-                state.write_usize(b);
+            #[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>() {
+                    // Thin pointer
+                    state.write_usize(*self as *const () as usize);
+                } else {
+                    // Fat pointer
+                    // SAFETY: we are accessing the memory occupied by `self`
+                    // which is guaranteed to be valid.
+                    // This assumes a fat pointer can be represented by a `(usize, usize)`,
+                    // which is safe to do in `std` because it is shipped and kept in sync
+                    // with the implementation of fat pointers in `rustc`.
+                    let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
+                    state.write_usize(a);
+                    state.write_usize(b);
+                }
             }
         }
     }
@@ -693,19 +702,28 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl<T: ?Sized> Hash for *mut T {
         fn hash<H: Hasher>(&self, state: &mut H) {
-            if mem::size_of::<Self>() == mem::size_of::<usize>() {
-                // Thin pointer
-                state.write_usize(*self as *const () as usize);
-            } else {
-                // Fat pointer
-                // SAFETY: we are accessing the memory occupied by `self`
-                // which is guaranteed to be valid.
-                // This assumes a fat pointer can be represented by a `(usize, usize)`,
-                // which is safe to do in `std` because it is shipped and kept in sync
-                // with the implementation of fat pointers in `rustc`.
-                let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
-                state.write_usize(a);
-                state.write_usize(b);
+            #[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>() {
+                    // Thin pointer
+                    state.write_usize(*self as *const () as usize);
+                } else {
+                    // Fat pointer
+                    // SAFETY: we are accessing the memory occupied by `self`
+                    // which is guaranteed to be valid.
+                    // This assumes a fat pointer can be represented by a `(usize, usize)`,
+                    // which is safe to do in `std` because it is shipped and kept in sync
+                    // with the implementation of fat pointers in `rustc`.
+                    let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
+                    state.write_usize(a);
+                    state.write_usize(b);
+                }
             }
         }
     }
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index bd89ec27ae2..a635e59e89b 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -916,9 +916,14 @@ impl<T> *const [T] {
     #[unstable(feature = "slice_ptr_len", issue = "71146")]
     #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
     pub const fn len(self) -> usize {
-        // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
-        // Only `std` can make this guarantee.
-        unsafe { Repr { rust: self }.raw }.len
+        #[cfg(bootstrap)]
+        {
+            // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
+            // Only `std` can make this guarantee.
+            unsafe { Repr { rust: self }.raw }.len
+        }
+        #[cfg(not(bootstrap))]
+        metadata(self)
     }
 
     /// Returns a raw pointer to the slice's buffer.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 967495f7f2d..05fd090125c 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -85,6 +85,8 @@ pub use crate::intrinsics::write_bytes;
 #[cfg(not(bootstrap))]
 mod metadata;
 #[cfg(not(bootstrap))]
+pub(crate) use metadata::PtrRepr;
+#[cfg(not(bootstrap))]
 #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
 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
 }
 
+#[cfg(bootstrap)]
 #[repr(C)]
 pub(crate) union Repr<T> {
     pub(crate) rust: *const [T],
@@ -233,12 +236,14 @@ pub(crate) union Repr<T> {
     pub(crate) raw: FatPtr<T>,
 }
 
+#[cfg(bootstrap)]
 #[repr(C)]
 pub(crate) struct FatPtr<T> {
     data: *const T,
     pub(crate) len: usize,
 }
 
+#[cfg(bootstrap)]
 // Manual impl needed to avoid `T: Clone` bound.
 impl<T> Clone for FatPtr<T> {
     fn clone(&self) -> Self {
@@ -246,6 +251,7 @@ impl<T> Clone for FatPtr<T> {
     }
 }
 
+#[cfg(bootstrap)]
 // Manual impl needed to avoid `T: Copy` bound.
 impl<T> Copy for FatPtr<T> {}
 
@@ -273,10 +279,15 @@ impl<T> Copy for FatPtr<T> {}
 #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
 #[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] {
-    // 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
-    // guarantee.
-    unsafe { Repr { raw: FatPtr { data, len } }.rust }
+    #[cfg(bootstrap)]
+    {
+        // 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
+        // guarantee.
+        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
@@ -308,9 +319,14 @@ 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")]
 #[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] {
-    // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T]
-    // and FatPtr have the same memory layouts
-    unsafe { Repr { raw: FatPtr { data, len } }.rust_mut }
+    #[cfg(bootstrap)]
+    {
+        // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T]
+        // and FatPtr have the same memory layouts
+        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
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 731b97a06cb..f7da49290ae 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1173,9 +1173,14 @@ impl<T> *mut [T] {
     #[unstable(feature = "slice_ptr_len", issue = "71146")]
     #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
     pub const fn len(self) -> usize {
-        // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
-        // Only `std` can make this guarantee.
-        unsafe { Repr { rust_mut: self }.raw }.len
+        #[cfg(bootstrap)]
+        {
+            // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
+            // Only `std` can make this guarantee.
+            unsafe { Repr { rust_mut: self }.raw }.len
+        }
+        #[cfg(not(bootstrap))]
+        metadata(self)
     }
 
     /// Returns a raw pointer to the slice's buffer.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index a6929e462e7..1c1b9e0b27e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -94,9 +94,23 @@ impl<T> [T] {
     // 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)]
     pub const fn len(&self) -> usize {
-        // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
-        // Only `std` can make this guarantee.
-        unsafe { crate::ptr::Repr { rust: self }.raw.len }
+        #[cfg(bootstrap)]
+        {
+            // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
+            // Only `std` can make this guarantee.
+            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.