Skip to content

Commit

Permalink
std: Stabilize the hash module
Browse files Browse the repository at this point in the history
This commit is an implementation of [RFC 823][rfc] which is another pass over
the `std::hash` module for stabilization. The contents of the module were not
entirely marked stable, but some portions which remained quite similar to the
previous incarnation are now marked `#[stable]`. Specifically:

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0823-hash-simplification.md

* `std::hash` is now stable (the name)
* `Hash` is now stable
* `Hash::hash` is now stable
* `Hasher` is now stable
* `SipHasher` is now stable
* `SipHasher::new` and `new_with_keys` are now stable
* `Hasher for SipHasher` is now stable
* Many `Hash` implementations are now stable

All other portions of the `hash` module remain `#[unstable]` as they are less
commonly used and were recently redesigned.

This commit is a breaking change due to the modifications to the `std::hash` API
and more details can be found on the [RFC][rfc].

Closes #22467
[breaking-change]
  • Loading branch information
alexcrichton committed Feb 18, 2015
1 parent dfc5c0f commit f83e23a
Show file tree
Hide file tree
Showing 54 changed files with 4,988 additions and 356 deletions.
8 changes: 8 additions & 0 deletions src/liballoc/arc.rs
Expand Up @@ -605,11 +605,19 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
fn default() -> Arc<T> { Arc::new(Default::default()) }
}

#[cfg(stage0)]
impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
fn hash(&self, state: &mut H) {
(**self).hash(state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for Arc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}

#[cfg(test)]
mod tests {
Expand Down
25 changes: 17 additions & 8 deletions src/liballoc/boxed.rs
Expand Up @@ -10,13 +10,14 @@

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Boxes are useful in two situations: recursive data structures, and occasionally when returning
//! data. [The Pointer chapter of the Book](../../../book/pointers.html#best-practices-1) explains
//! these cases in detail.
//! Boxes are useful in two situations: recursive data structures, and
//! occasionally when returning data. [The Pointer chapter of the
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
//! detail.
//!
//! # Examples
//!
Expand Down Expand Up @@ -58,8 +59,8 @@ use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use core::raw::TraitObject;

/// A value that represents the heap. This is the default place that the `box` keyword allocates
/// into when no place is supplied.
/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
Expand Down Expand Up @@ -219,12 +220,20 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[cfg(stage0)]
impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}

/// Extension methods for an owning `Any` trait object.
#[unstable(feature = "alloc",
Expand Down
1 change: 0 additions & 1 deletion src/liballoc/lib.rs
Expand Up @@ -73,7 +73,6 @@
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![feature(core)]
#![feature(hash)]
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
feature(libc))]

Expand Down
12 changes: 10 additions & 2 deletions src/liballoc/rc.rs
Expand Up @@ -150,7 +150,7 @@ use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::hash::{Hasher, Hash};
use core::marker;
use core::mem::{transmute, min_align_of, size_of, forget};
use core::nonzero::NonZero;
Expand Down Expand Up @@ -599,12 +599,20 @@ impl<T: Ord> Ord for Rc<T> {
}

