diff --git a/core/commonMain/src/implementations/immutableMap/PersistentHashMap.kt b/core/commonMain/src/implementations/immutableMap/PersistentHashMap.kt index 1abbac43..0bafd4db 100644 --- a/core/commonMain/src/implementations/immutableMap/PersistentHashMap.kt +++ b/core/commonMain/src/implementations/immutableMap/PersistentHashMap.kt @@ -51,14 +51,12 @@ internal class PersistentHashMap(internal val node: TrieNode, override fun remove(key: K): PersistentHashMap { val newNode = node.remove(key.hashCode(), key, 0) if (node === newNode) { return this } - if (newNode == null) { return PersistentHashMap.emptyOf() } return PersistentHashMap(newNode, size - 1) } override fun remove(key: K, value: @UnsafeVariance V): PersistentHashMap { val newNode = node.remove(key.hashCode(), key, value, 0) if (node === newNode) { return this } - if (newNode == null) { return PersistentHashMap.emptyOf() } return PersistentHashMap(newNode, size - 1) } diff --git a/core/commonMain/src/implementations/immutableMap/PersistentHashMapBuilder.kt b/core/commonMain/src/implementations/immutableMap/PersistentHashMapBuilder.kt index 2f1383e2..d11385f2 100644 --- a/core/commonMain/src/implementations/immutableMap/PersistentHashMapBuilder.kt +++ b/core/commonMain/src/implementations/immutableMap/PersistentHashMapBuilder.kt @@ -64,14 +64,14 @@ internal class PersistentHashMapBuilder(private var map: PersistentHashMap override fun remove(key: K): V? { operationResult = null @Suppress("UNCHECKED_CAST") - node = node.mutableRemove(key.hashCode(), key, 0, this) ?: TrieNode.EMPTY as TrieNode + node = node.mutableRemove(key.hashCode(), key, 0, this) return operationResult } fun remove(key: K, value: V): Boolean { val oldSize = size @Suppress("UNCHECKED_CAST") - node = node.mutableRemove(key.hashCode(), key, value, 0, this) ?: TrieNode.EMPTY as TrieNode + node = node.mutableRemove(key.hashCode(), key, value, 0, this) return oldSize != size } diff --git a/core/commonMain/src/implementations/immutableMap/TrieNode.kt b/core/commonMain/src/implementations/immutableMap/TrieNode.kt index 815c2607..6b4172d5 100644 --- a/core/commonMain/src/implementations/immutableMap/TrieNode.kt +++ b/core/commonMain/src/implementations/immutableMap/TrieNode.kt @@ -290,20 +290,18 @@ internal class TrieNode( return TrieNode(0, 1 shl setBit1, arrayOf(node), owner) } - private fun removeEntryAtIndex(keyIndex: Int, positionMask: Int): TrieNode? { + private fun removeEntryAtIndex(keyIndex: Int, positionMask: Int): TrieNode { // assert(hasEntryAt(positionMask)) - // It is possible only when this node is the root node - if (buffer.size == ENTRY_SIZE) return null - +// assert(buffer.size > ENTRY_SIZE) // can be false only for the root node val newBuffer = buffer.removeEntryAtIndex(keyIndex) return TrieNode(dataMap xor positionMask, nodeMap, newBuffer) } - private fun mutableRemoveEntryAtIndex(keyIndex: Int, positionMask: Int, mutator: PersistentHashMapBuilder): TrieNode? { + private fun mutableRemoveEntryAtIndex(keyIndex: Int, positionMask: Int, mutator: PersistentHashMapBuilder): TrieNode { // assert(hasEntryAt(positionMask)) +// assert(buffer.size > ENTRY_SIZE) mutator.size-- mutator.operationResult = valueAtKeyIndex(keyIndex) - if (buffer.size == ENTRY_SIZE) return null if (ownedBy === mutator.ownership) { buffer = buffer.removeEntryAtIndex(keyIndex) @@ -314,17 +312,16 @@ internal class TrieNode( return TrieNode(dataMap xor positionMask, nodeMap, newBuffer, mutator.ownership) } - private fun collisionRemoveEntryAtIndex(i: Int): TrieNode? { - if (buffer.size == ENTRY_SIZE) return null - + private fun collisionRemoveEntryAtIndex(i: Int): TrieNode { +// assert(buffer.size > ENTRY_SIZE) val newBuffer = buffer.removeEntryAtIndex(i) return TrieNode(0, 0, newBuffer) } - private fun mutableCollisionRemoveEntryAtIndex(i: Int, mutator: PersistentHashMapBuilder): TrieNode? { + private fun mutableCollisionRemoveEntryAtIndex(i: Int, mutator: PersistentHashMapBuilder): TrieNode { +// assert(buffer.size > ENTRY_SIZE) mutator.size-- mutator.operationResult = valueAtKeyIndex(i) - if (buffer.size == ENTRY_SIZE) return null if (ownedBy === mutator.ownership) { buffer = buffer.removeEntryAtIndex(i) @@ -391,7 +388,7 @@ internal class TrieNode( return TrieNode(0, 0, newBuffer, mutator.ownership) } - private fun collisionRemove(key: K): TrieNode? { + private fun collisionRemove(key: K): TrieNode { for (i in 0 until buffer.size step ENTRY_SIZE) { if (key == keyAtIndex(i)) { return collisionRemoveEntryAtIndex(i) @@ -400,7 +397,7 @@ internal class TrieNode( return this } - private fun mutableCollisionRemove(key: K, mutator: PersistentHashMapBuilder): TrieNode? { + private fun mutableCollisionRemove(key: K, mutator: PersistentHashMapBuilder): TrieNode { for (i in 0 until buffer.size step ENTRY_SIZE) { if (key == keyAtIndex(i)) { return mutableCollisionRemoveEntryAtIndex(i, mutator) @@ -409,7 +406,7 @@ internal class TrieNode( return this } - private fun collisionRemove(key: K, value: V): TrieNode? { + private fun collisionRemove(key: K, value: V): TrieNode { for (i in 0 until buffer.size step ENTRY_SIZE) { if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) { return collisionRemoveEntryAtIndex(i) @@ -418,7 +415,7 @@ internal class TrieNode( return this } - private fun mutableCollisionRemove(key: K, value: V, mutator: PersistentHashMapBuilder): TrieNode? { + private fun mutableCollisionRemove(key: K, value: V, mutator: PersistentHashMapBuilder): TrieNode { for (i in 0 until buffer.size step ENTRY_SIZE) { if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) { return mutableCollisionRemoveEntryAtIndex(i, mutator) @@ -534,7 +531,7 @@ internal class TrieNode( return mutableInsertEntryAt(keyPositionMask, key, value, mutator.ownership) } - fun remove(keyHash: Int, key: K, shift: Int): TrieNode? { + fun remove(keyHash: Int, key: K, shift: Int): TrieNode { val keyPositionMask = 1 shl indexSegment(keyHash, shift) if (hasEntryAt(keyPositionMask)) { // key is directly in buffer @@ -554,7 +551,6 @@ internal class TrieNode( } else { targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR) } - checkNotNull(newNode) if (targetNode === newNode) return this return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode) } @@ -563,7 +559,7 @@ internal class TrieNode( return this } - fun mutableRemove(keyHash: Int, key: K, shift: Int, mutator: PersistentHashMapBuilder): TrieNode? { + fun mutableRemove(keyHash: Int, key: K, shift: Int, mutator: PersistentHashMapBuilder): TrieNode { val keyPositionMask = 1 shl indexSegment(keyHash, shift) if (hasEntryAt(keyPositionMask)) { // key is directly in buffer @@ -583,7 +579,6 @@ internal class TrieNode( } else { targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR, mutator) } - checkNotNull(newNode) if (ownedBy === mutator.ownership || targetNode !== newNode) { return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership) } @@ -594,7 +589,7 @@ internal class TrieNode( return this } - fun remove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int): TrieNode? { + fun remove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int): TrieNode { val keyPositionMask = 1 shl indexSegment(keyHash, shift) if (hasEntryAt(keyPositionMask)) { // key is directly in buffer @@ -614,7 +609,6 @@ internal class TrieNode( } else { targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR) } - checkNotNull(newNode) if (targetNode === newNode) return this return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode) } @@ -623,7 +617,7 @@ internal class TrieNode( return this } - fun mutableRemove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int, mutator: PersistentHashMapBuilder): TrieNode? { + fun mutableRemove(keyHash: Int, key: K, value: @UnsafeVariance V, shift: Int, mutator: PersistentHashMapBuilder): TrieNode { val keyPositionMask = 1 shl indexSegment(keyHash, shift) if (hasEntryAt(keyPositionMask)) { // key is directly in buffer @@ -643,7 +637,6 @@ internal class TrieNode( } else { targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR, mutator) } - checkNotNull(newNode) if (ownedBy === mutator.ownership || targetNode !== newNode) { return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership) } diff --git a/core/commonMain/src/implementations/immutableSet/PersistentHashSet.kt b/core/commonMain/src/implementations/immutableSet/PersistentHashSet.kt index 39d5f0d5..972a4f43 100644 --- a/core/commonMain/src/implementations/immutableSet/PersistentHashSet.kt +++ b/core/commonMain/src/implementations/immutableSet/PersistentHashSet.kt @@ -27,7 +27,6 @@ internal class PersistentHashSet(internal val node: TrieNode, override fun remove(element: E): PersistentSet { val newNode = node.remove(element.hashCode(), element, 0) if (node === newNode) { return this } - if (newNode == null) { return PersistentHashSet.emptyOf() } return PersistentHashSet(newNode, size - 1) } diff --git a/core/commonMain/src/implementations/immutableSet/PersistentHashSetBuilder.kt b/core/commonMain/src/implementations/immutableSet/PersistentHashSetBuilder.kt index 738c2cff..37ebad0a 100644 --- a/core/commonMain/src/implementations/immutableSet/PersistentHashSetBuilder.kt +++ b/core/commonMain/src/implementations/immutableSet/PersistentHashSetBuilder.kt @@ -46,7 +46,7 @@ internal class PersistentHashSetBuilder(private var set: PersistentHashSet override fun remove(element: E): Boolean { val size = this.size @Suppress("UNCHECKED_CAST") - node = node.mutableRemove(element.hashCode(), element, 0, this) ?: TrieNode.EMPTY as TrieNode + node = node.mutableRemove(element.hashCode(), element, 0, this) return size != this.size } diff --git a/core/commonMain/src/implementations/immutableSet/TrieNode.kt b/core/commonMain/src/implementations/immutableSet/TrieNode.kt index 2725ac8f..59aa94e0 100644 --- a/core/commonMain/src/implementations/immutableSet/TrieNode.kt +++ b/core/commonMain/src/implementations/immutableSet/TrieNode.kt @@ -186,18 +186,17 @@ internal class TrieNode( } - private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode? { + private fun removeCellAtIndex(cellIndex: Int, positionMask: Int): TrieNode { // assert(!hasNoCellAt(positionMask)) - // It is possible only when this node is the root node - if (buffer.size == 1) return null +// assert(buffer.size > 1) can be false only for the root node val newBuffer = buffer.removeCellAtIndex(cellIndex) return TrieNode(bitmap xor positionMask, newBuffer) } - private fun mutableRemoveCellAtIndex(cellIndex: Int, positionMask: Int, owner: MutabilityOwnership): TrieNode? { + private fun mutableRemoveCellAtIndex(cellIndex: Int, positionMask: Int, owner: MutabilityOwnership): TrieNode { // assert(!hasNoCellAt(positionMask)) - if (buffer.size == 1) return null +// assert(buffer.size > 1) if (ownedBy === owner) { buffer = buffer.removeCellAtIndex(cellIndex) @@ -208,16 +207,12 @@ internal class TrieNode( return TrieNode(bitmap xor positionMask, newBuffer, owner) } - private fun collisionRemoveElementAtIndex(i: Int): TrieNode? { - if (buffer.size == 1) return null - + private fun collisionRemoveElementAtIndex(i: Int): TrieNode { val newBuffer = buffer.removeCellAtIndex(i) return TrieNode(0, newBuffer) } - private fun mutableCollisionRemoveElementAtIndex(i: Int, owner: MutabilityOwnership): TrieNode? { - if (buffer.size == 1) return null - + private fun mutableCollisionRemoveElementAtIndex(i: Int, owner: MutabilityOwnership): TrieNode { if (ownedBy === owner) { buffer = buffer.removeCellAtIndex(i) return this @@ -247,7 +242,7 @@ internal class TrieNode( return TrieNode(0, newBuffer, mutator.ownership) } - private fun collisionRemove(element: E): TrieNode? { + private fun collisionRemove(element: E): TrieNode { val index = buffer.indexOf(element) if (index != -1) { return collisionRemoveElementAtIndex(index) @@ -255,7 +250,7 @@ internal class TrieNode( return this } - private fun mutableCollisionRemove(element: E, mutator: PersistentHashSetBuilder<*>): TrieNode? { + private fun mutableCollisionRemove(element: E, mutator: PersistentHashSetBuilder<*>): TrieNode { val index = buffer.indexOf(element) if (index != -1) { mutator.size-- @@ -331,7 +326,7 @@ internal class TrieNode( return mutableMoveElementToNode(cellIndex, elementHash, element, shift, mutator.ownership) } - fun remove(elementHash: Int, element: E, shift: Int): TrieNode? { + fun remove(elementHash: Int, element: E, shift: Int): TrieNode { val cellPositionMask = 1 shl indexSegment(elementHash, shift) if (hasNoCellAt(cellPositionMask)) { // element is absent @@ -346,7 +341,6 @@ internal class TrieNode( } else { targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR) } - checkNotNull(newNode) if (targetNode === newNode) return this return updateNodeAtIndex(cellIndex, newNode) } @@ -357,7 +351,7 @@ internal class TrieNode( return this } - fun mutableRemove(elementHash: Int, element: E, shift: Int, mutator: PersistentHashSetBuilder<*>): TrieNode? { + fun mutableRemove(elementHash: Int, element: E, shift: Int, mutator: PersistentHashSetBuilder<*>): TrieNode { val cellPositionMask = 1 shl indexSegment(elementHash, shift) if (hasNoCellAt(cellPositionMask)) { // element is absent @@ -372,7 +366,6 @@ internal class TrieNode( } else { targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR, mutator) } - checkNotNull(newNode) if (ownedBy === mutator.ownership || targetNode !== newNode) { return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership) }