Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in PersistentMap equals implementation #198

Open
iquadrat opened this issue Nov 8, 2024 · 0 comments
Open

Bug in PersistentMap equals implementation #198

iquadrat opened this issue Nov 8, 2024 · 0 comments
Labels

Comments

@iquadrat
Copy link

iquadrat commented Nov 8, 2024

PersistentMap.equals sometimes returns false even though all map entries are equal!

This is quite serious as comparing PersistentMap is a basic functionality.

We have seen this in the wild. Below is a fully self-contained test to reproduce it. The problem seems to be related with the node structure and the 'minus' / remove method.

Affected versions: at least 0.3.5 and 0.3.8

import kotlinx.collections.immutable.minus
import kotlinx.collections.immutable.persistentMapOf
import net.oddpoet.expect.extension.equal
import net.oddpoet.expect.should
import kotlin.test.Test

class PersistentMapEqualsBugTest {
    private class ChosenHashCode(
        private val hashCode: Int,
        private val name: String,
    ) {
        override fun equals(other: Any?): Boolean {
            return other is ChosenHashCode && (other.name == name)
        }

        override fun hashCode(): Int {
            return hashCode
        }

        override fun toString(): String {
            return name
        }
    }

    @Test
    fun `debug PersistentMap equals`() {
        val a = ChosenHashCode(123, "A")
        val b = ChosenHashCode(123, "B")
        val c = ChosenHashCode(123, "C")

        val abc = persistentMapOf(
            a to "x",
            b to "y",
            c to "z",
        )

        val minusAb = abc.minus(arrayOf(a, b))
        val cOnly = persistentMapOf(c to "z")

        minusAb.entries.should.equal(cOnly.entries) // passes
        minusAb.should.equal(cOnly) // fails
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants