Skip to content

derive(Hash) on enum causes hash collision on 32-bit system #21714

Closed
@klutzy

Description

@klutzy
use std::hash::{hash, SipHasher};

#[derive(Hash)]
enum E {
    A = 1,
    B,
}

fn main() {
    let a = hash::<_,   SipHasher>(&E::A);
    let b = hash::<_,   SipHasher>(&E::B);

    println!("{}, {}, {}", a, b, a == b);
}
$ rustc a.rs --target=i686-unknown-linux-gnu && ./a
13715208377448023093, 13715208377448023093, true

Output of -Z unstable-options --pretty=expanded is:

// snip
#[automatically_derived]
impl <__S: ::std::hash::Writer + ::std::hash::Hasher> ::std::hash::Hash<__S>
 for E {
    #[inline]
    fn hash(&self, __arg_0: &mut __S) -> () {
        match (&*self,) {
            (&E::A,) => { ::std::hash::Hash::hash(&1, __arg_0); }
            (&E::B,) => { ::std::hash::Hash::hash(&1us, __arg_0); }
        }
    }
}
// snip

Here A uses 1 (is i32) and B uses 1us for hashing, thus they collide if they have same bit representation.

(was potential issue of #18573)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-syntaxextArea: Syntax extensions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions