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

Lint: Warn if only one of {Hash, PartialEq} is derived, the other manually implemented #1499

Closed
untitaker opened this issue Feb 13, 2016 · 7 comments

Comments

@untitaker
Copy link
Contributor

This is a continuation of rust-lang/rust#29758

The derived Hash and PartialEq implementations for structs rely on the struct fields' implementations of those traits for comparison and hashing. If I manually implement one of those traits by myself, the following rule might be broken:

k1 == k2 -> hash(k1) == hash(k2)

(found in the docs of Hash)

See the previous issue on top for an example.

This seems like a potential pitfall. In my particular case, I had a struct with derive(Eq, PartialEq, Hash), and wanted to change the way equality works. So I manually implemented PartialEq, but forgot to do the same for Hash as well. Luckily @eefriedman reminded me of the incorrect Hash impl during code review, but the code compiled perfectly fine.

I think rustc could detect this kind of situation. IMO the compiler should warn if one of {Hash, PartialEq} is derived, and the other trait manually implemented, because:

  1. It's unlikely that the developer intentionally derives only one of those traits.
  2. It's unlikely (if not impossible) that the struct's hashing and equivalency behavior satisfy the rule above AND differ in behavior from impls you get with derive
@pnkfelix
Copy link
Member

I think I have seen lots of code that derives PartialEq without any impl of Hash (derived or not)

I wouldn't want warnings on all those cases

@untitaker untitaker changed the title Lint: Warn if only one of {Hash, PartialEq} is derived Lint: Warn if only one of {Hash, PartialEq} is derived, the other manually implemented Feb 13, 2016
@untitaker
Copy link
Contributor Author

I think I have seen lots of code that derives PartialEq without any impl of Hash (derived or not)

The proposal in bold doesn't concern those types. I've now updated the title as well.

To be clear:

  • #[derive(PartialEq, Hash)] is fine
  • #[derive(PartialEq)] is fine
  • #[derive(PartialEq)] and manually impl Hash should yield a warning
  • #[derive(Hash)] and manually impl PartialEq should yield a warning

@sfackler
Copy link
Member

This seems like something that can be handled in e.g. clippy.

@oli-obk
Copy link
Contributor

oli-obk commented Feb 15, 2016

This seems like something that can be handled in e.g. clippy.

One direction is in clippy:

https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq

@untitaker
Copy link
Contributor Author

This is awesome!

On Mon, Feb 15, 2016 at 01:39:17AM -0800, Oliver Schneider wrote:

This seems like something that can be handled in e.g. clippy.

One direction is in clippy:

https://github.com/Manishearth/rust-clippy/wiki#derive_hash_not_eq


Reply to this email directly or view it on GitHub:
#1499 (comment)

@oli-obk
Copy link
Contributor

oli-obk commented Feb 16, 2016

Clippy now requires either both derived or both not derived: https://github.com/Manishearth/rust-clippy/pull/676

@untitaker
Copy link
Contributor Author

Let's close this issue for now and see how the lint in Clippy works out. If it works well enough I'd still like to see it in rustc itself, but it's probably too early to tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants