Skip to content

Feature request: hash_with at the enum-variant level #121

@Pr0methean

Description

@Pr0methean

Describe the bug
It would be useful to be able to apply the hash_with attribute to an enum variant rather than to individual fields, so that fields can interact if necessary.

To Reproduce
The enum I'd use this on is:

#[derive(Derivative)]
#[derivative(Clone, Debug, Hash, Eq)]
#[repr(u8)]
pub enum ComplexFactor {
    AddSub {
        #[derivative(Hash(hash_with = "crate::algebraic::hash_add_sub"))]
        terms: (Factor, Factor),
        subtract: bool,
    },
    /* and other variants */
}
fn hash_add_sub<H: Hasher>(terms: &(Factor, Factor), state: &mut H) {
    let (left, right) = terms;
    let invariant_hasher_state = RandomState::with_seed(0x1337c0de);
    let left_hash = invariant_hasher_state.hash_one(left);
    let right_hash = invariant_hasher_state.hash_one(right);
    state.write_u64(left_hash.wrapping_add(right_hash));
}

This way I could ensure that x+y and y+x have the same hash, but x-y and y-x don't, and avoid the double hashing of subtraction terms.
Expected behavior
I can replace the above code with:

#[derive(Derivative)]
#[derivative(Clone, Debug, Hash, Eq)]
#[repr(u8)]
pub enum ComplexFactor {
    #[derivative(Hash(hash_with = "crate::algebraic::hash_add_sub"))]
    AddSub {
        terms: (Factor, Factor),
        subtract: bool,
    },
    /* and other variants */
}
fn hash_add_sub<H: Hasher>(terms: &(Factor, Factor), subtract: bool, state: &mut H) {
    let (left, right) = terms;
    if subtract {
        left.hash(state);
        right.hash(state);
    } else {
        let invariant_hasher_state = RandomState::with_seed(0x1337c0de);
        let left_hash = invariant_hasher_state.hash_one(left);
        let right_hash = invariant_hasher_state.hash_one(right);
        state.write_u64(left_hash.wrapping_add(right_hash));
    }
}

Errors

error: Unknown attribute `hash_with` for trait `Hash`
   --> src/algebraic.rs:628:23
    |
628 |     #[derivative(Hash(hash_with = "crate::algebraic::hash...
    |                       ^^^^^^^^^

Version:

$ rustup --version
rustup 1.28.2 (e4f3ad6f8 2025-04-28)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.94.0-nightly (7b5cde737 2025-12-27)`
$ cargo --version
cargo 1.94.0-nightly (94c368ad2 2025-12-26)
  • Version of derivative: 2.2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThe crate does not work as expected

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions