Skip to content

PersistentOrderedSetIterator breaks if hash of an element changes #76

@Loomie

Description

@Loomie

Problem

Exception in thread "main" kotlin.KotlinNullPointerException
	at kotlinx.collections.immutable.implementations.persistentOrderedSet.PersistentOrderedSetIterator.next(PersistentOrderedSetIterator.kt:22)

When iterating over a PersistentOrderedSet

How to reproduce

After creating the PersistentSet alter a contained element so its hash code changes.

import kotlinx.collections.immutable.PersistentSet
import kotlinx.collections.immutable.toPersistentSet

fun main() {
    val changing = mutableSetOf("ok")
    val persistent: PersistentSet<Any> = setOf("constant", changing, "fix").toPersistentSet()
    doSomething(changing, persistent)
    changing.add("break iteration")
    doSomething(changing, persistent)
}

private fun doSomething(changing: MutableSet<String>, persistent: PersistentSet<Any>) {
    println("actual hash is ${changing.hashCode()}")
    val result = persistent.firstOrNull { it is Set<*> }
    println("Found $result")
}

Version used: 0.3.2

Details

The error occurs in TrieNode.get(Int, K, Int) because although the data is in the buffer hasEntryAt() returns false. Seems like the dataMap is outdated.

Note: The set is not changed during iteration but during two independent iterations.

I found no documentation on PersistentSet that values must not change their hash codes. Like a Set it should always be iterable.

In my actual project I used a data class with a collection. A workaround is to use a normal class with the default hashCode() implementation.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions