diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index e9c142c9011..e309ddc0181 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -575,6 +575,134 @@ public inline fun UShortArray.copyOfRange(fromIndex: Int, toIndex: Int): UShortA return UShortArray(storage.copyOfRange(fromIndex, toIndex)) } +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UIntArray.plus(element: UInt): UIntArray { + return UIntArray(storage + element.toInt()) +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun ULongArray.plus(element: ULong): ULongArray { + return ULongArray(storage + element.toLong()) +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UByteArray.plus(element: UByte): UByteArray { + return UByteArray(storage + element.toByte()) +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UShortArray.plus(element: UShort): UShortArray { + return UShortArray(storage + element.toShort()) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public operator fun UIntArray.plus(elements: Collection): UIntArray { + var index = size + val result = storage.copyOf(size + elements.size) + for (element in elements) result[index++] = element.toInt() + return UIntArray(result) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public operator fun ULongArray.plus(elements: Collection): ULongArray { + var index = size + val result = storage.copyOf(size + elements.size) + for (element in elements) result[index++] = element.toLong() + return ULongArray(result) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public operator fun UByteArray.plus(elements: Collection): UByteArray { + var index = size + val result = storage.copyOf(size + elements.size) + for (element in elements) result[index++] = element.toByte() + return UByteArray(result) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public operator fun UShortArray.plus(elements: Collection): UShortArray { + var index = size + val result = storage.copyOf(size + elements.size) + for (element in elements) result[index++] = element.toShort() + return UShortArray(result) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UIntArray.plus(elements: UIntArray): UIntArray { + return UIntArray(storage + elements.storage) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun ULongArray.plus(elements: ULongArray): ULongArray { + return ULongArray(storage + elements.storage) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UByteArray.plus(elements: UByteArray): UByteArray { + return UByteArray(storage + elements.storage) +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline operator fun UShortArray.plus(elements: UShortArray): UShortArray { + return UShortArray(storage + elements.storage) +} + /** * Returns an array of type [ByteArray], which is a copy of this array where each element is a signed reinterpretation * of the corresponding element of this array. diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index 54a71ebefb1..0c4b649fd17 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -99,7 +99,7 @@ class ArraysTest { assertEquals(0.toShort(), arr[0]) assertEquals(1.toShort(), arr[1]) } - + @Test fun intArray() { val arr = IntArray(2) @@ -107,7 +107,7 @@ class ArraysTest { assertEquals(0, arr[0]) assertEquals(0, arr[1]) } - + @Test fun intArrayInit() { val arr = IntArray(2) { it.toInt() } @@ -115,7 +115,7 @@ class ArraysTest { assertEquals(0.toInt(), arr[0]) assertEquals(1.toInt(), arr[1]) } - + @Test fun longArray() { val arr = LongArray(2) @@ -141,7 +141,7 @@ class ArraysTest { assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } - + @Test fun floatArrayInit() { val arr = FloatArray(2) { it.toFloat() } @@ -916,7 +916,7 @@ class ArraysTest { byteArrayOf(1, 2, 3), byteArrayOf(4, 5, 6), byteArrayOf(5, 6, 3), byteArrayOf(6, 3, 3), byteArrayOf(6, 6, 3) ) - + doTest( CharArray::copyInto, ::assertArrayNotSameButEquals, CharArray::contentToString, charArrayOf('a', 'b', 'c'), charArrayOf('e', 'f', 'g'), diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt index b2865c9df3b..662280bab6c 100644 --- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt +++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt @@ -9,6 +9,9 @@ package test.collections import test.collections.behaviors.collectionBehavior import kotlin.test.* +fun assertArrayContentEquals(expected: UIntArray, actual: UIntArray, message: String = "") { assertTrue(expected contentEquals actual, message) } + + class UnsignedArraysTest { @Test @@ -228,4 +231,11 @@ class UnsignedArraysTest { } } + @Test + fun plus() { + assertArrayContentEquals(uintArrayOf(1u, 2u, 3u), uintArrayOf(1u, 2u) + 3u) + assertArrayContentEquals(uintArrayOf(1u, 2u, 3u, 4u), uintArrayOf(1u, 2u) + listOf(3u, 4u)) + assertArrayContentEquals(uintArrayOf(1u, 2u, 3u, 4u), uintArrayOf(1u, 2u) + uintArrayOf(3u, 4u)) + } + } \ No newline at end of file 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 d6848a28d78..e0101ddada7 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 @@ -2299,6 +2299,10 @@ public final class kotlin/collections/UArraysKt { public static final fun contentToString-GBYM_sE ([B)Ljava/lang/String; public static final fun contentToString-QwZRm1k ([J)Ljava/lang/String; public static final fun contentToString-rL5Bavg ([S)Ljava/lang/String; + public static final fun plus-CFIt9YE ([ILjava/util/Collection;)[I + public static final fun plus-kzHmqpY ([JLjava/util/Collection;)[J + public static final fun plus-ojwP5H8 ([SLjava/util/Collection;)[S + public static final fun plus-xo_DsdI ([BLjava/util/Collection;)[B public static final fun random-2D5oskM ([ILkotlin/random/Random;)I public static final fun random-JzugnMA ([JLkotlin/random/Random;)J public static final fun random-oSF2wD8 ([BLkotlin/random/Random;)B diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index 405b56cd0cd..19c750b4e53 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -454,171 +454,204 @@ object ArrayOps : TemplateGroupBase() { } val f_plus = fn("plus(element: T)") { - include(InvariantArraysOfObjects, ArraysOfPrimitives) + include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builderWith { primitive -> doc { "Returns an array containing all elements of the original array and then the given [element]." } operator() returns("SELF") - on(Platform.JVM) { + specialFor(ArraysOfUnsigned) { + inlineOnly() + val signedPrimitiveName = primitive!!.name.drop(1) body { """ - val index = size - val result = java.util.Arrays.copyOf(this, index + 1) - result[index] = element - return result + return SELF(storage + element.to$signedPrimitiveName()) """ } } - on(Platform.JS) { - inline(suppressWarning = true) - specialFor(InvariantArraysOfObjects) { - family = ArraysOfObjects - suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 - returns("Array") + specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) { + on(Platform.JVM) { + body { + """ + val index = size + val result = java.util.Arrays.copyOf(this, index + 1) + result[index] = element + return result + """ + } } - body { - if (primitive == null) - "return this.asDynamic().concat(arrayOf(element))" - else - "return plus(${primitive.name.toLowerCase()}ArrayOf(element))" + on(Platform.JS) { + inline(suppressWarning = true) + specialFor(InvariantArraysOfObjects) { + family = ArraysOfObjects + suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 + returns("Array") + } + + body { + if (primitive == null) + "return this.asDynamic().concat(arrayOf(element))" + else + "return plus(${primitive.name.toLowerCase()}ArrayOf(element))" + } } - } - on(Platform.Native) { - body { - """ - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result - """ + on(Platform.Native) { + body { + """ + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result + """ + } } - } - on(Platform.Common) { - specialFor(InvariantArraysOfObjects) { - suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + on(Platform.Common) { + specialFor(InvariantArraysOfObjects) { + suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + } } } } val f_plus_collection = fn("plus(elements: Collection)") { - include(InvariantArraysOfObjects, ArraysOfPrimitives) + include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { operator() returns("SELF") doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] collection." } - on(Platform.JVM) { + + specialFor(ArraysOfUnsigned) { + val signedPrimitiveName = primitive!!.name.drop(1) body { """ var index = size - val result = java.util.Arrays.copyOf(this, index + elements.size) - for (element in elements) result[index++] = element - return result + val result = storage.copyOf(size + elements.size) + for (element in elements) result[index++] = element.to$signedPrimitiveName() + return SELF(result) """ } } - on(Platform.JS) { - // TODO: inline arrayPlusCollection when @PublishedAPI is available -// inline(Platform.JS, Inline.Yes) -// annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""") - specialFor(InvariantArraysOfObjects) { - family = ArraysOfObjects - suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 - returns("Array") + specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) { + on(Platform.JVM) { + body { + """ + var index = size + val result = java.util.Arrays.copyOf(this, index + elements.size) + for (element in elements) result[index++] = element + return result + """ + } } - when (primitive) { - null, PrimitiveType.Boolean, PrimitiveType.Long -> - body { "return arrayPlusCollection(this, elements)" } - else -> { - on(Backend.Legacy) { - body { - "return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)" + on(Platform.JS) { + // TODO: inline arrayPlusCollection when @PublishedAPI is available +// inline(Platform.JS, Inline.Yes) +// annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""") + specialFor(InvariantArraysOfObjects) { + family = ArraysOfObjects + suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 + returns("Array") + } + when (primitive) { + null, PrimitiveType.Boolean, PrimitiveType.Long -> + body { "return arrayPlusCollection(this, elements)" } + else -> { + on(Backend.Legacy) { + body { + "return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)" + } } - } - on(Backend.IR) { - // Don't use fillFromCollection because it treats arrays - // as `dynamic` but we need to concrete types to perform - // unboxing of collections elements - body { - """ - var index = size - val result = this.copyOf(size + elements.size) - for (element in elements) result[index++] = element - return result - """ + on(Backend.IR) { + // Don't use fillFromCollection because it treats arrays + // as `dynamic` but we need to concrete types to perform + // unboxing of collections elements + body { + """ + var index = size + val result = this.copyOf(size + elements.size) + for (element in elements) result[index++] = element + return result + """ + } } } } } - } - on(Platform.Native) { - body { - """ - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result - """ + on(Platform.Native) { + body { + """ + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result + """ + } } - } - on(Platform.Common) { - specialFor(InvariantArraysOfObjects) { - suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + on(Platform.Common) { + specialFor(InvariantArraysOfObjects) { + suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + } } } } val f_plus_array = fn("plus(elements: SELF)") { - include(InvariantArraysOfObjects, ArraysOfPrimitives) + include(InvariantArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { operator(true) doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] array." } returns("SELF") - specialFor(InvariantArraysOfObjects) { - signature("plus(elements: Array)", notForSorting = true) - } - on(Platform.JVM) { - body { - """ - val thisSize = size - val arraySize = elements.size - val result = java.util.Arrays.copyOf(this, thisSize + arraySize) - System.arraycopy(elements, 0, result, thisSize, arraySize) - return result - """ + specialFor(ArraysOfUnsigned) { + inlineOnly() + body { "return SELF(storage + elements.storage)" } + } + specialFor(InvariantArraysOfObjects, ArraysOfPrimitives) { + specialFor(InvariantArraysOfObjects) { + signature("plus(elements: Array)", notForSorting = true) } - } - on(Platform.JS) { - inline(suppressWarning = true) - specialFor(InvariantArraysOfObjects) { - family = ArraysOfObjects - suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 - returns("Array") - body { """return this.asDynamic().concat(elements)""" } + on(Platform.JVM) { + body { + """ + val thisSize = size + val arraySize = elements.size + val result = java.util.Arrays.copyOf(this, thisSize + arraySize) + System.arraycopy(elements, 0, result, thisSize, arraySize) + return result + """ + } + } - specialFor(ArraysOfPrimitives) { - body { """return primitiveArrayConcat(this, elements)""" } + on(Platform.JS) { + inline(suppressWarning = true) + specialFor(InvariantArraysOfObjects) { + family = ArraysOfObjects + suppress("ACTUAL_WITHOUT_EXPECT") // TODO: KT-21937 + returns("Array") + body { """return this.asDynamic().concat(elements)""" } + } + specialFor(ArraysOfPrimitives) { + body { """return primitiveArrayConcat(this, elements)""" } + } } - } - on(Platform.Native) { - body { - """ - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyInto(result, thisSize) - return result - """ + on(Platform.Native) { + body { + """ + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result + """ + } } - } - on(Platform.Common) { - specialFor(InvariantArraysOfObjects) { - suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + on(Platform.Common) { + specialFor(InvariantArraysOfObjects) { + suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 + } } } }