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)]