From c199d253867085dae44f6946d7085a991abe17c8 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Thu, 6 Apr 2017 21:59:08 +0200 Subject: [PATCH 1/5] rephrased std::hash::BuildHasherDefault docs Part of #29357. * split summary and explanation more clearly * added link to nomicon for "zero-sized" * "does not need construction" -> say how it can be created, and that it doesn't need to be done with `HashMap` or `HashSet` --- src/libcore/hash/mod.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 756d472eca8d4..0d34aeb7cb731 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -285,11 +285,17 @@ pub trait BuildHasher { fn build_hasher(&self) -> Self::Hasher; } -/// The `BuildHasherDefault` structure is used in scenarios where one has a -/// type that implements [`Hasher`] and [`Default`], but needs that type to -/// implement [`BuildHasher`]. +/// Used to create a default [`BuildHasher`] instance for types that implement +/// [`Hasher`] and [`Default`]. /// -/// This structure is zero-sized and does not need construction. +/// `BuildHasherDefault` can be used when a type `H` implements [`Hasher`] and +/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is +/// defined. +/// +/// Any `BuildHasherDefault` is [zero-sized]. It can be created with +/// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or +/// [`HashSet`], this doesn't need to be done, since they implement appropriate +/// [`Default`] instances themselves. /// /// # Examples /// @@ -322,8 +328,11 @@ pub trait BuildHasher { /// /// [`BuildHasher`]: trait.BuildHasher.html /// [`Default`]: ../default/trait.Default.html +/// [method.default]: #method.default /// [`Hasher`]: trait.Hasher.html /// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`HashSet`]: ../../std/collections/struct.HashSet.html +/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts #[stable(since = "1.7.0", feature = "build_hasher")] pub struct BuildHasherDefault(marker::PhantomData); From e88a511fd50276b2d88edf9a7a7bbf6a89ca9f68 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Thu, 6 Apr 2017 22:32:51 +0200 Subject: [PATCH 2/5] improved std::hash::BuildHasher docs Part of #29357. * split summary and explanation more clearly, while expanding the explanation to make the reason for `BuildHasher` existing more clear * added an example illustrating that `Hasher`s created by one `BuildHasher` should be identical * added links * repeated the fact that hashers produced should be identical in `build_hasher`s method docs --- src/libcore/hash/mod.rs | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 0d34aeb7cb731..b24938b908a6f 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -258,12 +258,35 @@ pub trait Hasher { } } -/// A `BuildHasher` is typically used as a factory for instances of `Hasher` -/// which a `HashMap` can then use to hash keys independently. +/// A trait for creating instances of [`Hasher`]. /// -/// Note that for each instance of `BuildHasher`, the created hashers should be -/// identical. That is, if the same stream of bytes is fed into each hasher, the -/// same output will also be generated. +/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create +/// [`Hasher`]s for each key such that they are hashed independently of one +/// another, since [`Hasher`]s contain state. +/// +/// For each instance of `BuildHasher`, the [`Hasher`]s created by +/// [`build_hasher`] should be identical. That is, if the same stream of bytes +/// is fed into each hasher, the same output will also be generated. +/// +/// # Examples +/// +/// ``` +/// use std::collections::hash_map::RandomState; +/// use std::hash::{BuildHasher, Hasher}; +/// +/// let s = RandomState::new(); +/// let mut hasher_1 = s.build_hasher(); +/// let mut hasher_2 = s.build_hasher(); +/// +/// hasher_1.write_u32(8128); +/// hasher_2.write_u32(8128); +/// +/// assert_eq!(hasher_1.finish(), hasher_2.finish()); +/// ``` +/// +/// [`build_hasher`]: #method.build_hasher +/// [`Hasher`]: trait.Hasher.html +/// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")] pub trait BuildHasher { /// Type of the hasher that will be created. @@ -272,6 +295,9 @@ pub trait BuildHasher { /// Creates a new hasher. /// + /// Each call to `build_hasher` on the same instance should produce identical + /// [`Hasher`]s. + /// /// # Examples /// /// ``` @@ -281,6 +307,8 @@ pub trait BuildHasher { /// let s = RandomState::new(); /// let new_s = s.build_hasher(); /// ``` + /// + /// [`Hasher`]: trait.Hasher.html #[stable(since = "1.7.0", feature = "build_hasher")] fn build_hasher(&self) -> Self::Hasher; } From 37275b6fc3635291d19331974e361c1ccd02a467 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Thu, 6 Apr 2017 23:39:32 +0200 Subject: [PATCH 3/5] improved std::hash::Hash docs Part of #29357. * merged "Derivable" and "How can I implement `Hash`?" sections into one "Implementing `Hash`" section to aid coherency * added an example for `#[derive(Hash)]` * moved part about relation between `Hash` and `Eq` into a new "`Hash` and `Eq`" section; changed wording to be more consistent with `HashMap` and `HashSet`'s * explicitly mentioned `#[derive(PartialEq, Eq, Hash)]` in the new section * changed method summaries for consistency, adding links and examples --- src/libcore/hash/mod.rs | 83 ++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index b24938b908a6f..130a75a7027ac 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -107,29 +107,25 @@ mod sip; /// A hashable type. /// -/// The `H` type parameter is an abstract hash state that is used by the `Hash` -/// to compute the hash. +/// Types implementing `Hash` are able to be [`hash`]ed with an instance of +/// [`Hasher`]. /// -/// If you are also implementing [`Eq`], there is an additional property that -/// is important: +/// ## Implementing `Hash` /// -/// ```text -/// k1 == k2 -> hash(k1) == hash(k2) -/// ``` -/// -/// In other words, if two keys are equal, their hashes should also be equal. -/// [`HashMap`] and [`HashSet`] both rely on this behavior. +/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`. +/// The resulting hash will be the combination of the values from calling +/// [`hash`] on each field. /// -/// ## Derivable -/// -/// This trait can be used with `#[derive]` if all fields implement `Hash`. -/// When `derive`d, the resulting hash will be the combination of the values -/// from calling [`.hash`] on each field. -/// -/// ## How can I implement `Hash`? +/// ``` +/// #[derive(Hash)] +/// struct Rustacean { +/// name: String, +/// country: String, +/// } +/// ``` /// -/// If you need more control over how a value is hashed, you need to implement -/// the `Hash` trait: +/// If you need more control over how a value is hash, you can of course +/// implement the `Hash` trait yourself: /// /// ``` /// use std::hash::{Hash, Hasher}; @@ -148,17 +144,60 @@ mod sip; /// } /// ``` /// +/// ## `Hash` and `Eq` +/// +/// When implementing both `Hash` and [`Eq`], it is important that the following +/// property holds: +/// +/// ```text +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// In other words, if two keys are equal, their hashes must also be equal. +/// [`HashMap`] and [`HashSet`] both rely on this behavior. +/// +/// Thankfully, you won't need to worry about upholding this property when +/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`. +/// /// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`Hasher`]: trait.Hasher.html /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html -/// [`.hash`]: #tymethod.hash +/// [`hash`]: #tymethod.hash #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { - /// Feeds this value into the state given, updating the hasher as necessary. + /// Feeds this value into the given [`Hasher`]. + /// + /// # Examples + /// + /// ``` + /// use std::collections::hash_map::DefaultHasher; + /// use std::hash::{Hash, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// 7920.hash(&mut hasher); + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + /// + /// [`Hasher`]: trait.Hasher.html #[stable(feature = "rust1", since = "1.0.0")] fn hash(&self, state: &mut H); - /// Feeds a slice of this type into the state provided. + /// Feeds a slice of this type into the given [`Hasher`]. + /// + /// # Examples + /// + /// ``` + /// use std::collections::hash_map::DefaultHasher; + /// use std::hash::{Hash, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// let numbers = [6, 28, 496, 8128]; + /// Hash::hash_slice(&numbers, &mut hasher); + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + /// + /// [`Hasher`]: trait.Hasher.html #[stable(feature = "hash_slice", since = "1.3.0")] fn hash_slice(data: &[Self], state: &mut H) where Self: Sized From 0dce5862fcb8677f416e0bf1eb75b8e53108c70c Mon Sep 17 00:00:00 2001 From: lukaramu Date: Fri, 7 Apr 2017 00:39:27 +0200 Subject: [PATCH 4/5] improved std::hash::Hasher docs Part of #29357. * rephrased summary sentences to be less redundant * expanded top-level docs, adding a usage example and links to relevant methods (`finish`, `write` etc) as well as `Hash` * added examples to the `finish` and `write` methods --- src/libcore/hash/mod.rs | 59 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 130a75a7027ac..4ebec401669c5 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -208,18 +208,73 @@ pub trait Hash { } } -/// A trait which represents the ability to hash an arbitrary stream of bytes. +/// A trait for hashing an arbitrary stream of bytes. +/// +/// Instances of `Hasher` usually represent state that is changed while hashing +/// data. +/// +/// `Hasher` provides a fairly basic interface for retrieving the generated hash +/// (with [`finish`]), and writing integers as well as slices of bytes into an +/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher` +/// instances are used in conjunction with the [`Hash`] trait. +/// +/// # Examples +/// +/// ``` +/// use std::collections::hash_map::DefaultHasher; +/// use std::hash::Hasher; +/// +/// let mut hasher = DefaultHasher::new(); +/// +/// hasher.write_u32(1989); +/// hasher.write_u8(11); +/// hasher.write_u8(9); +/// hasher.write(b"Huh?"); +/// +/// println!("Hash is {:x}!", hasher.finish()); +/// ``` +/// +/// [`Hash`]: trait.Hash.html +/// [`finish`]: #tymethod.finish +/// [`write`]: #tymethod.write +/// [`write_u8`]: #method.write_u8 #[stable(feature = "rust1", since = "1.0.0")] pub trait Hasher { /// Completes a round of hashing, producing the output hash generated. + /// + /// # Examples + /// + /// ``` + /// use std::collections::hash_map::DefaultHasher; + /// use std::hash::Hasher; + /// + /// let mut hasher = DefaultHasher::new(); + /// hasher.write(b"Cool!"); + /// + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn finish(&self) -> u64; /// Writes some data into this `Hasher`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::hash_map::DefaultHasher; + /// use std::hash::Hasher; + /// + /// let mut hasher = DefaultHasher::new(); + /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; + /// + /// hasher.write(&data); + /// + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, bytes: &[u8]); - /// Write a single `u8` into this hasher. + /// Writes a single `u8` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] fn write_u8(&mut self, i: u8) { From 12d7c3d9d8e6694b693e9ee30402063b6cef18ab Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 10 Apr 2017 17:50:54 +0200 Subject: [PATCH 5/5] Fixed indent, grammar, and link in std::hash docs --- src/libcore/hash/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 4ebec401669c5..f68361e852277 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -119,12 +119,12 @@ mod sip; /// ``` /// #[derive(Hash)] /// struct Rustacean { -/// name: String, -/// country: String, +/// name: String, +/// country: String, /// } /// ``` /// -/// If you need more control over how a value is hash, you can of course +/// If you need more control over how a value is hashed, you can of course /// implement the `Hash` trait yourself: /// /// ``` @@ -378,7 +378,7 @@ pub trait Hasher { /// assert_eq!(hasher_1.finish(), hasher_2.finish()); /// ``` /// -/// [`build_hasher`]: #method.build_hasher +/// [`build_hasher`]: #tymethod.build_hasher /// [`Hasher`]: trait.Hasher.html /// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")]