diff options
| author | kennytm <kennytm@gmail.com> | 2017-10-26 03:02:51 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-26 03:02:51 +0800 |
| commit | 86360b7ef5771ea7d091d50fe9735f6767acbb21 (patch) | |
| tree | de3b62141ba02c2835250ad6d79039359eded8fd /src/libcore | |
| parent | 6402797f4d65f5a48ebad1d39afafc512866092a (diff) | |
| parent | c2c1910d69086827629d37deb5ce6a2febdb36fd (diff) | |
| download | rust-86360b7ef5771ea7d091d50fe9735f6767acbb21.tar.gz rust-86360b7ef5771ea7d091d50fe9735f6767acbb21.zip | |
Rollup merge of #45483 - mbrubeck:hash, r=alexcrichton
Implement Hash for raw pointers to unsized types This is useful for some niche cases, like a hash table of slices or trait objects where the key is the raw pointer. Example use case: https://docs.rs/by_address
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/hash/mod.rs | 28 | ||||
| -rw-r--r-- | src/libcore/tests/hash/mod.rs | 8 |
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 } |
