about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatt Brubeck <mbrubeck@limpet.net>2017-10-23 14:21:00 -0700
committerMatt Brubeck <mbrubeck@limpet.net>2017-10-25 11:07:13 -0700
commitc2c1910d69086827629d37deb5ce6a2febdb36fd (patch)
treea6ab98463b450e4b2ecb6a369e56a65bfd123be9 /src
parent4c053db233d69519b548e5b8ed7192d0783e582a (diff)
downloadrust-c2c1910d69086827629d37deb5ce6a2febdb36fd.tar.gz
rust-c2c1910d69086827629d37deb5ce6a2febdb36fd.zip
Implement Hash for raw pointers to unsized types
Diffstat (limited to 'src')
-rw-r--r--src/libcore/hash/mod.rs28
-rw-r--r--src/libcore/tests/hash/mod.rs8
2 files changed, 32 insertions, 4 deletions
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index bc1b911cd78..b3c11ed1b5a 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -665,16 +665,36 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T> Hash for *const T {
+    impl<T: ?Sized> Hash for *const T {
         fn hash<H: Hasher>(&self, state: &mut H) {
-            state.write_usize(*self as usize)
+            if mem::size_of::<Self>() == mem::size_of::<usize>() {
+                // Thin pointer
+                state.write_usize(*self as *const () as usize);
+            } else {
+                // Fat pointer
+                let (a, b) = unsafe {
+                    *(self as *const Self as *const (usize, usize))
+                };
+                state.write_usize(a);
+                state.write_usize(b);
+            }
         }
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T> Hash for *mut T {
+    impl<T: ?Sized> Hash for *mut T {
         fn hash<H: Hasher>(&self, state: &mut H) {
-            state.write_usize(*self as usize)
+            if mem::size_of::<Self>() == mem::size_of::<usize>() {
+                // Thin pointer
+                state.write_usize(*self as *const () as usize);
+            } else {
+                // Fat pointer
+                let (a, b) = unsafe {
+                    *(self as *const Self as *const (usize, usize))
+                };
+                state.write_usize(a);
+                state.write_usize(b);
+            }
         }
     }
 }
diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs
index 43ba941f13b..8716421b424 100644
--- a/src/libcore/tests/hash/mod.rs
+++ b/src/libcore/tests/hash/mod.rs
@@ -79,6 +79,14 @@ fn test_writer_hasher() {
 
     let ptr = 5_usize as *mut i32;
     assert_eq!(hash(&ptr), 5);
+
+    let cs: &mut [u8] = &mut [1, 2, 3];
+    let ptr = cs.as_ptr();
+    let slice_ptr = cs as *const [u8];
+    assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
+
+    let slice_ptr = cs as *mut [u8];
+    assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
 }
 
 struct Custom { hash: u64 }