diff --git a/collect/src/main/kotlin/com/certora/collect/AbstractTreapMap.kt b/collect/src/main/kotlin/com/certora/collect/AbstractTreapMap.kt index f3994d4..9fa72c1 100644 --- a/collect/src/main/kotlin/com/certora/collect/AbstractTreapMap.kt +++ b/collect/src/main/kotlin/com/certora/collect/AbstractTreapMap.kt @@ -151,19 +151,19 @@ internal sealed class AbstractTreapMap<@Treapable K, V, @Treapable S : AbstractT override operator fun iterator() = entrySequence().map { it.value }.iterator() } - override fun union(m: Map, merger: (K, V, V) -> V): TreapMap = + override fun union(m: Map, merger: (K, V, V) -> V): TreapMap = m.useAsTreap( { otherTreap -> self.unionWith(otherTreap, getShallowUnionMerger(merger)) ?: clear() }, { fallbackUnion(m, merger) } ) - override fun parallelUnion(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = + override fun parallelUnion(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = m.useAsTreap( { otherTreap -> self.parallelUnionWith(otherTreap, parallelThresholdLog2, getShallowUnionMerger(merger)) ?: clear() }, { fallbackUnion(m, merger) } ) - private fun fallbackUnion(m: Map, merger: (K, V, V) -> V): TreapMap { + private fun fallbackUnion(m: Map, merger: (K, V, V) -> V): TreapMap { var newThis = this as TreapMap for ((k, v) in m.entries) { if (k in this) { @@ -175,19 +175,19 @@ internal sealed class AbstractTreapMap<@Treapable K, V, @Treapable S : AbstractT return newThis } - override fun intersect(m: Map, merger: (K, V, V) -> V): TreapMap = + override fun intersect(m: Map, merger: (K, V, V) -> V): TreapMap = m.useAsTreap( { otherTreap -> self.intersectWith(otherTreap, getShallowIntersectMerger(merger)) ?: clear() }, { fallbackIntersect(m, merger) } ) - override fun parallelIntersect(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = + override fun parallelIntersect(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = m.useAsTreap( { otherTreap -> self.parallelIntersectWith(otherTreap, parallelThresholdLog2, getShallowIntersectMerger(merger)) ?: clear() }, { fallbackIntersect(m, merger) } ) - private fun fallbackIntersect(m: Map, merger: (K, V, V) -> V): TreapMap { + private fun fallbackIntersect(m: Map, merger: (K, V, V) -> V): TreapMap { var newThis = clear() for ((k, v) in m.entries) { if (k in this) { @@ -201,7 +201,7 @@ internal sealed class AbstractTreapMap<@Treapable K, V, @Treapable S : AbstractT Merges the entries in `m` with the entries in this AbstractTreapMap, applying the "merger" function to get the new values for each key. */ - override fun merge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap = + override fun merge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap = m.useAsTreap( { otherTreap -> self.mergeWith(otherTreap, mode, getShallowMerger(mode, merger)) @@ -220,7 +220,7 @@ internal sealed class AbstractTreapMap<@Treapable K, V, @Treapable S : AbstractT @param[merger] The merge function to apply to each pair of entries. Must be pure and thread-safe. */ override fun parallelMerge( - m: Map, + m: Map, mode: MergeMode, parallelThresholdLog2: Int, merger: (K, V?, V?) -> V? @@ -233,7 +233,7 @@ internal sealed class AbstractTreapMap<@Treapable K, V, @Treapable S : AbstractT { fallbackMerge(m, mode, merger) } ) - private fun fallbackMerge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap { + private fun fallbackMerge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap { var newThis = clear() val keys = when(mode) { MergeMode.UNION -> this.keys union m.keys diff --git a/collect/src/main/kotlin/com/certora/collect/EmptyTreapMap.kt b/collect/src/main/kotlin/com/certora/collect/EmptyTreapMap.kt index e092758..f8cf059 100644 --- a/collect/src/main/kotlin/com/certora/collect/EmptyTreapMap.kt +++ b/collect/src/main/kotlin/com/certora/collect/EmptyTreapMap.kt @@ -44,13 +44,13 @@ internal class EmptyTreapMap<@Treapable K, V> private constructor() : TreapMap put(key, v) } - override fun union(m: Map, merger: (K, V, V) -> V): TreapMap = putAll(m) - override fun parallelUnion(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = putAll(m) + override fun union(m: Map, merger: (K, V, V) -> V): TreapMap = putAll(m) + override fun parallelUnion(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = putAll(m) - override fun intersect(m: Map, merger: (K, V, V) -> V): TreapMap = this - override fun parallelIntersect(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = this + override fun intersect(m: Map, merger: (K, V, V) -> V): TreapMap = this + override fun parallelIntersect(m: Map, parallelThresholdLog2: Int, merger: (K, V, V) -> V): TreapMap = this - override fun merge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap { + override fun merge(m: Map, mode: MergeMode, merger: (K, V?, V?) -> V?): TreapMap { var map: TreapMap = this if (mode == MergeMode.UNION) { for ((key, value) in m) { @@ -65,7 +65,7 @@ internal class EmptyTreapMap<@Treapable K, V> private constructor() : TreapMap, + m: Map, mode: MergeMode, parallelThresholdLog2: Int, merger: (K, V?, V?) -> V? diff --git a/collect/src/main/kotlin/com/certora/collect/TreapList.kt b/collect/src/main/kotlin/com/certora/collect/TreapList.kt index fd56f87..1e8a608 100644 --- a/collect/src/main/kotlin/com/certora/collect/TreapList.kt +++ b/collect/src/main/kotlin/com/certora/collect/TreapList.kt @@ -6,17 +6,17 @@ import kotlinx.collections.immutable.PersistentList A PersistentList implemented as a [Treap](https://en.wikipedia.org/wiki/Treap). */ @Treapable -public sealed interface TreapList : PersistentList { - override fun add(element: E): TreapList = addLast(element) - override fun addAll(elements: Collection): TreapList - override fun remove(element: E): TreapList - override fun removeAll(elements: Collection): TreapList +public sealed interface TreapList : PersistentList { + override fun add(element: @UnsafeVariance E): TreapList = addLast(element) + override fun addAll(elements: Collection<@UnsafeVariance E>): TreapList + override fun remove(element: @UnsafeVariance E): TreapList + override fun removeAll(elements: Collection<@UnsafeVariance E>): TreapList override fun removeAll(predicate: (E) -> Boolean): TreapList - override fun retainAll(elements: Collection): TreapList + override fun retainAll(elements: Collection<@UnsafeVariance E>): TreapList override fun clear(): TreapList - override fun addAll(index: Int, c: Collection): TreapList - override fun set(index: Int, element: E): TreapList - override fun add(index: Int, element: E): TreapList + override fun addAll(index: Int, c: Collection<@UnsafeVariance E>): TreapList + override fun set(index: Int, element: @UnsafeVariance E): TreapList + override fun add(index: Int, element: @UnsafeVariance E): TreapList override fun removeAt(index: Int): TreapList override fun subList(fromIndex: Int, toIndex: Int): TreapList @@ -28,14 +28,14 @@ public sealed interface TreapList : PersistentList { public fun last(): E public fun lastOrNull(): E? - public fun addFirst(element: E): TreapList - public fun addLast(element: E): TreapList + public fun addFirst(element: @UnsafeVariance E): TreapList + public fun addLast(element: @UnsafeVariance E): TreapList public fun removeFirst(): TreapList public fun removeLast(): TreapList - public fun updateElements(transform: (E) -> E?): TreapList - public fun updateElementsIndexed(transform: (Int, E) -> E?): TreapList + public fun updateElements(transform: (E) -> @UnsafeVariance E?): TreapList + public fun updateElementsIndexed(transform: (Int, E) -> @UnsafeVariance E?): TreapList public fun mapReduce(map: (E) -> R, reduce: (R, R) -> R): R? public fun parallelMapReduce(map: (E) -> R, reduce: (R, R) -> R, parallelThresholdLog2: Int = 5): R? @@ -57,7 +57,7 @@ public sealed interface TreapList : PersistentList { public fun removeLast(): E } - override fun builder(): Builder + override fun builder(): Builder<@UnsafeVariance E> } public fun treapListOf(): TreapList = EmptyTreapList() diff --git a/collect/src/main/kotlin/com/certora/collect/TreapMap.kt b/collect/src/main/kotlin/com/certora/collect/TreapMap.kt index 3d8c641..a95ce3e 100644 --- a/collect/src/main/kotlin/com/certora/collect/TreapMap.kt +++ b/collect/src/main/kotlin/com/certora/collect/TreapMap.kt @@ -6,7 +6,11 @@ import kotlinx.collections.immutable.PersistentMap A [PersistentMap] implemented as a [Treap](https://en.wikipedia.org/wiki/Treap) - a kind of balanced binary tree. */ @Treapable -public sealed interface TreapMap : PersistentMap { +public sealed interface TreapMap : PersistentMap { + + // Note: all the @UnsafeVariance annotations are safe because we never mutate anything. Any value appearing in an + // "in" position can only be a) compared to other values, or b) returned in an "out" position. + override fun put(key: K, value: @UnsafeVariance V): TreapMap override fun remove(key: K): TreapMap override fun remove(key: K, value: @UnsafeVariance V): TreapMap @@ -54,8 +58,8 @@ public sealed interface TreapMap : PersistentMap { the value from [m], in that order, and the returned value will appear in the resulting map. */ public fun union( - m: Map, - merger: (K, V, V) -> V + m: Map, + merger: (K, V, V) -> @UnsafeVariance V ): TreapMap /** @@ -68,9 +72,9 @@ public sealed interface TreapMap : PersistentMap { Merge operations are performed in parallel for maps larger than (approximately) 2^parallelThresholdLog2. */ public fun parallelUnion( - m: Map, + m: Map, parallelThresholdLog2: Int = 4, - merger: (K, V, V) -> V + merger: (K, V, V) -> @UnsafeVariance V ): TreapMap /** @@ -80,8 +84,8 @@ public sealed interface TreapMap : PersistentMap { the key, the value from this map, and the value from [m], in that order. */ public fun intersect( - m: Map, - merger: (K, V, V) -> V + m: Map, + merger: (K, V, V) -> @UnsafeVariance V ): TreapMap /** @@ -93,9 +97,9 @@ public sealed interface TreapMap : PersistentMap { Merge operations are performed in parallel for maps larger than (approximately) 2^parallelThresholdLog2. */ public fun parallelIntersect( - m: Map, + m: Map, parallelThresholdLog2: Int = 4, - merger: (K, V, V) -> V + merger: (K, V, V) -> @UnsafeVariance V ): TreapMap /** @@ -115,9 +119,9 @@ public sealed interface TreapMap : PersistentMap { [union] or [intersect] instead. */ public fun merge( - m: Map, + m: Map, mode: MergeMode, - merger: (K, V?, V?) -> V? + merger: (K, V?, V?) -> @UnsafeVariance V? ): TreapMap /** @@ -134,8 +138,8 @@ public sealed interface TreapMap : PersistentMap { [union] or [intersect] instead. */ public fun merge( - m: Map, - merger: (K, V?, V?) -> V? + m: Map, + merger: (K, V?, V?) -> @UnsafeVariance V? ): TreapMap = merge(m, MergeMode.UNION, merger) /** @@ -157,10 +161,10 @@ public sealed interface TreapMap : PersistentMap { [parallelUnion] or [parallelIntersect] instead. */ public fun parallelMerge( - m: Map, + m: Map, mode: MergeMode, parallelThresholdLog2: Int = 4, - merger: (K, V?, V?) -> V? + merger: (K, V?, V?) -> @UnsafeVariance V? ): TreapMap /** @@ -179,9 +183,9 @@ public sealed interface TreapMap : PersistentMap { [parallelUnion] or [parallelIntersect] instead. */ public fun parallelMerge( - m: Map, + m: Map, parallelThresholdLog2: Int = 4, - merger: (K, V?, V?) -> V? + merger: (K, V?, V?) -> @UnsafeVariance V? ): TreapMap = parallelMerge(m, MergeMode.UNION, parallelThresholdLog2, merger) /** @@ -231,7 +235,7 @@ public sealed interface TreapMap : PersistentMap { public fun updateEntry( key: K, value: U, - merger: (V?, U) -> V? + merger: (V?, U) -> @UnsafeVariance V? ): TreapMap /** @@ -239,7 +243,7 @@ public sealed interface TreapMap : PersistentMap { the key to a pair of values. Each value may be null, if the key is not present in the corresponding map. */ public fun zip( - m: Map + m: Map ): Sequence>> /**