Skip to content

prost-build: add Config::eq_when_safe to gate auto Eq derives (#30) - #1423

Draft
MukundaKatta wants to merge 1 commit into
tokio-rs:masterfrom
MukundaKatta:feat/eq-derive-when-safe
Draft

prost-build: add Config::eq_when_safe to gate auto Eq derives (#30)#1423
MukundaKatta wants to merge 1 commit into
tokio-rs:masterfrom
MukundaKatta:feat/eq-derive-when-safe

Conversation

@MukundaKatta

Copy link
Copy Markdown

Summary

Closes #30. Adds an explicit Config::eq_when_safe(bool) builder so callers can opt out of automatic Eq/Hash derives. Default true preserves existing behavior.

What's added

  • prost-build/src/config.rs — new eq_when_safe field + builder method.
  • prost-build/src/context.rs — gates can_message_derive_eq / can_field_derive_eq on the flag, with RefCell<HashMap> memoization and a cycle-break sentinel for recursive types.
  • prost-build/src/lib.rs — unit tests for both flag states.
  • New tests/src/derive_eq.proto and tests/src/derive_eq.rs with compile-time TestEqIsImplemented: Eq bound across all-int, float, double, composed-safe, and composed-unsafe messages.

Test plan

  • cargo fmt --all -- --check clean.
  • cargo clippy -p prost-build --all-targets --all-features -- -D warnings clean.
  • 539/539 tests pass across prost, prost-build, prost-derive, prost-types, tests.

Implements issue tokio-rs#30 by exposing an explicit configuration knob,
`Config::eq_when_safe(bool)`, that controls whether prost emits
`#[derive(Eq, Hash)]` on generated message and oneof types when the
type is provably free of floating point fields (transitively).

The auto-derive logic itself was already in place, but it ran
unconditionally. With this change, callers that prefer to opt out
(for example to add their own manual `Eq` impls, or to keep
generated code minimal) can now do so by calling
`config.eq_when_safe(false)` before compiling.

The default is `true`, matching prost's pre-existing behavior, so
existing users are not affected.

Other notes:
- `Context::can_message_derive_eq` now memoizes results per
  fully-qualified message name. Cycles in the message graph (which
  are already broken at the field-typing layer via `is_nested`) are
  handled by leaving an in-progress sentinel in the cache.
- Added tests:
  * prost-build unit tests assert that `eq_when_safe(false)` strips
    `Eq`/`Hash` from the generated derives, and that the default
    keeps them.
  * tests/src/derive_eq.{proto,rs} compile a mix of int-only,
    float-bearing, and composed messages and rely on a `TestEqIsImplemented`
    bound to confirm that only the safe types satisfy `Eq` while
    float-bearing types remain only `PartialEq`.

@caspermeijn caspermeijn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I don't understand is: Why do you want to disable Eq when it is safe? The trait is useful, so why remove it?

Comment thread prost-build/src/config.rs
/// // Opt out of automatic `Eq` derives.
/// config.eq_when_safe(false);
/// ```
pub fn eq_when_safe(&mut self, enable: bool) -> &mut Self {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want this config API, it should use accept paths, like https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method.btree_map

That way it can be enabled or disabled on specific messages

Comment thread tests/src/derive_eq.proto
@@ -0,0 +1,36 @@
syntax = "proto3";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this diff. The master branch already contains the file: tests/src/derive_eq.proto

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

Successfully merging this pull request may close these issues.

Implement 'Eq' trait for proto

2 participants