Skip to content

feat: make LDValue hashable - #519

Open
abelonogov-ld wants to merge 1 commit into
v11from
andrey/ldvalue-hashable
Open

feat: make LDValue hashable#519
abelonogov-ld wants to merge 1 commit into
v11from
andrey/ldvalue-hashable

Conversation

@abelonogov-ld

Copy link
Copy Markdown
Contributor

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Split out of #516, which needs to hash a flag value as part of an evaluation exposure key. That PR is stacked on this one.

Describe the solution you've provided

LDValue was Equatable but not Hashable, so anything wanting to hold one in a dictionary or a set had to switch over the enum and hash each case by hand — which #516 was doing, including sorting object keys so that a map's iteration order could not change the hash.

Every payload LDValue carries is already Hashable once LDValue itself is ([LDValue] and [String: LDValue] conform when their elements do), so the conformance is synthesized. That matters for correctness: it agrees by construction with the Equatable conformance, which was also synthesized, rather than being a second hand-written definition of the same thing that could drift from it.

Hashable refines Equatable, so this replaces Equatable in the conformance list rather than adding to it. Adding a conformance to a public type is source compatible.

Describe alternatives you've considered

  • Writing hash(into:) by hand. It's more code, and it has to be kept in step with equality; the synthesized pair cannot disagree.
  • Leaving LDValue alone and keeping the hand-rolled hashing in the deduper. That leaves the same work for the next caller that wants to key something by a flag value, and each copy has to remember details like object key ordering.

Additional context

LDValueSpec covers equal values hashing alike, an object hashing the same whichever order its keys were written in, values of different kinds staying distinct (including pairs a naive payload-only hash would collide, such as .bool(false) against .null), and a value keying a dictionary.

Full suite passes: 597 tests.

Made with Cursor

An LDValue could be compared but not hashed, so anything holding one in a
dictionary or a set had to walk the enum and hash each case by hand. The
conformance is synthesized, so it agrees with the equality that was already
synthesized alongside it, including an object hashing the same whichever order
its keys were written in.

Hashable refines Equatable, so this replaces that conformance rather than adding
to it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@abelonogov-ld
abelonogov-ld requested a review from a team as a code owner August 13, 2026 23:36
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.

1 participant