From f3145454f28e075e83f64c2cf49f5aff357d30a1 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Thu, 30 Apr 2020 11:40:17 +0300 Subject: [PATCH] Decommonize collection builder implementations --- libraries/stdlib/js/src/kotlin/collections.kt | 55 ++++++++- .../collections/AbstractMutableCollection.kt | 21 +++- .../kotlin/collections/AbstractMutableList.kt | 18 ++- .../kotlin/collections/AbstractMutableMap.kt | 17 +++ .../js/src/kotlin/collections/ArrayList.kt | 21 ++++ .../js/src/kotlin/collections/HashMap.kt | 2 + .../js/src/kotlin/collections/HashSet.kt | 4 +- .../src/kotlin/collections/LinkedHashMap.kt | 28 ++++- .../src/kotlin/collections/LinkedHashSet.kt | 8 ++ .../src/kotlin/collections/CollectionsJVM.kt | 37 ++++++ .../jvm/src/kotlin/collections/MapsJVM.kt | 49 ++++++-- .../jvm/src/kotlin/collections/SetsJVM.kt | 39 ++++++ .../collections/builders/ListBuilder.kt | 13 +- .../kotlin/collections/builders/MapBuilder.kt | 64 +++++++--- .../kotlin/collections/builders/SetBuilder.kt | 16 ++- .../src/kotlin/collections/Collections.kt | 16 ++- .../stdlib/src/kotlin/collections/Maps.kt | 25 ++-- .../stdlib/src/kotlin/collections/Sets.kt | 17 ++- .../test/collections/ContainerBuilderTest.kt | 115 +++++++++++------- .../kotlin-stdlib-runtime-merged.txt | 75 ++---------- 20 files changed, 471 insertions(+), 169 deletions(-) rename libraries/stdlib/{ => jvm}/src/kotlin/collections/builders/ListBuilder.kt (97%) rename libraries/stdlib/{ => jvm}/src/kotlin/collections/builders/MapBuilder.kt (91%) rename libraries/stdlib/{ => jvm}/src/kotlin/collections/builders/SetBuilder.kt (71%) diff --git a/libraries/stdlib/js/src/kotlin/collections.kt b/libraries/stdlib/js/src/kotlin/collections.kt index eb22233caf3..318cfe3b110 100644 --- a/libraries/stdlib/js/src/kotlin/collections.kt +++ b/libraries/stdlib/js/src/kotlin/collections.kt @@ -49,22 +49,75 @@ internal actual fun copyToArrayImpl(collection: Collection<*>, array: Array< return array } + /** * Returns an immutable list containing only the specified object [element]. */ public fun listOf(element: T): List = arrayListOf(element) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(builderAction: MutableList.() -> Unit): List { + return ArrayList().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(capacity: Int, builderAction: MutableList.() -> Unit): List { + checkBuilderCapacity(capacity) + return ArrayList(capacity).apply(builderAction).build() +} + + /** * Returns an immutable set containing only the specified object [element]. */ public fun setOf(element: T): Set = hashSetOf(element) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(builderAction: MutableSet.() -> Unit): Set { + return LinkedHashSet().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(capacity: Int, builderAction: MutableSet.() -> Unit): Set { + return LinkedHashSet(capacity).apply(builderAction).build() +} + + /** * Returns an immutable map, mapping only the specified key to the * specified value. */ public fun mapOf(pair: Pair): Map = hashMapOf(pair) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map { + return LinkedHashMap().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map { + return LinkedHashMap(capacity).apply(builderAction).build() +} + + /** * Fills the list with the provided [value]. * @@ -196,6 +249,6 @@ internal actual fun mapCapacity(expectedSize: Int) = expectedSize @SinceKotlin("1.3") @ExperimentalStdlibApi @PublishedApi -internal actual fun checkBuilderCapacity(capacity: Int) { +internal fun checkBuilderCapacity(capacity: Int) { require(capacity >= 0) { "capacity must be non-negative." } } \ No newline at end of file diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt index 164b5845995..636c44aaabd 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt @@ -15,6 +15,7 @@ public actual abstract class AbstractMutableCollection protected actual const actual abstract override fun add(element: E): Boolean actual override fun remove(element: E): Boolean { + checkIsMutable() val iterator = iterator() while (iterator.hasNext()) { if (iterator.next() == element) { @@ -26,6 +27,7 @@ public actual abstract class AbstractMutableCollection protected actual const } actual override fun addAll(elements: Collection): Boolean { + checkIsMutable() var modified = false for (element in elements) { if (add(element)) modified = true @@ -33,10 +35,18 @@ public actual abstract class AbstractMutableCollection protected actual const return modified } - actual override fun removeAll(elements: Collection): Boolean = (this as MutableIterable).removeAll { it in elements } - actual override fun retainAll(elements: Collection): Boolean = (this as MutableIterable).removeAll { it !in elements } + actual override fun removeAll(elements: Collection): Boolean { + checkIsMutable() + return (this as MutableIterable).removeAll { it in elements } + } + + actual override fun retainAll(elements: Collection): Boolean { + checkIsMutable() + return (this as MutableIterable).removeAll { it !in elements } + } actual override fun clear(): Unit { + checkIsMutable() val iterator = this.iterator() while (iterator.hasNext()) { iterator.next() @@ -46,5 +56,12 @@ public actual abstract class AbstractMutableCollection protected actual const @JsName("toJSON") open fun toJSON(): Any = this.toArray() + + + /** + * This method is called every time when a mutating method is called on this mutable collection. + * Mutable collections that are built (frozen) must throw `UnsupportedOperationException`. + */ + internal open fun checkIsMutable(): Unit { } } diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt index 99bacdb5575..778e1693e81 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt @@ -28,11 +28,13 @@ public actual abstract class AbstractMutableList protected actual constructor * @return `true` because the list is always modified as the result of this operation. */ actual override fun add(element: E): Boolean { + checkIsMutable() add(size, element) return true } actual override fun addAll(index: Int, elements: Collection): Boolean { + checkIsMutable() var _index = index var changed = false for (e in elements) { @@ -43,11 +45,19 @@ public actual abstract class AbstractMutableList protected actual constructor } actual override fun clear() { + checkIsMutable() removeRange(0, size) } - actual override fun removeAll(elements: Collection): Boolean = removeAll { it in elements } - actual override fun retainAll(elements: Collection): Boolean = removeAll { it !in elements } + actual override fun removeAll(elements: Collection): Boolean { + checkIsMutable() + return removeAll { it in elements } + } + + actual override fun retainAll(elements: Collection): Boolean { + checkIsMutable() + return removeAll { it !in elements } + } actual override fun iterator(): MutableIterator = IteratorImpl() @@ -164,7 +174,7 @@ public actual abstract class AbstractMutableList protected actual constructor override fun set(element: E) { check(last != -1) { "Call next() or previous() before updating element value with the iterator." } - this@AbstractMutableList[last] = element + set(last, element) } } @@ -204,6 +214,8 @@ public actual abstract class AbstractMutableList protected actual constructor } override val size: Int get() = _size + + internal override fun checkIsMutable(): Unit = list.checkIsMutable() } } diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt index 012993916cd..bc72c801f19 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt @@ -30,6 +30,10 @@ public actual abstract class AbstractMutableMap protected actual construct override val value: V get() = _value override fun setValue(newValue: V): V { + // Should check if the map containing this entry is mutable. + // However, to not increase entry memory footprint it might be worthwhile not to check it here and + // force subclasses that implement `build()` (freezing) operation to implement their own `MutableEntry`. +// this@AbstractMutableMap.checkIsMutable() val oldValue = this._value this._value = newValue return oldValue @@ -67,6 +71,7 @@ public actual abstract class AbstractMutableMap protected actual construct } override fun remove(element: K): Boolean { + checkIsMutable() if (containsKey(element)) { this@AbstractMutableMap.remove(element) return true @@ -75,6 +80,8 @@ public actual abstract class AbstractMutableMap protected actual construct } override val size: Int get() = this@AbstractMutableMap.size + + override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable() } } return _keys!! @@ -83,6 +90,7 @@ public actual abstract class AbstractMutableMap protected actual construct actual abstract override fun put(key: K, value: V): V? actual override fun putAll(from: Map) { + checkIsMutable() for ((key, value) in from) { put(key, value) } @@ -117,12 +125,15 @@ public actual abstract class AbstractMutableMap protected actual construct } override fun hashCode(): Int = AbstractList.orderedHashCode(this) + + override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable() } } return _values!! } actual override fun remove(key: K): V? { + checkIsMutable() val iter = entries.iterator() while (iter.hasNext()) { val entry = iter.next() @@ -136,4 +147,10 @@ public actual abstract class AbstractMutableMap protected actual construct return null } + + /** + * This method is called every time when a mutating method is called on this mutable map. + * Mutable maps that are built (frozen) must throw `UnsupportedOperationException`. + */ + internal open fun checkIsMutable(): Unit {} } diff --git a/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt b/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt index 64557ef4f3b..885d46ca700 100644 --- a/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt +++ b/libraries/stdlib/js/src/kotlin/collections/ArrayList.kt @@ -13,6 +13,7 @@ package kotlin.collections * capacity and "growth increment" concepts. */ public actual open class ArrayList internal constructor(private var array: Array) : AbstractMutableList(), MutableList, RandomAccess { + private var isReadOnly: Boolean = false /** * Creates an empty [ArrayList]. @@ -31,6 +32,13 @@ public actual open class ArrayList internal constructor(private var array: Ar */ public actual constructor(elements: Collection) : this(elements.toTypedArray()) {} + @PublishedApi + internal fun build(): List { + checkIsMutable() + isReadOnly = true + return this + } + /** Does nothing in this ArrayList implementation. */ public actual fun trimToSize() {} @@ -41,23 +49,27 @@ public actual open class ArrayList internal constructor(private var array: Ar @Suppress("UNCHECKED_CAST") actual override fun get(index: Int): E = array[rangeCheck(index)] as E actual override fun set(index: Int, element: E): E { + checkIsMutable() rangeCheck(index) @Suppress("UNCHECKED_CAST") return array[index].apply { array[index] = element } as E } actual override fun add(element: E): Boolean { + checkIsMutable() array.asDynamic().push(element) modCount++ return true } actual override fun add(index: Int, element: E): Unit { + checkIsMutable() array.asDynamic().splice(insertionRangeCheck(index), 0, element) modCount++ } actual override fun addAll(elements: Collection): Boolean { + checkIsMutable() if (elements.isEmpty()) return false array += elements.toTypedArray() @@ -66,6 +78,7 @@ public actual open class ArrayList internal constructor(private var array: Ar } actual override fun addAll(index: Int, elements: Collection): Boolean { + checkIsMutable() insertionRangeCheck(index) if (index == size) return addAll(elements) @@ -81,6 +94,7 @@ public actual open class ArrayList internal constructor(private var array: Ar } actual override fun removeAt(index: Int): E { + checkIsMutable() rangeCheck(index) modCount++ return if (index == lastIndex) @@ -90,6 +104,7 @@ public actual open class ArrayList internal constructor(private var array: Ar } actual override fun remove(element: E): Boolean { + checkIsMutable() for (index in array.indices) { if (array[index] == element) { array.asDynamic().splice(index, 1) @@ -101,11 +116,13 @@ public actual open class ArrayList internal constructor(private var array: Ar } override fun removeRange(fromIndex: Int, toIndex: Int) { + checkIsMutable() modCount++ array.asDynamic().splice(fromIndex, toIndex - fromIndex) } actual override fun clear() { + checkIsMutable() array = emptyArray() modCount++ } @@ -119,6 +136,10 @@ public actual open class ArrayList internal constructor(private var array: Ar override fun toArray(): Array = js("[]").slice.call(array) + internal override fun checkIsMutable() { + if (isReadOnly) throw UnsupportedOperationException() + } + private fun rangeCheck(index: Int) = index.apply { AbstractList.checkElementIndex(index, size) } diff --git a/libraries/stdlib/js/src/kotlin/collections/HashMap.kt b/libraries/stdlib/js/src/kotlin/collections/HashMap.kt index 91a145dfec3..8cbdd4d17e9 100644 --- a/libraries/stdlib/js/src/kotlin/collections/HashMap.kt +++ b/libraries/stdlib/js/src/kotlin/collections/HashMap.kt @@ -16,6 +16,8 @@ import kotlin.collections.MutableMap.MutableEntry * * This implementation makes no guarantees regarding the order of enumeration of [keys], [values] and [entries] collections. */ +// Classes that extend HashMap and implement `build()` (freezing) operation +// have to make sure mutating methods check `checkIsMutable`. public actual open class HashMap : AbstractMutableMap, MutableMap { private inner class EntrySet : AbstractMutableSet>() { diff --git a/libraries/stdlib/js/src/kotlin/collections/HashSet.kt b/libraries/stdlib/js/src/kotlin/collections/HashSet.kt index 826c8bf62d9..9f099aa7391 100644 --- a/libraries/stdlib/js/src/kotlin/collections/HashSet.kt +++ b/libraries/stdlib/js/src/kotlin/collections/HashSet.kt @@ -12,9 +12,11 @@ package kotlin.collections /** * The implementation of the [MutableSet] interface, backed by a [HashMap] instance. */ +// Classes that extend HashSet and implement `build()` (freezing) operation +// have to make sure mutating methods check `checkIsMutable`. public actual open class HashSet : AbstractMutableSet, MutableSet { - private val map: HashMap + internal val map: HashMap /** * Constructs a new empty [HashSet]. diff --git a/libraries/stdlib/js/src/kotlin/collections/LinkedHashMap.kt b/libraries/stdlib/js/src/kotlin/collections/LinkedHashMap.kt index 051974d59a7..67057019bb6 100644 --- a/libraries/stdlib/js/src/kotlin/collections/LinkedHashMap.kt +++ b/libraries/stdlib/js/src/kotlin/collections/LinkedHashMap.kt @@ -30,9 +30,14 @@ public actual open class LinkedHashMap : HashMap, MutableMap { * small modifications. Paying a small storage cost only if you use * LinkedHashMap and minimizing code size seemed like a better tradeoff */ - private class ChainEntry(key: K, value: V) : AbstractMutableMap.SimpleEntry(key, value) { + private inner class ChainEntry(key: K, value: V) : AbstractMutableMap.SimpleEntry(key, value) { internal var next: ChainEntry? = null internal var prev: ChainEntry? = null + + override fun setValue(newValue: V): V { + this@LinkedHashMap.checkIsMutable() + return super.setValue(newValue) + } } private inner class EntrySet : AbstractMutableSet>() { @@ -65,6 +70,7 @@ public actual open class LinkedHashMap : HashMap, MutableMap { override fun remove() { check(last != null) + this@EntrySet.checkIsMutable() // checkStructuralChange(map, this) last!!.remove() @@ -84,6 +90,7 @@ public actual open class LinkedHashMap : HashMap, MutableMap { override operator fun iterator(): MutableIterator> = EntryIterator() override fun remove(element: MutableEntry): Boolean { + checkIsMutable() if (contains(element)) { this@LinkedHashMap.remove(element.key) return true @@ -92,6 +99,8 @@ public actual open class LinkedHashMap : HashMap, MutableMap { } override val size: Int get() = this@LinkedHashMap.size + + override fun checkIsMutable(): Unit = this@LinkedHashMap.checkIsMutable() } @@ -154,6 +163,8 @@ public actual open class LinkedHashMap : HashMap, MutableMap { */ private val map: HashMap> + private var isReadOnly: Boolean = false + /** * Constructs an empty [LinkedHashMap] instance. */ @@ -189,7 +200,15 @@ public actual open class LinkedHashMap : HashMap, MutableMap { this.putAll(original) } + @PublishedApi + internal fun build(): Map { + checkIsMutable() + isReadOnly = true + return this + } + actual override fun clear() { + checkIsMutable() map.clear() head = null } @@ -219,6 +238,8 @@ public actual open class LinkedHashMap : HashMap, MutableMap { actual override operator fun get(key: K): V? = map.get(key)?.value actual override fun put(key: K, value: V): V? { + checkIsMutable() + val old = map.get(key) if (old == null) { val newEntry = ChainEntry(key, value) @@ -231,6 +252,8 @@ public actual open class LinkedHashMap : HashMap, MutableMap { } actual override fun remove(key: K): V? { + checkIsMutable() + val entry = map.remove(key) if (entry != null) { entry.remove() @@ -241,6 +264,9 @@ public actual open class LinkedHashMap : HashMap, MutableMap { actual override val size: Int get() = map.size + internal override fun checkIsMutable() { + if (isReadOnly) throw UnsupportedOperationException() + } } /** diff --git a/libraries/stdlib/js/src/kotlin/collections/LinkedHashSet.kt b/libraries/stdlib/js/src/kotlin/collections/LinkedHashSet.kt index 285566aaee6..b599a3446bb 100644 --- a/libraries/stdlib/js/src/kotlin/collections/LinkedHashSet.kt +++ b/libraries/stdlib/js/src/kotlin/collections/LinkedHashSet.kt @@ -43,6 +43,14 @@ public actual open class LinkedHashSet : HashSet, MutableSet { actual constructor(initialCapacity: Int) : this(initialCapacity, 0.0f) + @PublishedApi + internal fun build(): Set { + (map as LinkedHashMap).build() + return this + } + + internal override fun checkIsMutable(): Unit = map.checkIsMutable() + // public override fun clone(): Any { // return LinkedHashSet(this) // } diff --git a/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt b/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt index c35fb7a6246..90fa8721a9b 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt @@ -8,6 +8,7 @@ package kotlin.collections +import kotlin.collections.builders.ListBuilder import kotlin.internal.InlineOnly import kotlin.internal.apiVersionIsAtLeast @@ -18,6 +19,42 @@ import kotlin.internal.apiVersionIsAtLeast */ public fun listOf(element: T): List = java.util.Collections.singletonList(element) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(builderAction: MutableList.() -> Unit): List { + return build(createListBuilder().apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(capacity: Int, builderAction: MutableList.() -> Unit): List { + return build(createListBuilder(capacity).apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createListBuilder(): MutableList { + return ListBuilder() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createListBuilder(capacity: Int): MutableList { + return ListBuilder(capacity) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun build(builder: MutableList): List { + return (builder as ListBuilder).build() +} /** * Returns a list containing the elements returned by this enumeration diff --git a/libraries/stdlib/jvm/src/kotlin/collections/MapsJVM.kt b/libraries/stdlib/jvm/src/kotlin/collections/MapsJVM.kt index 4227236653e..10486f73467 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/MapsJVM.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/MapsJVM.kt @@ -9,11 +9,11 @@ package kotlin.collections import java.util.Comparator -import java.util.LinkedHashMap import java.util.Properties import java.util.SortedMap import java.util.TreeMap import java.util.concurrent.ConcurrentMap +import kotlin.collections.builders.MapBuilder /** @@ -26,6 +26,43 @@ import java.util.concurrent.ConcurrentMap */ public fun mapOf(pair: Pair): Map = java.util.Collections.singletonMap(pair.first, pair.second) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map { + return build(createMapBuilder().apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map { + return build(createMapBuilder(capacity).apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createMapBuilder(): MutableMap { + return MapBuilder() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createMapBuilder(capacity: Int): MutableMap { + return MapBuilder(capacity) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun build(builder: MutableMap): Map { + return (builder as MapBuilder).build() +} + /** * Concurrent getOrPut, that is safe for concurrent maps. @@ -111,13 +148,3 @@ internal actual fun mapCapacity(expectedSize: Int): Int = when { else -> Int.MAX_VALUE } private const val INT_MAX_POWER_OF_TWO: Int = 1 shl (Int.SIZE_BITS - 2) - -/** - * Checks a collection builder function capacity argument. - * Does nothing, capacity is validated in List/Set/Map constructor - */ -@SinceKotlin("1.3") -@ExperimentalStdlibApi -@PublishedApi -@kotlin.internal.InlineOnly -internal actual inline fun checkBuilderCapacity(capacity: Int) {} \ No newline at end of file diff --git a/libraries/stdlib/jvm/src/kotlin/collections/SetsJVM.kt b/libraries/stdlib/jvm/src/kotlin/collections/SetsJVM.kt index d6213a07890..e58181e9e76 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/SetsJVM.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/SetsJVM.kt @@ -8,6 +8,8 @@ package kotlin.collections +import kotlin.collections.builders.SetBuilder + /** * Returns an immutable set containing only the specified object [element]. @@ -15,6 +17,43 @@ package kotlin.collections */ public fun setOf(element: T): Set = java.util.Collections.singleton(element) +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(builderAction: MutableSet.() -> Unit): Set { + return build(createSetBuilder().apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(capacity: Int, builderAction: MutableSet.() -> Unit): Set { + return build(createSetBuilder(capacity).apply(builderAction)) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createSetBuilder(): MutableSet { + return SetBuilder() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun createSetBuilder(capacity: Int): MutableSet { + return SetBuilder(capacity) +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +internal fun build(builder: MutableSet): Set { + return (builder as SetBuilder).build() +} + /** * Returns a new [java.util.SortedSet] with the given elements. diff --git a/libraries/stdlib/src/kotlin/collections/builders/ListBuilder.kt b/libraries/stdlib/jvm/src/kotlin/collections/builders/ListBuilder.kt similarity index 97% rename from libraries/stdlib/src/kotlin/collections/builders/ListBuilder.kt rename to libraries/stdlib/jvm/src/kotlin/collections/builders/ListBuilder.kt index 42719a6dec2..cf4a27cf413 100644 --- a/libraries/stdlib/src/kotlin/collections/builders/ListBuilder.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/builders/ListBuilder.kt @@ -5,19 +5,19 @@ package kotlin.collections.builders -@PublishedApi internal class ListBuilder private constructor( private var array: Array, private var offset: Int, private var length: Int, private var isReadOnly: Boolean, - private val backing: ListBuilder? + private val backing: ListBuilder?, + private val root: ListBuilder? ) : MutableList, RandomAccess, AbstractMutableList() { constructor() : this(10) constructor(initialCapacity: Int) : this( - arrayOfUninitializedElements(initialCapacity), 0, 0, false, null) + arrayOfUninitializedElements(initialCapacity), 0, 0, false, null, null) fun build(): List { if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ListBuilder @@ -127,7 +127,7 @@ internal class ListBuilder private constructor( override fun subList(fromIndex: Int, toIndex: Int): MutableList { AbstractList.checkRangeIndexes(fromIndex, toIndex, length) - return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this) + return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this, root ?: this) } @OptIn(ExperimentalStdlibApi::class) @@ -155,7 +155,7 @@ internal class ListBuilder private constructor( // ---------------------------- private ---------------------------- private fun checkIsMutable() { - if (isReadOnly) throw UnsupportedOperationException() + if (isReadOnly || root != null && root.isReadOnly) throw UnsupportedOperationException() } private fun ensureExtraCapacity(n: Int) { @@ -277,9 +277,8 @@ internal class ListBuilder private constructor( } override fun set(element: E) { - list.checkIsMutable() check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." } - list.array[list.offset + lastIndex] = element + list.set(lastIndex, element) } override fun add(element: E) { diff --git a/libraries/stdlib/src/kotlin/collections/builders/MapBuilder.kt b/libraries/stdlib/jvm/src/kotlin/collections/builders/MapBuilder.kt similarity index 91% rename from libraries/stdlib/src/kotlin/collections/builders/MapBuilder.kt rename to libraries/stdlib/jvm/src/kotlin/collections/builders/MapBuilder.kt index 03487672d19..221761596a8 100644 --- a/libraries/stdlib/src/kotlin/collections/builders/MapBuilder.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/builders/MapBuilder.kt @@ -5,7 +5,6 @@ package kotlin.collections.builders -@PublishedApi internal class MapBuilder private constructor( private var keysArray: Array, private var valuesArray: Array?, // allocated only when actually used, always null in pure HashSet @@ -19,9 +18,9 @@ internal class MapBuilder private constructor( override var size: Int = 0 private set - private var keysView: HashMapKeys? = null - private var valuesView: HashMapValues? = null - private var entriesView: HashMapEntrySet? = null + private var keysView: MapBuilderKeys? = null + private var valuesView: MapBuilderValues? = null + private var entriesView: MapBuilderEntries? = null private var isReadOnly: Boolean = false @@ -68,7 +67,8 @@ internal class MapBuilder private constructor( } override fun putAll(from: Map) { - putAllEntries(from.entries) // mutability gets checked here + checkIsMutable() + putAllEntries(from.entries) } override fun remove(key: K): V? { @@ -99,7 +99,7 @@ internal class MapBuilder private constructor( override val keys: MutableSet get() { val cur = keysView return if (cur == null) { - val new = HashMapKeys(this) + val new = MapBuilderKeys(this) keysView = new new } else cur @@ -108,7 +108,7 @@ internal class MapBuilder private constructor( override val values: MutableCollection get() { val cur = valuesView return if (cur == null) { - val new = HashMapValues(this) + val new = MapBuilderValues(this) valuesView = new new } else cur @@ -117,7 +117,7 @@ internal class MapBuilder private constructor( override val entries: MutableSet> get() { val cur = entriesView return if (cur == null) { - val new = HashMapEntrySet(this) + val new = MapBuilderEntries(this) entriesView = new return new } else cur @@ -157,7 +157,7 @@ internal class MapBuilder private constructor( private val capacity: Int get() = keysArray.size private val hashSize: Int get() = hashArray.size - private fun checkIsMutable() { + internal fun checkIsMutable() { if (isReadOnly) throw UnsupportedOperationException() } @@ -382,8 +382,7 @@ internal class MapBuilder private constructor( return true } - internal fun putEntry(entry: Map.Entry): Boolean { - checkIsMutable() + private fun putEntry(entry: Map.Entry): Boolean { val index = addKey(entry.key) val valuesArray = allocateValuesArray() if (index >= 0) { @@ -398,8 +397,7 @@ internal class MapBuilder private constructor( return false } - internal fun putAllEntries(from: Collection>): Boolean { - checkIsMutable() + private fun putAllEntries(from: Collection>): Boolean { if (from.isEmpty()) return false ensureExtraCapacity(from.size) val it = from.iterator() @@ -549,7 +547,7 @@ internal class MapBuilder private constructor( } } -internal class HashMapKeys internal constructor( +internal class MapBuilderKeys internal constructor( private val backing: MapBuilder ) : MutableSet, AbstractMutableSet() { @@ -561,9 +559,19 @@ internal class HashMapKeys internal constructor( override fun addAll(elements: Collection): Boolean = throw UnsupportedOperationException() override fun remove(element: E): Boolean = backing.removeKey(element) >= 0 override fun iterator(): MutableIterator = backing.keysIterator() + + override fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } } -internal class HashMapValues internal constructor( +internal class MapBuilderValues internal constructor( val backing: MapBuilder<*, V> ) : MutableCollection, AbstractMutableCollection() { @@ -575,9 +583,19 @@ internal class HashMapValues internal constructor( override fun clear() = backing.clear() override fun iterator(): MutableIterator = backing.valuesIterator() override fun remove(element: V): Boolean = backing.removeValue(element) + + override fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } } -internal class HashMapEntrySet internal constructor( +internal class MapBuilderEntries internal constructor( val backing: MapBuilder ) : MutableSet>, AbstractMutableSet>() { @@ -585,9 +603,19 @@ internal class HashMapEntrySet internal constructor( override fun isEmpty(): Boolean = backing.isEmpty() override fun contains(element: MutableMap.MutableEntry): Boolean = backing.containsEntry(element) override fun clear() = backing.clear() - override fun add(element: MutableMap.MutableEntry): Boolean = backing.putEntry(element) + override fun add(element: MutableMap.MutableEntry): Boolean = throw UnsupportedOperationException() + override fun addAll(elements: Collection>): Boolean = throw UnsupportedOperationException() override fun remove(element: MutableMap.MutableEntry): Boolean = backing.removeEntry(element) override fun iterator(): MutableIterator> = backing.entriesIterator() override fun containsAll(elements: Collection>): Boolean = backing.containsAllEntries(elements) - override fun addAll(elements: Collection>): Boolean = backing.putAllEntries(elements) + + override fun removeAll(elements: Collection>): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection>): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } } diff --git a/libraries/stdlib/src/kotlin/collections/builders/SetBuilder.kt b/libraries/stdlib/jvm/src/kotlin/collections/builders/SetBuilder.kt similarity index 71% rename from libraries/stdlib/src/kotlin/collections/builders/SetBuilder.kt rename to libraries/stdlib/jvm/src/kotlin/collections/builders/SetBuilder.kt index e603666d4d4..5d8298e0363 100644 --- a/libraries/stdlib/src/kotlin/collections/builders/SetBuilder.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/builders/SetBuilder.kt @@ -5,7 +5,6 @@ package kotlin.collections.builders -@PublishedApi internal class SetBuilder internal constructor( private val backing: MapBuilder ) : MutableSet, AbstractMutableSet() { @@ -26,4 +25,19 @@ internal class SetBuilder internal constructor( override fun add(element: E): Boolean = backing.addKey(element) >= 0 override fun remove(element: E): Boolean = backing.removeKey(element) >= 0 override fun iterator(): MutableIterator = backing.keysIterator() + + override fun addAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.addAll(elements) + } + + override fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } } \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/collections/Collections.kt b/libraries/stdlib/src/kotlin/collections/Collections.kt index aefaf821ae3..1493d51d962 100644 --- a/libraries/stdlib/src/kotlin/collections/Collections.kt +++ b/libraries/stdlib/src/kotlin/collections/Collections.kt @@ -11,7 +11,6 @@ package kotlin.collections import kotlin.contracts.* import kotlin.random.Random -import kotlin.collections.builders.* internal object EmptyIterator : ListIterator { override fun hasNext(): Boolean = false @@ -170,9 +169,15 @@ public inline fun MutableList(size: Int, init: (index: Int) -> T): MutableLi @kotlin.internal.InlineOnly public inline fun buildList(@BuilderInference builderAction: MutableList.() -> Unit): List { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return ListBuilder().apply(builderAction).build() + return buildListInternal(builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildListInternal(builderAction: MutableList.() -> Unit): List + /** * Builds a new read-only [List] by populating a [MutableList] using the given [builderAction] * and returning a read-only list with the same elements. @@ -191,9 +196,14 @@ public inline fun buildList(@BuilderInference builderAction: MutableList. @kotlin.internal.InlineOnly public inline fun buildList(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return ListBuilder(capacity).apply(builderAction).build() + return buildListInternal(capacity, builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildListInternal(capacity: Int, builderAction: MutableList.() -> Unit): List /** * Returns an [IntRange] of the valid indices for this collection. diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index e872fb0df0f..43ea50b16bf 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -9,7 +9,6 @@ package kotlin.collections -import kotlin.collections.builders.MapBuilder import kotlin.contracts.* private object EmptyMap : Map, Serializable { @@ -140,9 +139,15 @@ public fun linkedMapOf(vararg pairs: Pair): LinkedHashMap = p @kotlin.internal.InlineOnly public inline fun buildMap(@BuilderInference builderAction: MutableMap.() -> Unit): Map { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return MapBuilder().apply(builderAction).build() + return buildMapInternal(builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map + /** * Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction] * and returning a read-only map with the same key-value pairs. @@ -163,23 +168,21 @@ public inline fun buildMap(@BuilderInference builderAction: MutableMap buildMap(capacity: Int, @BuilderInference builderAction: MutableMap.() -> Unit): Map { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return MapBuilder(capacity).apply(builderAction).build() + return buildMapInternal(capacity, builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map + /** * Calculate the initial capacity of a map. */ @PublishedApi internal expect fun mapCapacity(expectedSize: Int): Int -/** - * Checks a collection builder function capacity argument. - */ -@SinceKotlin("1.3") -@ExperimentalStdlibApi -@PublishedApi -internal expect fun checkBuilderCapacity(capacity: Int) - /** * Returns `true` if this map is not empty. * @sample samples.collections.Maps.Usage.mapIsNotEmpty diff --git a/libraries/stdlib/src/kotlin/collections/Sets.kt b/libraries/stdlib/src/kotlin/collections/Sets.kt index 875c4a7da8c..b6c9eec0cfd 100644 --- a/libraries/stdlib/src/kotlin/collections/Sets.kt +++ b/libraries/stdlib/src/kotlin/collections/Sets.kt @@ -10,7 +10,6 @@ package kotlin.collections import kotlin.contracts.* -import kotlin.collections.builders.* internal object EmptySet : Set, Serializable { private const val serialVersionUID: Long = 3406603774387020532 @@ -126,9 +125,15 @@ public fun setOfNotNull(vararg elements: T?): Set { @kotlin.internal.InlineOnly public inline fun buildSet(@BuilderInference builderAction: MutableSet.() -> Unit): Set { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return SetBuilder().apply(builderAction).build() + return buildSetInternal(builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildSetInternal(builderAction: MutableSet.() -> Unit): Set + /** * Builds a new read-only [Set] by populating a [MutableSet] using the given [builderAction] * and returning a read-only set with the same elements. @@ -149,9 +154,15 @@ public inline fun buildSet(@BuilderInference builderAction: MutableSet.() @kotlin.internal.InlineOnly public inline fun buildSet(capacity: Int, @BuilderInference builderAction: MutableSet.() -> Unit): Set { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return SetBuilder(capacity).apply(builderAction).build() + return buildSetInternal(capacity, builderAction) } +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal expect inline fun buildSetInternal(capacity: Int, builderAction: MutableSet.() -> Unit): Set + /** Returns this Set if it's not `null` and the empty set otherwise. */ @kotlin.internal.InlineOnly diff --git a/libraries/stdlib/test/collections/ContainerBuilderTest.kt b/libraries/stdlib/test/collections/ContainerBuilderTest.kt index 2c6d2179675..46c55c90d6d 100644 --- a/libraries/stdlib/test/collections/ContainerBuilderTest.kt +++ b/libraries/stdlib/test/collections/ContainerBuilderTest.kt @@ -6,35 +6,55 @@ import test.collections.behaviors.setBehavior import kotlin.test.* class ContainerBuilderTest { - private fun mutableCollectionOperations(e: E) = listOf.() -> Unit>( - { add(e) }, - { addAll(listOf(e)) }, - { remove(e) }, - { removeAll(listOf(e)) }, - { retainAll(listOf(e)) }, - { clear() }, - { iterator().apply { next() }.remove() } + private fun mutableCollectionOperations(present: E, absent: E) = listOf.() -> Unit>>( + "add(present)" to { add(present) }, + "add(absent)" to { add(absent) }, + + "addAll(listOf(present))" to { addAll(listOf(present)) }, + "addAll(listOf(absent))" to { addAll(listOf(absent)) }, + "addAll(emptyList())" to { addAll(emptyList()) }, + + "remove(present)" to { remove(present) }, + "remove(absent)" to { remove(absent) }, + + "removeAll(listOf(present))" to { removeAll(listOf(present)) }, + "removeAll(emptyList())" to { removeAll(emptyList()) }, + "removeAll(this.toList())" to { removeAll(this.toList()) }, + + "retainAll(listOf(present))" to { retainAll(listOf(present)) }, + "retainAll(emptyList())" to { retainAll(emptyList()) }, + "retainAll(this.toList())" to { retainAll(this.toList()) }, + + "clear()" to { clear() }, + + "iterator().apply { next() }.remove()" to { iterator().apply { next() }.remove() } ) - private fun mutableListOperations(e: E) = mutableCollectionOperations(e) + listOf.() -> Unit>( - { add(0, e) }, - { addAll(0, listOf(e)) }, - { removeAt(0) }, - { set(0, e) }, - { listIterator().apply { next() }.remove() }, - { listIterator(0).apply { next() }.remove() }, - { listIterator().add(e) } + private fun mutableListOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf.() -> Unit>>( + "add(0, present)" to { add(0, present) }, + "addAll(0, listOf(present))" to { addAll(0, listOf(present)) }, + "addAll(0, emptyList())" to { addAll(0, emptyList()) }, + "removeAt(0)" to { removeAt(0) }, + "set(0, present)" to { set(0, present) }, + "listIterator().apply { next() }.remove()" to { listIterator().apply { next() }.remove() }, + "listIterator(0).apply { next() }.remove()" to { listIterator(0).apply { next() }.remove() }, + "listIterator().apply { next() }.set(present)" to { listIterator().apply { next() }.set(present) }, + "listIterator().add(present)" to { listIterator().add(present) } ) - private fun mutableSetOperations(e: E): List.() -> Unit> = mutableCollectionOperations(e) + private fun mutableSetOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf.() -> Unit>>( + // check java.util.AbstractSet.removeAll optimisation + "removeAll(List(this.size) { absent })" to { removeAll(List(this.size) { absent }) } + ) - private fun mutableMapOperations(k: K, v: V) = listOf.() -> Unit>( - { put(k, v) }, - { remove(k) }, - { putAll(mapOf(k to v)) }, - { clear() }, - { entries.first().setValue(v) }, - { entries.iterator().next().setValue(v) } + private fun mutableMapOperations(k: K, v: V) = listOf.() -> Unit>>( + "put(k, v)" to { put(k, v) }, + "remove(k)" to { remove(k) }, + "putAll(mapOf(k to v))" to { putAll(mapOf(k to v)) }, + "putAll(emptyMap())" to { putAll(emptyMap()) }, + "clear()" to { clear() }, + "entries.first().setValue(v)" to { entries.first().setValue(v) }, + "entries.iterator().next().setValue(v)" to { entries.iterator().next().setValue(v) } ) @Test @@ -44,10 +64,14 @@ class ContainerBuilderTest { add('c') } - val y = buildList(4) { + val subList: MutableList + + val y = buildList(4) { add('a') addAll(x) add('d') + + subList = subList(0, 4) } compare(listOf('a', 'b', 'c', 'd'), y) { listBehavior() } @@ -60,9 +84,10 @@ class ContainerBuilderTest { } assertTrue(y is MutableList) - for (operation in mutableListOperations('a')) { - assertFailsWith { y.operation() } - assertFailsWith { y.subList(1, 3).operation() } + for ((fName, operation) in mutableListOperations('b', 'x')) { + assertFailsWith("y.$fName") { y.operation() } + assertFailsWith("y.subList(1, 3).$fName") { y.subList(1, 3).operation() } + assertFailsWith("subList.$fName") { subList.operation() } } } @@ -90,10 +115,12 @@ class ContainerBuilderTest { val subSubList = subList.subList(2, 4) // buffer reallocation should happen repeat(20) { subSubList.add('x') } + repeat(20) { subSubList.add(subSubList.size - 2 * it, 'y') } - compare("ab123${"x".repeat(20)}e".toList(), this) { listBehavior() } - compare("b123${"x".repeat(20)}".toList(), subList) { listBehavior() } - compare("23${"x".repeat(20)}".toList(), subSubList) { listBehavior() } + val addedChars = "xy".repeat(20) + compare("ab123${addedChars}e".toList(), this) { listBehavior() } + compare("b123$addedChars".toList(), subList) { listBehavior() } + compare("23$addedChars".toList(), subSubList) { listBehavior() } } } @@ -118,8 +145,8 @@ class ContainerBuilderTest { } assertTrue(y is MutableSet) - for (operation in mutableSetOperations('b')) { - assertFailsWith { y.operation() } + for ((fName, operation) in mutableSetOperations('b', 'x')) { + assertFailsWith("y.$fName") { y.operation() } } } @@ -145,17 +172,23 @@ class ContainerBuilderTest { } assertTrue(y is MutableMap) - for (operation in mutableMapOperations('a', 0)) { - assertFailsWith { y.operation() } + for ((fName, operation) in mutableMapOperations('a', 1) + mutableMapOperations('x', 10)) { + assertFailsWith("y.$fName") { y.operation() } } - for (operation in mutableSetOperations('a')) { - assertFailsWith { y.keys.operation() } + for ((fName, operation) in mutableSetOperations('a', 'x')) { + assertFailsWith("y.keys.$fName") { y.keys.operation() } } - for (operation in mutableCollectionOperations(1)) { - assertFailsWith { y.values.operation() } + for ((fName, operation) in mutableCollectionOperations(1, 10)) { + assertFailsWith("y.values.$fName") { y.values.operation() } } - for (operation in mutableSetOperations(y.entries.first())) { - assertFailsWith { y.entries.operation() } + val presentEntry = y.entries.first() + val absentEntry: MutableMap.MutableEntry = object : MutableMap.MutableEntry { + override val key: Char get() = 'x' + override val value: Int get() = 10 + override fun setValue(newValue: Int): Int = fail("Unreachable") + } + for ((fName, operation) in mutableSetOperations(presentEntry, absentEntry)) { + assertFailsWith("y.entries.$fName") { y.entries.operation() } } } } diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index f26c39cfc6d..0f37a6eac32 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -2082,6 +2082,7 @@ public final class kotlin/collections/CollectionsKt { public static synthetic fun binarySearch$default (Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;IIILjava/lang/Object;)I public static final fun binarySearchBy (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;)I public static synthetic fun binarySearchBy$default (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I + public static final fun build (Ljava/util/List;)Ljava/util/List; public static final fun chunked (Ljava/lang/Iterable;I)Ljava/util/List; public static final fun chunked (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun collectionSizeOrDefault (Ljava/lang/Iterable;I)I @@ -2089,6 +2090,8 @@ public final class kotlin/collections/CollectionsKt { public static final fun contains (Ljava/lang/Iterable;Ljava/lang/Object;)Z public static final fun count (Ljava/lang/Iterable;)I public static final fun count (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)I + public static final fun createListBuilder ()Ljava/util/List; + public static final fun createListBuilder (I)Ljava/util/List; public static final fun distinct (Ljava/lang/Iterable;)Ljava/util/List; public static final fun distinctBy (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun drop (Ljava/lang/Iterable;I)Ljava/util/List; @@ -2369,7 +2372,10 @@ public final class kotlin/collections/MapsKt { public static final fun any (Ljava/util/Map;)Z public static final fun any (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Z public static final fun asSequence (Ljava/util/Map;)Lkotlin/sequences/Sequence; + public static final fun build (Ljava/util/Map;)Ljava/util/Map; public static final fun count (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)I + public static final fun createMapBuilder ()Ljava/util/Map; + public static final fun createMapBuilder (I)Ljava/util/Map; public static final fun emptyMap ()Ljava/util/Map; public static final fun filter (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun filterKeys (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; @@ -2434,6 +2440,9 @@ public final class kotlin/collections/MapsKt { } public final class kotlin/collections/SetsKt { + public static final fun build (Ljava/util/Set;)Ljava/util/Set; + public static final fun createSetBuilder ()Ljava/util/Set; + public static final fun createSetBuilder (I)Ljava/util/Set; public static final fun emptySet ()Ljava/util/Set; public static final fun hashSetOf ([Ljava/lang/Object;)Ljava/util/HashSet; public static final fun linkedSetOf ([Ljava/lang/Object;)Ljava/util/LinkedHashSet; @@ -2505,72 +2514,6 @@ public abstract class kotlin/collections/UShortIterator : java/util/Iterator, ko public fun remove ()V } -public final class kotlin/collections/builders/ListBuilder : kotlin/collections/AbstractMutableList, java/util/List, java/util/RandomAccess, kotlin/jvm/internal/markers/KMutableList { - public fun ()V - public fun (I)V - public fun add (ILjava/lang/Object;)V - public fun add (Ljava/lang/Object;)Z - public fun addAll (ILjava/util/Collection;)Z - public fun addAll (Ljava/util/Collection;)Z - public final fun build ()Ljava/util/List; - public fun clear ()V - public fun equals (Ljava/lang/Object;)Z - public fun get (I)Ljava/lang/Object; - public fun getSize ()I - public fun hashCode ()I - public fun indexOf (Ljava/lang/Object;)I - public fun isEmpty ()Z - public fun iterator ()Ljava/util/Iterator; - public fun lastIndexOf (Ljava/lang/Object;)I - public fun listIterator ()Ljava/util/ListIterator; - public fun listIterator (I)Ljava/util/ListIterator; - public fun remove (Ljava/lang/Object;)Z - public fun removeAll (Ljava/util/Collection;)Z - public fun removeAt (I)Ljava/lang/Object; - public fun retainAll (Ljava/util/Collection;)Z - public fun set (ILjava/lang/Object;)Ljava/lang/Object; - public fun subList (II)Ljava/util/List; - public fun toString ()Ljava/lang/String; -} - -public final class kotlin/collections/builders/MapBuilder : java/util/Map, kotlin/jvm/internal/markers/KMutableMap { - public fun ()V - public fun (I)V - public final fun build ()Ljava/util/Map; - public fun clear ()V - public fun containsKey (Ljava/lang/Object;)Z - public fun containsValue (Ljava/lang/Object;)Z - public final fun entrySet ()Ljava/util/Set; - public fun equals (Ljava/lang/Object;)Z - public fun get (Ljava/lang/Object;)Ljava/lang/Object; - public fun getEntries ()Ljava/util/Set; - public fun getKeys ()Ljava/util/Set; - public fun getSize ()I - public fun getValues ()Ljava/util/Collection; - public fun hashCode ()I - public fun isEmpty ()Z - public final fun keySet ()Ljava/util/Set; - public fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun putAll (Ljava/util/Map;)V - public fun remove (Ljava/lang/Object;)Ljava/lang/Object; - public final fun size ()I - public fun toString ()Ljava/lang/String; - public final fun values ()Ljava/util/Collection; -} - -public final class kotlin/collections/builders/SetBuilder : kotlin/collections/AbstractMutableSet, java/util/Set, kotlin/jvm/internal/markers/KMutableSet { - public fun ()V - public fun (I)V - public fun add (Ljava/lang/Object;)Z - public final fun build ()Ljava/util/Set; - public fun clear ()V - public fun contains (Ljava/lang/Object;)Z - public fun getSize ()I - public fun isEmpty ()Z - public fun iterator ()Ljava/util/Iterator; - public fun remove (Ljava/lang/Object;)Z -} - public final class kotlin/collections/unsigned/UArraysKt { public static final fun asList--ajY-9A ([I)Ljava/util/List; public static final fun asList-GBYM_sE ([B)Ljava/util/List;