Skip to content

Commit 81eeb4e

Browse files
lihaoyieed3si9n
authored andcommitted
[1.x] Make libraryClassName relation deterministic under concurrency (#1638)
Previously, Zinc could produce nondeterministic analysis output because `binaryClassName` used `put(binary, className)` from concurrent `externalLibraryDependency` callbacks. The final value depended on callback scheduling, so `binaryClassName` stores one representative class per binary JAR in a concurrent map, but representative selection was non-deterministic. This PR replaces `put` with deterministic merge using `get`, choosing the lexicographically smallest class name for each binary. `libraryClassName` only needs a stable representative class per binary for lookup/stamp checks; selecting a deterministic representative preserves behavior while removing scheduler dependence. This removes one source of nondeterminism in Zinc analysis serialization.
1 parent 758b31c commit 81eeb4e

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,12 @@ private final class AnalysisCallback(
740740
source: VirtualFileRef,
741741
context: DependencyContext
742742
): Unit = {
743-
binaryClassName.put(binary, className)
743+
// Break ties via lexicographic ordering on the className, which ensures a stable
744+
// representative class name is picked for each binary avoiding non-deterministic output
745+
binaryClassName.get(binary) match {
746+
case Some(existing) if className.compareTo(existing) >= 0 => ()
747+
case _ => binaryClassName.put(binary, className)
748+
}
744749
add(libraryDeps, source, binary)
745750
}
746751

0 commit comments

Comments
 (0)