prost icon indicating copy to clipboard operation
prost copied to clipboard

Adding #[derive(Eq)] to type_attribute conflicts with the generated code for Enumeration

Open bliednov opened this issue 4 years ago • 7 comments

The following code stated in the documentation won't work, because enums already derive from Eq, so it produces an error.

# let mut config = prost_build::Config::new();
// Nothing around uses floats, so we can derive real `Eq` in addition to `PartialEq`.
config.type_attribute(".", "#[derive(Eq)]");

Here is an error:

   Compiling test-proto v0.1.0 (/Users/test/pro/co/test/tools/nexttest/test)
error[E0119]: conflicting implementations of trait `std::cmp::Eq` for type `test::Test`:
  --> /Users/test/pro/co/test/tools/nexttest/target/debug/build/test-proto-822a20cdddd51ab3/out/test.rs:37:41
   |
37 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
   |                                         ^^ conflicting implementation for `test::Test`
38 | #[repr(i32)]
39 | #[derive(Eq)]
   |          -- first implementation here

How to add #[derive(Eq)] only to all Messages?

bliednov avatar May 15 '20 14:05 bliednov

IMHO adding it to each message specifically is impractical because if you have even 20 messages, it's already a lot to do by hand, but what if one has 100 different messages? I think there should be a way to add type_attribute to all messages or to all enums.

bliednov avatar May 15 '20 14:05 bliednov

See also #371

danburkert avatar Dec 31 '20 21:12 danburkert

Hitting this also. Ideally would be great of prost-build could just merge derives. Only workaround I could find is to manually list out every non-enum to add Eq and Hash which is pretty painful.

Having some visibility into what prost-build is doing via visitors (or just being able to add a pass that runs over all types) would be a really nice escape hatch for this kind of stuff.

robo-corg avatar Apr 19 '22 17:04 robo-corg

I just ran into this because Rust 1.63.0 now has a new Clippy lint for deriving PartialEq without Eq, which means all of my prost-generated structs are now throwing this warning.

Like @robo-corg said, being able to merge derives would help. This would presumably work not by parsing out the #[derive()] attributes but by having a separate method that takes an Iterator<Item=&str> or something, so it can just dedupe them.

Alternatively there could be some solution specific to Eq. Or, heck, prost could just derive Eq automatically for any struct that doesn't contain a float.

lilyball avatar Aug 19 '22 18:08 lilyball

Imho prost shouldn't be deriving Eq over encoded messages and esp protobuf which have a lot of backwards/forward compat featuers. C++ provides this https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.util.message_differencer which we could try to implement but requires features we are missing. We could add that derive iterator feature but in addition, there are many things that we can add to decorate the codegen and I am not really happy with the current approach. It doesn't feel sustainable to use type_attributes etc or keep adding methods like that. Generally, I would recommend to implement these sort of things on your end via fn/traits etc.

LucioFranco avatar Aug 23 '22 14:08 LucioFranco

@LucioFranco That makes sense. The use case I was using it for was using protobufs as keys in a HashMap and a key value store which is ~~probably~~ definitely a bad idea. The code in question should probably be projecting these onto types managed in the crate or something like that, it is just difficult to do this ergonomically but probably worth doing for the reasons you state.

The right call here seems like allowing Eq to be added as a derive but not automatically adding it, if only to keep confusing errors from occurring. Interestingly it really seems like the argument here could be extended to all traits that are not Clone or Copy. Maybe some warnings or documentation explaining why deriving these traits are bad?

robo-corg avatar Aug 31 '22 19:08 robo-corg

I solved this issue by calling message_attribute instead of type_attribute.

upbqdn avatar Sep 11 '23 13:09 upbqdn