From 1bcf9fae0315d25b2a5aebd5440bc18a7f01ebf0 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 4 Nov 2022 13:43:13 +0100 Subject: [PATCH 1/6] Made `Hash` and `Hasher` const_trait --- library/core/src/hash/mod.rs | 68 +++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index aa13435e6808d..f3a60ed1d5796 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -183,6 +183,7 @@ mod sip; /// [impl]: ../../std/primitive.str.html#impl-Hash-for-str #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Hash"] +#[const_trait] pub trait Hash { /// Feeds this value into the given [`Hasher`]. /// @@ -234,12 +235,19 @@ pub trait Hash { /// [`hash`]: Hash::hash /// [`hash_slice`]: Hash::hash_slice #[stable(feature = "hash_slice", since = "1.3.0")] - fn hash_slice(data: &[Self], state: &mut H) + fn hash_slice(data: &[Self], state: &mut H) where Self: Sized, { - for piece in data { - piece.hash(state); + //FIXME(const_iter_slice): Revert to for loop + //for piece in data { + // piece.hash(state); + //} + + let mut i = 0; + while i < data.len() { + data[i].hash(state); + i += 1; } } } @@ -313,6 +321,7 @@ pub use macros::Hash; /// [`write_u8`]: Hasher::write_u8 /// [`write_u32`]: Hasher::write_u32 #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait Hasher { /// Returns the hash value for the values written so far. /// @@ -558,7 +567,8 @@ pub trait Hasher { } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -impl Hasher for &mut H { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const Hasher for &mut H { fn finish(&self) -> u64 { (**self).finish() } @@ -806,14 +816,15 @@ mod impls { macro_rules! impl_write { ($(($ty:ident, $meth:ident),)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for $ty { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for $ty { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { state.$meth(*self) } #[inline] - fn hash_slice(data: &[$ty], state: &mut H) { + fn hash_slice(data: &[$ty], state: &mut H) { let newlen = data.len() * mem::size_of::<$ty>(); let ptr = data.as_ptr() as *const u8; // SAFETY: `ptr` is valid and aligned, as this macro is only used @@ -842,33 +853,37 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for bool { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for bool { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { state.write_u8(*self as u8) } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for char { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for char { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { state.write_u32(*self as u32) } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for str { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for str { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { state.write_str(self); } } #[stable(feature = "never_hash", since = "1.29.0")] - impl Hash for ! { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for ! { #[inline] - fn hash(&self, _: &mut H) { + fn hash(&self, _: &mut H) { *self } } @@ -876,9 +891,10 @@ mod impls { macro_rules! impl_hash_tuple { () => ( #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for () { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for () { #[inline] - fn hash(&self, _state: &mut H) {} + fn hash(&self, _state: &mut H) {} } ); @@ -886,10 +902,11 @@ mod impls { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl<$($name: ~const Hash),+> const Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] #[inline] - fn hash(&self, state: &mut S) { + fn hash(&self, state: &mut S) { let ($(ref $name,)+) = *self; $($name.hash(state);)+ } @@ -932,24 +949,27 @@ mod impls { impl_hash_tuple! { T B C D E F G H I J K L } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for [T] { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for [T] { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { state.write_length_prefix(self.len()); Hash::hash_slice(self, state) } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for &T { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for &T { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { (**self).hash(state); } } #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for &mut T { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + impl const Hash for &mut T { #[inline] fn hash(&self, state: &mut H) { (**self).hash(state); From 3ea4165a774df7060707c68efb2573ae23f75f1b Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 4 Nov 2022 21:30:39 +0100 Subject: [PATCH 2/6] Make `BuildHasher` const_trait --- library/core/src/hash/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index f3a60ed1d5796..b66475e43ac5f 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -86,7 +86,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; -use crate::marker; +use crate::marker::{self, Destruct}; #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -648,6 +648,7 @@ impl const Hasher for &mut H { /// [`build_hasher`]: BuildHasher::build_hasher /// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")] +#[const_trait] pub trait BuildHasher { /// Type of the hasher that will be created. #[stable(since = "1.7.0", feature = "build_hasher")] @@ -708,9 +709,10 @@ pub trait BuildHasher { /// ); /// ``` #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] - fn hash_one(&self, x: T) -> u64 + fn hash_one(&self, x: T) -> u64 where Self: Sized, + Self::Hasher: ~const Hasher + ~const Destruct, { let mut hasher = self.build_hasher(); x.hash(&mut hasher); @@ -774,7 +776,8 @@ impl fmt::Debug for BuildHasherDefault { } #[stable(since = "1.7.0", feature = "build_hasher")] -impl BuildHasher for BuildHasherDefault { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const BuildHasher for BuildHasherDefault { type Hasher = H; fn build_hasher(&self) -> H { From 5f9899b289c726518faab975ae2f612462ba888b Mon Sep 17 00:00:00 2001 From: onestacked Date: Sun, 6 Nov 2022 17:46:38 +0100 Subject: [PATCH 3/6] Made `Sip` const `Hasher` --- library/core/src/hash/sip.rs | 38 ++++++++++++++++--------- library/core/src/lib.rs | 1 + library/std/src/collections/hash/map.rs | 9 ++++-- library/std/src/lib.rs | 1 + 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 81bf1dfdf4510..b389ae4a01995 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -118,7 +118,7 @@ macro_rules! load_int_le { /// Safety: this performs unchecked indexing of `buf` at `start..start+len`, so /// that must be in-bounds. #[inline] -unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { +const unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { debug_assert!(len < 8); let mut i = 0; // current byte index (from LSB) in the output u64 let mut out = 0; @@ -138,7 +138,7 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); i += 1; } - debug_assert_eq!(i, len); + debug_assert!(i == len); out } @@ -150,8 +150,9 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[rustc_const_unstable(feature = "const_hash", issue = "none")] #[must_use] - pub fn new() -> SipHasher { + pub const fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -162,8 +163,9 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[rustc_const_unstable(feature = "const_hash", issue = "none")] #[must_use] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { + pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) } } @@ -176,7 +178,8 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - pub fn new() -> SipHasher13 { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -187,14 +190,15 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { + #[rustc_const_unstable(feature = "const_hash", issue = "none")] + pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } } } impl Hasher { #[inline] - fn new_with_keys(key0: u64, key1: u64) -> Hasher { + const fn new_with_keys(key0: u64, key1: u64) -> Hasher { let mut state = Hasher { k0: key0, k1: key1, @@ -209,7 +213,7 @@ impl Hasher { } #[inline] - fn reset(&mut self) { + const fn reset(&mut self) { self.length = 0; self.state.v0 = self.k0 ^ 0x736f6d6570736575; self.state.v1 = self.k1 ^ 0x646f72616e646f6d; @@ -220,7 +224,8 @@ impl Hasher { } #[stable(feature = "rust1", since = "1.0.0")] -impl super::Hasher for SipHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const super::Hasher for SipHasher { #[inline] fn write(&mut self, msg: &[u8]) { self.0.hasher.write(msg) @@ -238,7 +243,11 @@ impl super::Hasher for SipHasher { } #[unstable(feature = "hashmap_internals", issue = "none")] -impl super::Hasher for SipHasher13 { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const super::Hasher for SipHasher13 +where + Hasher: ~const super::Hasher, +{ #[inline] fn write(&mut self, msg: &[u8]) { self.hasher.write(msg) @@ -255,7 +264,7 @@ impl super::Hasher for SipHasher13 { } } -impl super::Hasher for Hasher { +impl const super::Hasher for Hasher { // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined // for this type. We could add them, copy the `short_write` implementation // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` @@ -335,7 +344,7 @@ impl super::Hasher for Hasher { } } -impl Clone for Hasher { +impl const Clone for Hasher { #[inline] fn clone(&self) -> Hasher { Hasher { @@ -359,6 +368,7 @@ impl Default for Hasher { } #[doc(hidden)] +#[const_trait] trait Sip { fn c_rounds(_: &mut State); fn d_rounds(_: &mut State); @@ -367,7 +377,7 @@ trait Sip { #[derive(Debug, Clone, Default)] struct Sip13Rounds; -impl Sip for Sip13Rounds { +impl const Sip for Sip13Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); @@ -384,7 +394,7 @@ impl Sip for Sip13Rounds { #[derive(Debug, Clone, Default)] struct Sip24Rounds; -impl Sip for Sip24Rounds { +impl const Sip for Sip24Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 659409557c910..5dc7427bee003 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -112,6 +112,7 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_fmt_arguments_new)] +#![feature(const_hash)] #![feature(const_heap)] #![feature(const_convert)] #![feature(const_index_range_slice_index)] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 708edc5de4751..1963c24b6e94d 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3161,14 +3161,16 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] + #[rustc_const_unstable(feature = "const_hash", issue = "none")] #[must_use] - pub fn new() -> DefaultHasher { + pub const fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const Default for DefaultHasher { /// Creates a new `DefaultHasher` using [`new`]. /// See its documentation for more. /// @@ -3180,7 +3182,8 @@ impl Default for DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { +#[rustc_const_unstable(feature = "const_hash", issue = "none")] +impl const Hasher for DefaultHasher { // The underlying `SipHasher13` doesn't override the other // `write_*` methods, so it's ok not to forward them here. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 385585dada896..8aa0424bc4bf0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -314,6 +314,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_uninit_array)] #![feature(const_waker)] +#![feature(const_hash)] // // Library features (alloc): #![feature(alloc_layout_extra)] From dc1f1a8e970f65cbc8d5dc7fbdd466c06c8082e9 Mon Sep 17 00:00:00 2001 From: onestacked Date: Sun, 6 Nov 2022 18:01:44 +0100 Subject: [PATCH 4/6] Added `const_hash` tracking issue id --- library/core/src/hash/mod.rs | 24 ++++++++++++------------ library/core/src/hash/sip.rs | 12 ++++++------ library/std/src/collections/hash/map.rs | 6 +++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index b66475e43ac5f..d8bb92fcc8d50 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -567,7 +567,7 @@ pub trait Hasher { } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hasher for &mut H { fn finish(&self) -> u64 { (**self).finish() @@ -776,7 +776,7 @@ impl fmt::Debug for BuildHasherDefault { } #[stable(since = "1.7.0", feature = "build_hasher")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const BuildHasher for BuildHasherDefault { type Hasher = H; @@ -819,7 +819,7 @@ mod impls { macro_rules! impl_write { ($(($ty:ident, $meth:ident),)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for $ty { #[inline] fn hash(&self, state: &mut H) { @@ -856,7 +856,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for bool { #[inline] fn hash(&self, state: &mut H) { @@ -865,7 +865,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for char { #[inline] fn hash(&self, state: &mut H) { @@ -874,7 +874,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for str { #[inline] fn hash(&self, state: &mut H) { @@ -883,7 +883,7 @@ mod impls { } #[stable(feature = "never_hash", since = "1.29.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for ! { #[inline] fn hash(&self, _: &mut H) { @@ -894,7 +894,7 @@ mod impls { macro_rules! impl_hash_tuple { () => ( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for () { #[inline] fn hash(&self, _state: &mut H) {} @@ -905,7 +905,7 @@ mod impls { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl<$($name: ~const Hash),+> const Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] #[inline] @@ -952,7 +952,7 @@ mod impls { impl_hash_tuple! { T B C D E F G H I J K L } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for [T] { #[inline] fn hash(&self, state: &mut H) { @@ -962,7 +962,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for &T { #[inline] fn hash(&self, state: &mut H) { @@ -971,7 +971,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hash for &mut T { #[inline] fn hash(&self, state: &mut H) { diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index b389ae4a01995..51581d2108951 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -150,7 +150,7 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) @@ -163,7 +163,7 @@ impl SipHasher { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) @@ -178,7 +178,7 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -190,7 +190,7 @@ impl SipHasher13 { since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead" )] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } } @@ -224,7 +224,7 @@ impl Hasher { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const super::Hasher for SipHasher { #[inline] fn write(&mut self, msg: &[u8]) { @@ -243,7 +243,7 @@ impl const super::Hasher for SipHasher { } #[unstable(feature = "hashmap_internals", issue = "none")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const super::Hasher for SipHasher13 where Hasher: ~const super::Hasher, diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 1963c24b6e94d..df490358827e7 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3161,7 +3161,7 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "none")] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) @@ -3169,7 +3169,7 @@ impl DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Default for DefaultHasher { /// Creates a new `DefaultHasher` using [`new`]. /// See its documentation for more. @@ -3182,7 +3182,7 @@ impl const Default for DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "none")] +#[rustc_const_unstable(feature = "const_hash", issue = "104061")] impl const Hasher for DefaultHasher { // The underlying `SipHasher13` doesn't override the other // `write_*` methods, so it's ok not to forward them here. From cebce1e616c6d1cd61154eef4928c991e9f7189f Mon Sep 17 00:00:00 2001 From: onestacked Date: Mon, 7 Nov 2022 15:34:43 +0100 Subject: [PATCH 5/6] Removed unnecessary Trait bound --- library/core/src/hash/sip.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 51581d2108951..0dea1c43f200f 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -244,10 +244,7 @@ impl const super::Hasher for SipHasher { #[unstable(feature = "hashmap_internals", issue = "none")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl const super::Hasher for SipHasher13 -where - Hasher: ~const super::Hasher, -{ +impl const super::Hasher for SipHasher13 { #[inline] fn write(&mut self, msg: &[u8]) { self.hasher.write(msg) From 56e59bcb27943a1a520f2d59f41af1f1cd8b1c01 Mon Sep 17 00:00:00 2001 From: onestacked Date: Tue, 8 Nov 2022 17:39:40 +0100 Subject: [PATCH 6/6] Test const `Hash`, fix nits --- library/core/src/hash/mod.rs | 24 +++++++++++++-------- library/core/src/hash/sip.rs | 1 + library/core/tests/hash/mod.rs | 38 +++++++++++++++++++++++++--------- library/core/tests/hash/sip.rs | 15 +++++++++++++- library/core/tests/lib.rs | 1 + library/std/src/lib.rs | 2 +- 6 files changed, 60 insertions(+), 21 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index d8bb92fcc8d50..c755afa39eb60 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -86,6 +86,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; +use crate::intrinsics::const_eval_select; use crate::marker::{self, Destruct}; #[stable(feature = "rust1", since = "1.0.0")] @@ -239,16 +240,21 @@ pub trait Hash { where Self: Sized, { - //FIXME(const_iter_slice): Revert to for loop - //for piece in data { - // piece.hash(state); - //} - - let mut i = 0; - while i < data.len() { - data[i].hash(state); - i += 1; + //FIXME(const_trait_impl): revert to only a for loop + fn rt(data: &[T], state: &mut H) { + for piece in data { + piece.hash(state) + } + } + const fn ct(data: &[T], state: &mut H) { + let mut i = 0; + while i < data.len() { + data[i].hash(state); + i += 1; + } } + // SAFETY: same behavior, CT just uses while instead of for + unsafe { const_eval_select((data, state), ct, rt) }; } } diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 0dea1c43f200f..7f8287bf56f64 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -138,6 +138,7 @@ const unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); i += 1; } + //FIXME(fee1-dead): use debug_assert_eq debug_assert!(i == len); out } diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index f7934d062a379..267245f05dcd2 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -9,16 +9,19 @@ struct MyHasher { hash: u64, } -impl Default for MyHasher { +impl const Default for MyHasher { fn default() -> MyHasher { MyHasher { hash: 0 } } } -impl Hasher for MyHasher { +impl const Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - for byte in buf { - self.hash += *byte as u64; + // FIXME(const_trait_impl): change to for loop + let mut i = 0; + while i < buf.len() { + self.hash += buf[i] as u64; + i += 1; } } fn write_str(&mut self, s: &str) { @@ -32,12 +35,25 @@ impl Hasher for MyHasher { #[test] fn test_writer_hasher() { - fn hash(t: &T) -> u64 { + const fn hash(t: &T) -> u64 { let mut s = MyHasher { hash: 0 }; t.hash(&mut s); s.finish() } + const { + // FIXME(fee1-dead): assert_eq + assert!(hash(&()) == 0); + assert!(hash(&5_u8) == 5); + assert!(hash(&5_u16) == 5); + assert!(hash(&5_u32) == 5); + + assert!(hash(&'a') == 97); + + let s: &str = "a"; + assert!(hash(&s) == 97 + 0xFF); + }; + assert_eq!(hash(&()), 0); assert_eq!(hash(&5_u8), 5); @@ -97,7 +113,7 @@ struct CustomHasher { output: u64, } -impl Hasher for CustomHasher { +impl const Hasher for CustomHasher { fn finish(&self) -> u64 { self.output } @@ -109,27 +125,29 @@ impl Hasher for CustomHasher { } } -impl Default for CustomHasher { +impl const Default for CustomHasher { fn default() -> CustomHasher { CustomHasher { output: 0 } } } -impl Hash for Custom { - fn hash(&self, state: &mut H) { +impl const Hash for Custom { + fn hash(&self, state: &mut H) { state.write_u64(self.hash); } } #[test] fn test_custom_state() { - fn hash(t: &T) -> u64 { + const fn hash(t: &T) -> u64 { let mut c = CustomHasher { output: 0 }; t.hash(&mut c); c.finish() } assert_eq!(hash(&Custom { hash: 5 }), 5); + + const { assert!(hash(&Custom { hash: 6 }) == 6) }; } // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. diff --git a/library/core/tests/hash/sip.rs b/library/core/tests/hash/sip.rs index 877d084183055..3abf6efcfa9ba 100644 --- a/library/core/tests/hash/sip.rs +++ b/library/core/tests/hash/sip.rs @@ -8,7 +8,6 @@ use core::{mem, slice}; struct Bytes<'a>(&'a [u8]); impl<'a> Hash for Bytes<'a> { - #[allow(unused_must_use)] fn hash(&self, state: &mut H) { let Bytes(v) = *self; state.write(v); @@ -24,6 +23,20 @@ fn hash(x: &T) -> u64 { hash_with(SipHasher::new(), x) } +#[test] +const fn test_const_sip() { + let val1 = 0x45; + let val2 = 0xfeed; + + const fn const_hash(x: &T) -> u64 { + let mut st = SipHasher::new(); + x.hash(&mut st); + st.finish() + } + + assert!(const_hash(&(val1)) != const_hash(&(val2))); +} + #[test] #[allow(unused_must_use)] fn test_siphash_1_3() { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index eda176d9fcbe6..e805e65cf20f2 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -11,6 +11,7 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_convert)] +#![feature(const_hash)] #![feature(const_heap)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8aa0424bc4bf0..9334c833bb650 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -314,7 +314,6 @@ #![feature(maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_uninit_array)] #![feature(const_waker)] -#![feature(const_hash)] // // Library features (alloc): #![feature(alloc_layout_extra)] @@ -353,6 +352,7 @@ // // Only for const-ness: #![feature(const_collections_with_hasher)] +#![feature(const_hash)] #![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv4)]