Persistent assoc/conj on a transient-created collision node

Description

Bug reported by Zach Tellman https://groups.google.com/d/msg/clojure-dev/HvppNjEH5Qc/1wZ-6qE7nWgJ

Since transients were introduced the invariant array.length == count*2 doesn't hold for HashCollisionNode.
However persistent .without still relies on it.

Hence persistent dissoc on a collision node created by transients fails.

1 2 3 4 (let [a (reify Object (hashCode [_] 42)) b (reify Object (hashCode [_] 42))] (= (-> #{a b} transient (disj! a) persistent! (conj a)) (-> #{a b} transient (disj! a) persistent! (conj a))))

returns false.

Patch: persistent-assoc-after-collision.diff

Generative test patch: transient-generative-test.diff

The generative test reliably reproduces the error. It is simpler than the original test that found the bug but tests a series conj/disj/transient/persistent actions on a set. I've included it separately in case we decide not to apply.

Screened by: Alex Miller

Environment

None

Status

Assignee

Unassigned

Reporter

Christophe Grand

Labels

Approval

Ok

Patch

Code and Test

Fix versions

Affects versions

Release 1.5

Priority

Critical
Configure