// FIXME (#18248) Make `T` `Sized?`
impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
#[cfg(stage0)]
impl<S: Hasher, T: Hash<S>> Hash<S> for Rc<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for Rc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display> fmt::Display for Rc<T> {
Expand Down
21 changes: 21 additions & 0 deletions src/libcollections/bit.rs
Expand Up @@ -984,6 +984,7 @@ impl fmt::Debug for Bitv {
}

#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
fn hash(&self, state: &mut S) {
self.nbits.hash(state);
Expand All @@ -992,6 +993,16 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for Bitv {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.nbits.hash(state);
for elem in self.blocks() {
elem.hash(state);
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for Bitv {
Expand Down Expand Up @@ -1756,13 +1767,23 @@ impl fmt::Debug for BitvSet {
}
}

#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
fn hash(&self, state: &mut S) {
for pos in self {
pos.hash(state);
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for BitvSet {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
for pos in self {
pos.hash(state);
}
}
}

/// An iterator for `BitvSet`.
#[derive(Clone)]
Expand Down
10 changes: 10 additions & 0 deletions src/libcollections/btree/map.rs
Expand Up @@ -843,6 +843,7 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
}
}

#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
fn hash(&self, state: &mut S) {
Expand All @@ -851,6 +852,15 @@ impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
}
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
for elt in self {
elt.hash(state);
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Default for BTreeMap<K, V> {
Expand Down
15 changes: 14 additions & 1 deletion src/libcollections/dlist.rs
Expand Up @@ -27,7 +27,9 @@ use alloc::boxed::Box;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{Writer, Hasher, Hash};
use core::hash::{Hasher, Hash};
#[cfg(stage0)]
use core::hash::Writer;
use core::iter::{self, FromIterator, IntoIterator};
use core::mem;
use core::ptr;
Expand Down Expand Up @@ -926,6 +928,7 @@ impl<A: fmt::Debug> fmt::Debug for DList<A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
fn hash(&self, state: &mut S) {
self.len().hash(state);
Expand All @@ -934,6 +937,16 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<A: Hash> Hash for DList<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for elt in self {
elt.hash(state);
}
}
}

#[cfg(test)]
mod tests {
Expand Down
1 change: 0 additions & 1 deletion src/libcollections/lib.rs
Expand Up @@ -26,7 +26,6 @@
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(hash)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
Expand Down
14 changes: 13 additions & 1 deletion src/libcollections/ring_buf.rs
Expand Up @@ -31,7 +31,8 @@ use core::ops::{Index, IndexMut};
use core::ptr;
use core::raw::Slice as RawSlice;

use core::hash::{Writer, Hash, Hasher};
use core::hash::{Hash, Hasher};
#[cfg(stage0)] use core::hash::Writer;
use core::cmp;

use alloc::heap;
Expand Down Expand Up @@ -1667,6 +1668,7 @@ impl<A: Ord> Ord for RingBuf<A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
fn hash(&self, state: &mut S) {
self.len().hash(state);
Expand All @@ -1675,6 +1677,16 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<A: Hash> Hash for RingBuf<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for elt in self {
elt.hash(state);
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A> Index<usize> for RingBuf<A> {
Expand Down
9 changes: 9 additions & 0 deletions src/libcollections/string.rs
Expand Up @@ -833,12 +833,21 @@ impl fmt::Debug for String {
}

#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
#[cfg(stage0)]
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
#[inline]
fn hash(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for String {
#[inline]
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}

#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
Expand Down
9 changes: 9 additions & 0 deletions src/libcollections/vec.rs
Expand Up @@ -1302,12 +1302,21 @@ impl<T:Clone> Clone for Vec<T> {
}
}

#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<T: Hash> Hash for Vec<T> {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Index<usize> for Vec<T> {
Expand Down
19 changes: 18 additions & 1 deletion src/libcollections/vec_map.rs
Expand Up @@ -20,7 +20,8 @@ use core::prelude::*;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{Hash, Writer, Hasher};
use core::hash::{Hash, Hasher};
#[cfg(stage0)] use core::hash::Writer;
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
use core::iter;
use core::mem::replace;
Expand Down Expand Up @@ -99,6 +100,7 @@ impl<V> Default for VecMap<V> {
fn default() -> VecMap<V> { VecMap::new() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<V:Clone> Clone for VecMap<V> {
#[inline]
fn clone(&self) -> VecMap<V> {
Expand All @@ -111,6 +113,7 @@ impl<V:Clone> Clone for VecMap<V> {
}
}

#[cfg(stage0)]
impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
fn hash(&self, state: &mut S) {
// In order to not traverse the `VecMap` twice, count the elements
Expand All @@ -123,6 +126,20 @@ impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
count.hash(state);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<V: Hash> Hash for VecMap<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
// In order to not traverse the `VecMap` twice, count the elements
// during iteration.
let mut count: usize = 0;
for elt in self {
elt.hash(state);
count += 1;
}
count.hash(state);
}
}

impl<V> VecMap<V> {
/// Creates an empty `VecMap`.
Expand Down
12 changes: 10 additions & 2 deletions src/libcore/array.rs
Expand Up @@ -17,7 +17,7 @@
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use fmt;
use hash::{Hash, Hasher, self};
use hash::{Hash, self};
use iter::IntoIterator;
use marker::Copy;
use ops::Deref;
Expand All @@ -35,11 +35,19 @@ macro_rules! array_impls {
}
}

impl<S: hash::Writer + Hasher, T: Hash<S>> Hash<S> for [T; $N] {
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
fn hash(&self, state: &mut S) {
Hash::hash(&self[], state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for [T; $N] {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Hash::hash(&self[], state)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
Expand Down

0 comments on commit f83e23a

Please sign in to comment.