Skip to content

impls of PartialEq<str> etc. violate Hash consistency #230

Closed
@mzabaluev

Description

@mzabaluev

This test currently fails:

    use bytes::Bytes;

    use std::{
        collections::hash_map::DefaultHasher,
        hash::{Hash, Hasher},
    };

    fn hash<T: Hash>(v: &T) -> u64 {
        let mut sh = DefaultHasher::new();
        v.hash(&mut sh);
        sh.finish()
    }

    #[test]
    fn hash_fail() {
        let s = "test string";
        let b = Bytes::from(s);
        assert_eq!(b, s);
        assert!(
            hash(&b) == hash(&s),
            "Hashes differ even though values compare as equal",
        );
    }

For things to be proper, this test should not even compile due to lack of an equality impl.
The PartialEq implementations that make the equality operators work between a Bytes value and a string, while convenient, allow two logically equal values to have different hashes. This violates the contract of Hash and therefore is a no-no. The standard library avoids pairing strings and byte slices in equality and comparison operators, and even burns extra CPU to make a string's Hash output pointedly different from that of an equivalent byte slice.

This issue does not affect HashTable because there is no Borrow impl to cross between the key types. But the inconsistency is lurking and can bite even in generic code using Hash by the book.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions