Problem
Compiling this namespace repeatedly in separate processes produces different .clj.dll bytes (10 compiles: 2 distinct SHA-256 hashes):
(ns repro.core)
(defn f []
(loop [x 1]
(if (pos? x)
[(fn [] x) (fn [] x)]
(recur 1.5))))
The recur type (Double) improves on the binding init type (Int64), so the loop body is re-analyzed with *reusable-types* bound to the module's incomplete TypeBuilders (typed_passes.clj :loop case, loop_bindings.clj infer-binding-types). fresh-type picks a recycled builder with some over that unordered set, ignoring the requested name. Both sibling fn types match (type-match checks only super, interfaces, attributes), so the pick follows identity-hash order and varies per process. Same bug family as #43, in the type-reuse path its sweep did not cover.
Suggestion
Select deterministically in fresh-type: sort matching candidates by type name with an ordinal comparator and take the first. Ordinal because committed DLLs are byte-diffed across machines and CLR default string comparison is culture-sensitive.
Problem
Compiling this namespace repeatedly in separate processes produces different
.clj.dllbytes (10 compiles: 2 distinct SHA-256 hashes):The recur type (Double) improves on the binding init type (Int64), so the loop body is re-analyzed with
*reusable-types*bound to the module's incomplete TypeBuilders (typed_passes.clj:loopcase,loop_bindings.cljinfer-binding-types).fresh-typepicks a recycled builder withsomeover that unordered set, ignoring the requested name. Both sibling fn types match (type-matchchecks only super, interfaces, attributes), so the pick follows identity-hash order and varies per process. Same bug family as #43, in the type-reuse path its sweep did not cover.Suggestion
Select deterministically in
fresh-type: sort matching candidates by type name with an ordinal comparator and take the first. Ordinal because committed DLLs are byte-diffed across machines and CLR default string comparison is culture-sensitive.