Skip to content

Regression: derive(Hash) no longer constant since 1.45, depends on bit-width and endianness #90230

@infinity0

Description

@infinity0

Cargo's test_cratesio_hash fails with rust 1.56.0 on Debian systems that are not little-endian 64-bit. Digging deeper, I found the problem has existed in rustc since 1.45, using only the following test program that uses the rust standard library only, no cargo code at all:

use std::hash::{Hash, Hasher, SipHasher};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SourceKind {
    Git(GitReference),
    Path,
    Registry,
    LocalRegistry,
    Directory,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GitReference {
    Tag(String),
    Branch(String),
    Rev(String),
    DefaultBranch,
}

pub fn hash_pair(r: SourceKind, a: &str) -> u64 {
    let mut hasher = SipHasher::new();
    r.hash(&mut hasher);
    a.hash(&mut hasher);
    hasher.finish()
}

fn main() {
	assert_eq!(
		hash_pair(SourceKind::Registry, "https://github.com/rust-lang/crates.io-index"),
		//0x1ecc6299db9ec823
		//0x 1e cc 62 99 db 9e c8 23
		0x23c89edb9962cc1e // little-endian
	);
}

The program fails with rust-1.45.0-i686-unknown-linux-gnu and later, and passes with rust-1.44.0-i686-unknown-linux-gnu and earlier.

The issue causes cargo's test_cratesio_hash to fail on Debian, but the underlying problem is not Debian-specific. Failing values:

Little-endian 32-bit 0x1285ae84e5963aae

Big-endian 64-bit 0xeae4ba8cbf2ce1c7

Big-endian 32-bit 0xb420f105fcaca6de

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions