Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derived Hash for repr(u8) enum submits 8 bytes to Hasher instead of 1 #39137

Closed
kryptan opened this issue Jan 17, 2017 · 12 comments · Fixed by #102857
Closed

Derived Hash for repr(u8) enum submits 8 bytes to Hasher instead of 1 #39137

kryptan opened this issue Jan 17, 2017 · 12 comments · Fixed by #102857
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@kryptan
Copy link
Contributor

kryptan commented Jan 17, 2017

Automatically derived Hash for an enum marked as repr(u8) will hash 8 bytes when it is only necessary to hash just one. When hashing large value containing many such enums this will lead to 8x slower hashing than necessary.

Example:

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

struct H;

impl Hasher for H {
    fn finish(&self) -> u64 {
        unreachable!()
    }

    fn write(&mut self, bytes: &[u8]) {
        println!("{:?}", bytes);
    }
}

#[repr(u8)]
#[derive(Hash)]
enum E {
    A,
    B,
}

fn main() { 
    E::A.hash(&mut H);
}

prints [0, 0, 0, 0, 0, 0, 0, 0] while I expected it to print [0] just like 0u8.hash(&mut H).

This behavior is the same on recent stable, beta and nightly (1.14, 1.15, 1.16).


EDIT: Added second variant to the enum. Previous example with single variant doesn't print anything anymore because of #42709.

@est31
Copy link
Member

est31 commented Jan 17, 2017

Can it be changed at this stage? Wouldn't a change break stability promises of the language?

@brson
Copy link
Contributor

brson commented Jan 18, 2017

I wonder if the performance impact can be quantified in real workloads, or if this mistake shows up elsewhere. I'd guess this is because our enum discriminant intrinsic returns only u64 but not sure.

The impact seems low so we might be able to get away with changing it.

@brson brson added I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 18, 2017
@est31
Copy link
Member

est31 commented Jan 18, 2017

The impact seems low so we might be able to get away with changing it.

For most non trivial hashing algorithms, it will most certainly change generated hashes if such an enum was involved.

There can be situations where you want your hashes to be stable, or when you design some on-disk or over-network format and want to keep the output constant because you need to be compatible with earlier compiles of your program.

Don't know of code which does this but it can't really be cratered...

@durka
Copy link
Contributor

durka commented Jan 18, 2017

That intrinsic may need to change soon to return u128 so we'll have to keep this in mind as a caveat.

@nagisa
Copy link
Member

nagisa commented Jan 18, 2017

Its plausible to change this. We specifically said in documentation of discriminant function, that the discriminant is only guaranteed to not change if it is observed in code compiled by the same compiler version.

I’m not sure how would we go around implementing the change which picks relevant feed method, but at the very least we do have type of enum “remembered” in Discriminant and could use that to deduce the right thing to use.

@durka
Copy link
Contributor

durka commented Jan 18, 2017 via email

stepancheg added a commit to stepancheg/rust that referenced this issue Jun 16, 2017
bors added a commit that referenced this issue Jun 28, 2017
deriv(Hash) for single-variant enum should not hash discriminant

Fixes #39137
@Mark-Simulacrum
Copy link
Member

Reopening -- this was not fixed by #42709. See #42709 (comment).

@durka
Copy link
Contributor

durka commented Jun 28, 2017

It sounds like the consensus here is it's okay to fix this?

@est31
Copy link
Member

est31 commented Jun 28, 2017

If so, we should explicitly document that the values generated by the Hash trait are not stable, and may change between compiler updates for same data.

@Mark-Simulacrum Mark-Simulacrum added C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Jul 26, 2017
@steveklabnik
Copy link
Member

Visiting for triage. Strangely, this code no longer prints. I'm not sure at all why this is.

@kryptan
Copy link
Contributor Author

kryptan commented Dec 7, 2019

Visiting for triage. Strangely, this code no longer prints. I'm not sure at all why this is.

That's because of #42709. I have updated the code (added second variant to the enum).

@saethlin
Copy link
Member

I think this has been done in the meantime. The above code now prints [0].

saethlin added a commit to saethlin/rust that referenced this issue Oct 9, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 16, 2022
…iaskrgr

Rollup of 4 pull requests

Successful merges:

 - rust-lang#102857 (Add a regression test for rust-lang#39137)
 - rust-lang#102953 (Improve docs for `struct_lint_level` function.)
 - rust-lang#103060 (rustdoc: make the help button a link to a page)
 - rust-lang#103115 (Clean up anchors.goml rustdoc GUI test)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors closed this as completed in 91c7d02 Oct 16, 2022
lyming2007 pushed a commit to lyming2007/rust that referenced this issue Oct 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants