Skip to content

Commit 150e0ec

Browse files
authored
Rollup merge of #104060 - ink-feather-org:const_hash, r=fee1-dead
Make `Hash`, `Hasher` and `BuildHasher` `#[const_trait]` and make `Sip` const `Hasher` This PR enables using Hashes in const context. r? ``@fee1-dead``
2 parents 529f714 + 56e59bc commit 150e0ec

File tree

8 files changed

+129
-55
lines changed

8 files changed

+129
-55
lines changed

library/core/src/hash/mod.rs

+56-27
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@
8686
#![stable(feature = "rust1", since = "1.0.0")]
8787

8888
use crate::fmt;
89-
use crate::marker;
89+
use crate::intrinsics::const_eval_select;
90+
use crate::marker::{self, Destruct};
9091

9192
#[stable(feature = "rust1", since = "1.0.0")]
9293
#[allow(deprecated)]
@@ -183,6 +184,7 @@ mod sip;
183184
/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str
184185
#[stable(feature = "rust1", since = "1.0.0")]
185186
#[rustc_diagnostic_item = "Hash"]
187+
#[const_trait]
186188
pub trait Hash {
187189
/// Feeds this value into the given [`Hasher`].
188190
///
@@ -234,13 +236,25 @@ pub trait Hash {
234236
/// [`hash`]: Hash::hash
235237
/// [`hash_slice`]: Hash::hash_slice
236238
#[stable(feature = "hash_slice", since = "1.3.0")]
237-
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
239+
fn hash_slice<H: ~const Hasher>(data: &[Self], state: &mut H)
238240
where
239241
Self: Sized,
240242
{
241-
for piece in data {
242-
piece.hash(state);
243+
//FIXME(const_trait_impl): revert to only a for loop
244+
fn rt<T: Hash, H: Hasher>(data: &[T], state: &mut H) {
245+
for piece in data {
246+
piece.hash(state)
247+
}
248+
}
249+
const fn ct<T: ~const Hash, H: ~const Hasher>(data: &[T], state: &mut H) {
250+
let mut i = 0;
251+
while i < data.len() {
252+
data[i].hash(state);
253+
i += 1;
254+
}
243255
}
256+
// SAFETY: same behavior, CT just uses while instead of for
257+
unsafe { const_eval_select((data, state), ct, rt) };
244258
}
245259
}
246260

@@ -313,6 +327,7 @@ pub use macros::Hash;
313327
/// [`write_u8`]: Hasher::write_u8
314328
/// [`write_u32`]: Hasher::write_u32
315329
#[stable(feature = "rust1", since = "1.0.0")]
330+
#[const_trait]
316331
pub trait Hasher {
317332
/// Returns the hash value for the values written so far.
318333
///
@@ -558,7 +573,8 @@ pub trait Hasher {
558573
}
559574

560575
#[stable(feature = "indirect_hasher_impl", since = "1.22.0")]
561-
impl<H: Hasher + ?Sized> Hasher for &mut H {
576+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
577+
impl<H: ~const Hasher + ?Sized> const Hasher for &mut H {
562578
fn finish(&self) -> u64 {
563579
(**self).finish()
564580
}
@@ -638,6 +654,7 @@ impl<H: Hasher + ?Sized> Hasher for &mut H {
638654
/// [`build_hasher`]: BuildHasher::build_hasher
639655
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
640656
#[stable(since = "1.7.0", feature = "build_hasher")]
657+
#[const_trait]
641658
pub trait BuildHasher {
642659
/// Type of the hasher that will be created.
643660
#[stable(since = "1.7.0", feature = "build_hasher")]
@@ -698,9 +715,10 @@ pub trait BuildHasher {
698715
/// );
699716
/// ```
700717
#[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
701-
fn hash_one<T: Hash>(&self, x: T) -> u64
718+
fn hash_one<T: ~const Hash + ~const Destruct>(&self, x: T) -> u64
702719
where
703720
Self: Sized,
721+
Self::Hasher: ~const Hasher + ~const Destruct,
704722
{
705723
let mut hasher = self.build_hasher();
706724
x.hash(&mut hasher);
@@ -764,7 +782,8 @@ impl<H> fmt::Debug for BuildHasherDefault<H> {
764782
}
765783

766784
#[stable(since = "1.7.0", feature = "build_hasher")]
767-
impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> {
785+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
786+
impl<H: ~const Default + Hasher> const BuildHasher for BuildHasherDefault<H> {
768787
type Hasher = H;
769788

770789
fn build_hasher(&self) -> H {
@@ -806,14 +825,15 @@ mod impls {
806825
macro_rules! impl_write {
807826
($(($ty:ident, $meth:ident),)*) => {$(
808827
#[stable(feature = "rust1", since = "1.0.0")]
809-
impl Hash for $ty {
828+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
829+
impl const Hash for $ty {
810830
#[inline]
811-
fn hash<H: Hasher>(&self, state: &mut H) {
831+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
812832
state.$meth(*self)
813833
}
814834

815835
#[inline]
816-
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
836+
fn hash_slice<H: ~const Hasher>(data: &[$ty], state: &mut H) {
817837
let newlen = data.len() * mem::size_of::<$ty>();
818838
let ptr = data.as_ptr() as *const u8;
819839
// SAFETY: `ptr` is valid and aligned, as this macro is only used
@@ -842,54 +862,60 @@ mod impls {
842862
}
843863

844864
#[stable(feature = "rust1", since = "1.0.0")]
845-
impl Hash for bool {
865+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
866+
impl const Hash for bool {
846867
#[inline]
847-
fn hash<H: Hasher>(&self, state: &mut H) {
868+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
848869
state.write_u8(*self as u8)
849870
}
850871
}
851872

852873
#[stable(feature = "rust1", since = "1.0.0")]
853-
impl Hash for char {
874+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
875+
impl const Hash for char {
854876
#[inline]
855-
fn hash<H: Hasher>(&self, state: &mut H) {
877+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
856878
state.write_u32(*self as u32)
857879
}
858880
}
859881

860882
#[stable(feature = "rust1", since = "1.0.0")]
861-
impl Hash for str {
883+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
884+
impl const Hash for str {
862885
#[inline]
863-
fn hash<H: Hasher>(&self, state: &mut H) {
886+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
864887
state.write_str(self);
865888
}
866889
}
867890

868891
#[stable(feature = "never_hash", since = "1.29.0")]
869-
impl Hash for ! {
892+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
893+
impl const Hash for ! {
870894
#[inline]
871-
fn hash<H: Hasher>(&self, _: &mut H) {
895+
fn hash<H: ~const Hasher>(&self, _: &mut H) {
872896
*self
873897
}
874898
}
875899

876900
macro_rules! impl_hash_tuple {
877901
() => (
878902
#[stable(feature = "rust1", since = "1.0.0")]
879-
impl Hash for () {
903+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
904+
impl const Hash for () {
880905
#[inline]
881-
fn hash<H: Hasher>(&self, _state: &mut H) {}
906+
fn hash<H: ~const Hasher>(&self, _state: &mut H) {}
882907
}
883908
);
884909

885910
( $($name:ident)+) => (
886911
maybe_tuple_doc! {
887912
$($name)+ @
888913
#[stable(feature = "rust1", since = "1.0.0")]
889-
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
914+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
915+
impl<$($name: ~const Hash),+> const Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
890916
#[allow(non_snake_case)]
891917
#[inline]
892-
fn hash<S: Hasher>(&self, state: &mut S) {
918+
fn hash<S: ~const Hasher>(&self, state: &mut S) {
893919
let ($(ref $name,)+) = *self;
894920
$($name.hash(state);)+
895921
}
@@ -932,24 +958,27 @@ mod impls {
932958
impl_hash_tuple! { T B C D E F G H I J K L }
933959

934960
#[stable(feature = "rust1", since = "1.0.0")]
935-
impl<T: Hash> Hash for [T] {
961+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
962+
impl<T: ~const Hash> const Hash for [T] {
936963
#[inline]
937-
fn hash<H: Hasher>(&self, state: &mut H) {
964+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
938965
state.write_length_prefix(self.len());
939966
Hash::hash_slice(self, state)
940967
}
941968
}
942969

943970
#[stable(feature = "rust1", since = "1.0.0")]
944-
impl<T: ?Sized + Hash> Hash for &T {
971+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
972+
impl<T: ?Sized + ~const Hash> const Hash for &T {
945973
#[inline]
946-
fn hash<H: Hasher>(&self, state: &mut H) {
974+
fn hash<H: ~const Hasher>(&self, state: &mut H) {
947975
(**self).hash(state);
948976
}
949977
}
950978

951979
#[stable(feature = "rust1", since = "1.0.0")]
952-
impl<T: ?Sized + Hash> Hash for &mut T {
980+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
981+
impl<T: ?Sized + ~const Hash> const Hash for &mut T {
953982
#[inline]
954983
fn hash<H: Hasher>(&self, state: &mut H) {
955984
(**self).hash(state);

library/core/src/hash/sip.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ macro_rules! load_int_le {
118118
/// Safety: this performs unchecked indexing of `buf` at `start..start+len`, so
119119
/// that must be in-bounds.
120120
#[inline]
121-
unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
121+
const unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
122122
debug_assert!(len < 8);
123123
let mut i = 0; // current byte index (from LSB) in the output u64
124124
let mut out = 0;
@@ -138,7 +138,8 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
138138
out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8);
139139
i += 1;
140140
}
141-
debug_assert_eq!(i, len);
141+
//FIXME(fee1-dead): use debug_assert_eq
142+
debug_assert!(i == len);
142143
out
143144
}
144145

@@ -150,8 +151,9 @@ impl SipHasher {
150151
since = "1.13.0",
151152
note = "use `std::collections::hash_map::DefaultHasher` instead"
152153
)]
154+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
153155
#[must_use]
154-
pub fn new() -> SipHasher {
156+
pub const fn new() -> SipHasher {
155157
SipHasher::new_with_keys(0, 0)
156158
}
157159

@@ -162,8 +164,9 @@ impl SipHasher {
162164
since = "1.13.0",
163165
note = "use `std::collections::hash_map::DefaultHasher` instead"
164166
)]
167+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
165168
#[must_use]
166-
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
169+
pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
167170
SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) })
168171
}
169172
}
@@ -176,7 +179,8 @@ impl SipHasher13 {
176179
since = "1.13.0",
177180
note = "use `std::collections::hash_map::DefaultHasher` instead"
178181
)]
179-
pub fn new() -> SipHasher13 {
182+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
183+
pub const fn new() -> SipHasher13 {
180184
SipHasher13::new_with_keys(0, 0)
181185
}
182186

@@ -187,14 +191,15 @@ impl SipHasher13 {
187191
since = "1.13.0",
188192
note = "use `std::collections::hash_map::DefaultHasher` instead"
189193
)]
190-
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
194+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
195+
pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
191196
SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) }
192197
}
193198
}
194199

195200
impl<S: Sip> Hasher<S> {
196201
#[inline]
197-
fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
202+
const fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
198203
let mut state = Hasher {
199204
k0: key0,
200205
k1: key1,
@@ -209,7 +214,7 @@ impl<S: Sip> Hasher<S> {
209214
}
210215

211216
#[inline]
212-
fn reset(&mut self) {
217+
const fn reset(&mut self) {
213218
self.length = 0;
214219
self.state.v0 = self.k0 ^ 0x736f6d6570736575;
215220
self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
@@ -220,7 +225,8 @@ impl<S: Sip> Hasher<S> {
220225
}
221226

222227
#[stable(feature = "rust1", since = "1.0.0")]
223-
impl super::Hasher for SipHasher {
228+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
229+
impl const super::Hasher for SipHasher {
224230
#[inline]
225231
fn write(&mut self, msg: &[u8]) {
226232
self.0.hasher.write(msg)
@@ -238,7 +244,8 @@ impl super::Hasher for SipHasher {
238244
}
239245

240246
#[unstable(feature = "hashmap_internals", issue = "none")]
241-
impl super::Hasher for SipHasher13 {
247+
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
248+
impl const super::Hasher for SipHasher13 {
242249
#[inline]
243250
fn write(&mut self, msg: &[u8]) {
244251
self.hasher.write(msg)
@@ -255,7 +262,7 @@ impl super::Hasher for SipHasher13 {
255262
}
256263
}
257264

258-
impl<S: Sip> super::Hasher for Hasher<S> {
265+
impl<S: ~const Sip> const super::Hasher for Hasher<S> {
259266
// Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
260267
// for this type. We could add them, copy the `short_write` implementation
261268
// in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
@@ -335,7 +342,7 @@ impl<S: Sip> super::Hasher for Hasher<S> {
335342
}
336343
}
337344

338-
impl<S: Sip> Clone for Hasher<S> {
345+
impl<S: Sip> const Clone for Hasher<S> {
339346
#[inline]
340347
fn clone(&self) -> Hasher<S> {
341348
Hasher {
@@ -359,6 +366,7 @@ impl<S: Sip> Default for Hasher<S> {
359366
}
360367

361368
#[doc(hidden)]
369+
#[const_trait]
362370
trait Sip {
363371
fn c_rounds(_: &mut State);
364372
fn d_rounds(_: &mut State);
@@ -367,7 +375,7 @@ trait Sip {
367375
#[derive(Debug, Clone, Default)]
368376
struct Sip13Rounds;
369377

370-
impl Sip for Sip13Rounds {
378+
impl const Sip for Sip13Rounds {
371379
#[inline]
372380
fn c_rounds(state: &mut State) {
373381
compress!(state);
@@ -384,7 +392,7 @@ impl Sip for Sip13Rounds {
384392
#[derive(Debug, Clone, Default)]
385393
struct Sip24Rounds;
386394

387-
impl Sip for Sip24Rounds {
395+
impl const Sip for Sip24Rounds {
388396
#[inline]
389397
fn c_rounds(state: &mut State) {
390398
compress!(state);

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
#![feature(const_float_bits_conv)]
113113
#![feature(const_float_classify)]
114114
#![feature(const_fmt_arguments_new)]
115+
#![feature(const_hash)]
115116
#![feature(const_heap)]
116117
#![feature(const_convert)]
117118
#![feature(const_index_range_slice_index)]

0 commit comments

Comments
 (0)