Skip to content

Hashcode in Decimal violates the hash contract #59

Description

@lukstei

The hash implementation in https://github.com/neogenie/fastnum/blob/master/src/decimal/dec/impls/hash.rs violates the Hash contract, because two decimals which are equal can have different hashes, this will lead to issues when using Decimal in HashMapkeys.

This happens can happen when one of the decimals has a different control block value than the other.

Test which replicates the issue:

#[cfg(test)]
mod tests {
    use fastnum::dec128;
    use fastnum::decimal::{Context, RoundingMode, Signals};
    use std::hash::{BuildHasher, BuildHasherDefault, DefaultHasher, Hash, Hasher, RandomState};

    #[test]
    fn test_hash() {
        fn hash<T: Hash>(x: T) -> u64 {
            let mut hasher = DefaultHasher::new();
            x.hash(&mut hasher);
            hasher.finish()
        }

        let price1 = dec128!(1);
        let price2 = dec128!(1.1).floor();
        assert!(!price2.is_op_ok());

        assert_eq!(price1, price2);
        assert_eq!(hash(price1), hash(price1));
        assert_eq!(hash(price1), hash(price2)); // will fail
    }
}

Metadata

Metadata

Assignees

Labels

proposalA proposal and request for comments.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions