Change:
As discussed at : the code of specifically passes an extra 0xFF byte to the Hasher, so that values like and hash differently ( in ). This is a subtle property of hashing and should probably be mentioned in the documentation for — particularly as already says “you cannot assume, for example, that a call is equivalent to four calls of ” which could be sloppily interpreted as an expectation that a good implementation will handle “quoting” of sequential calls itself. If an implementor of fails to have this property, it could compromise the hash-DoS resistance that Rust tries to offer by default. labels: +A-docs +T-libs-api +C-enhancement <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Should hand-implementors of instances keep this in mind as well? For instance, for the following struct: can auto-generate the following implementation (and I assume does the same): There are no magic bytes here, as in . Is that okay? Do we run the risk of this hashing to the same value as ? (Actually I will test this, one moment...)
The results are: Is this expected?
Different types hashing to the same value are not a problem. What is a problem is different (unequal) values of the same type hashing to the same value (for all s).
claim
Collisions are inevitable, and it shouldn't matter between s for the same reason it doesn't for different types. I do agree that types should try to avoid collisions, as long as we make this kind of thing a suggestion of best practice, not stated as a hard requirement of the trait.
Collisions in are inevitable. Collisions in are not inevitable. One benefit of not creating collisions in is that it then is possible to implement a randomized with mathematically bounded small collision probability for any two unequal inputs (using universal hashing). If there is a deterministic collision in , then it becomes impossible, because you have 100% collision probability for that pair of inputs.
OK, that's a compelling distinction between the responsibilities of and . Is it always possible to do this perfectly on the side? I suppose it must be -- if there's a feature that makes values different from an perspective, that is an input that should also be used for hashing.
[Trying again to set labels since I typoed the first one:] label: +A-docs +T-libs-api +C-enhancement
I am not sure it's always possible, in theory you could imagine some contrived algorithm that makes it computationally expensive to in a way fully consistent with it, but I can't think of a practical example. I think it would be fine to say that if can't come up with a proper algorithm that has this property, you shouldn't implement (perhaps you'd be better served by in that case).
For the docs, would it make sense to discuss the case of in a new paragraph after this paragraph: The paragraph could start with something like:
Let's then note that is thus currently "bugged" in that regard (c.f. my snippet in the URLO thread).
I gave this a try! I might not have understood correctly, however...
FWIW, being prefix-free can also be unfortunate sometimes. For example, is more efficient to hash than because the latter hashes the length to match the hash of the corresponding -- and slices do that so it's prefix-free. I don't know that there's a great answer for this, though...
See .
Is there a real reason and of length 2 have to hash to the same thing? I don't think it's that easy to accidentally coerce them to a wrong thing when hashing (surely doesn't do that). In any case, slices are already prefix-free (as long as T is) (and I think that's good, otherwise you'd have a lot of collisions on different short slices), so this issue doesn't change that.
Yes, requires it. You can have a with array keys and then do lookups with a slice.
Nominated this for discussion.
I a in after I forget why it was that way too :)
One possibility would be to leave the choice of whether to add a prefix to the via some form of hint: performance-oriented hashers would opt to skip the prefix while security-oriented ones would opt to keep it. This could be done with an optional method on the trait:
I dispute the idea that making the encoding non-prefix-free is a performance optimization, for the same reason an empty implementation that does nothing would not really be a performance optimization. Potential huge cost of resulting hash collisions (for certain kinds of data) is likely to greatly overwhelm any such (tiny) savings from lazy hashing. I think of this as a bug because it defeats the assumptions of mathematical analysis of the performance properties of hash tables with certain hashers.

Discussion:
/// Thankfully, you won't need to worry about upholding this property when /// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`. /// <ins> /// ## Prefix collisions /// /// Implementations of `hash` should ensure that the data they /// pass to the `Hasher` are prefix-free. That is, /// unequal values should cause two different sequences of values to be written, /// and neither of the two sequences should be a prefix of the other. /// /// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", /// "bc")` hash differently. /// </ins> /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`hash`]: Hash::hash <ins> /// [impl]: ../../std/primitive.str.html#impl-Hash </ins> #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Hash"] pub trait Hash {