Skip to content

fix: implement Deterministic hashCode for DynamicValue#1042

Open
samuel-asleep wants to merge 2 commits intozio:mainfrom
samuel-asleep:implement-deterministic-hashcode
Open

fix: implement Deterministic hashCode for DynamicValue#1042
samuel-asleep wants to merge 2 commits intozio:mainfrom
samuel-asleep:implement-deterministic-hashcode

Conversation

@samuel-asleep
Copy link

DynamicValue.hashCode was non-deterministic, breaking use as HashMap/HashSet keys and across JVM runs in two distinct ways.

Root Causes

  • Primitive[A]: Case class hashCode included standardType.##, which calls System.identityHashCode on StandardType singletons (plain implicit objects, not case objects) — unstable across JVM runs.
  • Dictionary: Auto-generated hashCode used Chunk.hashCode (order-sensitive), but entries originate from iterating a Map with non-deterministic order. Two logically-identical dictionaries could produce different hashes and fail equals within the same run.

Fixes

  • Primitive[A]: Override hashCode using standardType.tag.## (a stable String) combined with value.## via MurmurHash3:

    // Before: standardType.## → System.identityHashCode, changes between JVM runs
    // After: stable tag-based hash
    DynamicValue.Primitive(42, StandardType.IntType).hashCode ==
      DynamicValue.Primitive(42, StandardType.IntType).hashCode // always true
  • Dictionary: Override both hashCode (entries.toSet.hashCode()) and equals (entries.toSet == otherEntries.toSet) to be order-independent and mutually consistent:

    val d1 = DynamicValue.Dictionary(Chunk((k1, v1), (k2, v2)))
    val d2 = DynamicValue.Dictionary(Chunk((k2, v2), (k1, v1)))
    d1 == d2          // true  (was false)
    d1.hashCode == d2.hashCode  // true  (was false)

Tests

Four property-based tests added to DynamicValueSpec:

  • Primitive hashCode stability across separate instances
  • Primitive hashCode stability via toDynamic round-trips
  • Dictionary hashCode and equality are order-independent
  • General hashCode/equals contract across arbitrary generated DynamicValues

fixes #655
/claim #655

@samuel-asleep
Copy link
Author

@987Nabil can you please review when you have a moment

@samuel-asleep
Copy link
Author

@987Nabil @jdegoes can you please review when you have a moment

@samuel-asleep
Copy link
Author

@jdegoes @987Nabil please review !

@samuel-asleep
Copy link
Author

@987Nabil ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schema deterministic hashcode for DynamicValue

1 participant