From ccf3ae59cd43013e03e812025954155867fec842 Mon Sep 17 00:00:00 2001 From: Andrey Tabakov Date: Sat, 18 Oct 2025 14:20:25 +0300 Subject: [PATCH 1/5] Stdlib: add findIs method --- .../stdlib/common/src/generated/_Arrays.kt | 10 ++++++++++ .../common/src/generated/_Collections.kt | 10 ++++++++++ .../stdlib/common/src/generated/_Sequences.kt | 12 +++++++++++ .../test/samples/collections/collections.kt | 16 +++++++++++++++ .../src/templates/Elements.kt | 20 +++++++++++++++++++ 5 files changed, 68 insertions(+) diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index dcc7a33f51adf..a38dc1cd14512 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -1031,6 +1031,16 @@ public inline fun CharArray.find(predicate: (Char) -> Boolean): Char? { return firstOrNull(predicate) } +/** + * Returns the first transformed element matching specified type parameter R, or `null` if no such element was found. + * + * @sample samples.collections.Collections.Elements.findIs + */ +@kotlin.internal.InlineOnly +public inline fun Array<*>.findIs(): R? { + return find { element -> element is R } as R? +} + /** * Returns the last element matching the given [predicate], or `null` if no such element was found. * diff --git a/libraries/stdlib/common/src/generated/_Collections.kt b/libraries/stdlib/common/src/generated/_Collections.kt index 28b734cbd57f1..229ee9dc4f173 100644 --- a/libraries/stdlib/common/src/generated/_Collections.kt +++ b/libraries/stdlib/common/src/generated/_Collections.kt @@ -175,6 +175,16 @@ public inline fun Iterable.find(predicate: (T) -> Boolean): T? { return firstOrNull(predicate) } +/** + * Returns the first transformed element matching specified type parameter R, or `null` if no such element was found. + * + * @sample samples.collections.Collections.Elements.findIs + */ +@kotlin.internal.InlineOnly +public inline fun Iterable<*>.findIs(): R? { + return find { element -> element is R } as R? +} + /** * Returns the last element matching the given [predicate], or `null` if no such element was found. * diff --git a/libraries/stdlib/common/src/generated/_Sequences.kt b/libraries/stdlib/common/src/generated/_Sequences.kt index e54ba3b09c412..dd8f6f35ffca9 100644 --- a/libraries/stdlib/common/src/generated/_Sequences.kt +++ b/libraries/stdlib/common/src/generated/_Sequences.kt @@ -92,6 +92,18 @@ public inline fun Sequence.find(predicate: (T) -> Boolean): T? { return firstOrNull(predicate) } +/** + * Returns the first transformed element matching specified type parameter R, or `null` if no such element was found. + * + * The operation is _terminal_. + * + * @sample samples.collections.Collections.Elements.findIs + */ +@kotlin.internal.InlineOnly +public inline fun Sequence<*>.findIs(): R? { + return find { element -> element is R } as R? +} + /** * Returns the last element matching the given [predicate], or `null` if no such element was found. * diff --git a/libraries/stdlib/samples/test/samples/collections/collections.kt b/libraries/stdlib/samples/test/samples/collections/collections.kt index 05b2f823d1ab0..623b26b1e7a4c 100644 --- a/libraries/stdlib/samples/test/samples/collections/collections.kt +++ b/libraries/stdlib/samples/test/samples/collections/collections.kt @@ -1233,6 +1233,22 @@ class Collections { assertPrints(lastEven, "6") } + @Sample + fun findIs() { + val objects = listOf("one", 1, true, null) + val string = objects.findIs() + val boolean = objects.findIs() + val number = objects.findIs() + val int = objects.findIs() + val long = objects.findIs() + + assertPrints(string, "one") + assertEquals(number, 1) + assertEquals(int, 1) + assertTrue { boolean == true } + assertNull(long) + } + @Sample fun getOrElse() { val list = listOf(1, 2, 3) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index 4781a0ff26259..4534b319c72a8 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -631,6 +631,26 @@ object Elements : TemplateGroupBase() { body { "return firstOrNull(predicate)"} } + val f_findIs = fn("findIs()") { + include(Iterables, Sequences, ArraysOfObjects) + } builder { + inlineOnly() + genericStarProjection = true + typeParam("reified R") + returns("R?") + + sample("samples.collections.Collections.Elements.findIs") + + doc { + "Returns the first transformed ${f.element} matching specified type parameter R, or `null` if no such ${f.element} was found." + } + body { + """ + return find { element -> element is R } as R? + """ + } + } + private val Family.sampleClass: String get() = when (this) { Strings, CharSequences -> "samples.text.Strings" From 5b8265dc2d62d4aaf1c06cb795b87f500af52ea7 Mon Sep 17 00:00:00 2001 From: Andrey Tabakov Date: Sat, 18 Oct 2025 14:38:40 +0300 Subject: [PATCH 2/5] Stdlib: add firstIs method --- .../stdlib/common/src/generated/_Arrays.kt | 10 +++++++++ .../common/src/generated/_Collections.kt | 10 +++++++++ .../stdlib/common/src/generated/_Sequences.kt | 12 +++++++++++ .../test/samples/collections/collections.kt | 21 +++++++++++++++++++ .../src/templates/Elements.kt | 19 +++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index a38dc1cd14512..f8099287824f1 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -1311,6 +1311,16 @@ public inline fun CharArray.first(predicate: (Char) -> Boolean): Char { throw NoSuchElementException("Array contains no element matching the predicate.") } +/** + * Returns the first element matching the specified type R. + * @throws [NoSuchElementException] if no such element of specified type R is found. + */ +@kotlin.internal.InlineOnly +public inline fun Array<*>.firstIs(): R? { + for (element in this) if (element is R) return element + throw NoSuchElementException("Array contains no element matching the specified type ${R::class.simpleName}.") +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this array in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/common/src/generated/_Collections.kt b/libraries/stdlib/common/src/generated/_Collections.kt index 229ee9dc4f173..1238b340339a3 100644 --- a/libraries/stdlib/common/src/generated/_Collections.kt +++ b/libraries/stdlib/common/src/generated/_Collections.kt @@ -242,6 +242,16 @@ public inline fun Iterable.first(predicate: (T) -> Boolean): T { throw NoSuchElementException("Collection contains no element matching the predicate.") } +/** + * Returns the first element matching the specified type R. + * @throws [NoSuchElementException] if no such element of specified type R is found. + */ +@kotlin.internal.InlineOnly +public inline fun Iterable<*>.firstIs(): R? { + for (element in this) if (element is R) return element + throw NoSuchElementException("Collection contains no element matching the specified type ${R::class.simpleName}.") +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this collection in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/common/src/generated/_Sequences.kt b/libraries/stdlib/common/src/generated/_Sequences.kt index dd8f6f35ffca9..f45bfbc992f1c 100644 --- a/libraries/stdlib/common/src/generated/_Sequences.kt +++ b/libraries/stdlib/common/src/generated/_Sequences.kt @@ -141,6 +141,18 @@ public inline fun Sequence.first(predicate: (T) -> Boolean): T { throw NoSuchElementException("Sequence contains no element matching the predicate.") } +/** + * Returns the first element matching the specified type R. + * @throws [NoSuchElementException] if no such element of specified type R is found. + * + * The operation is _terminal_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence<*>.firstIs(): R? { + for (element in this) if (element is R) return element + throw NoSuchElementException("Sequence contains no element matching the specified type ${R::class.simpleName}.") +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this sequence in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/samples/test/samples/collections/collections.kt b/libraries/stdlib/samples/test/samples/collections/collections.kt index 623b26b1e7a4c..9a49678b961de 100644 --- a/libraries/stdlib/samples/test/samples/collections/collections.kt +++ b/libraries/stdlib/samples/test/samples/collections/collections.kt @@ -1249,6 +1249,27 @@ class Collections { assertNull(long) } + @Sample + fun firstIs() { + val objects = listOf("one", 1, true, null) + val string = objects.firstIs() + val boolean = objects.firstIs() + val number = objects.firstIs() + val int = objects.firstIs() + + assertPrints(string, "one") + assertEquals(number, 1) + assertEquals(int, 1) + assertTrue { boolean == true } + + val exception = assertFails { + objects.firstIs() + } + + assertIs(exception) + assertEquals("Collection contains no element matching the specified type Long.", exception.message) + } + @Sample fun getOrElse() { val list = listOf(1, 2, 3) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index 4534b319c72a8..dff7133c5499c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -620,6 +620,25 @@ object Elements : TemplateGroupBase() { } } + val f_firstIs = fn("firstIs()") { + include(Iterables, Sequences, ArraysOfObjects) + } builder { + inlineOnly() + genericStarProjection = true + typeParam("reified R") + returns("R?") + + doc { """Returns the first ${f.element} matching the specified type R. + @throws [NoSuchElementException] if no such ${f.element} of specified type R is found.""" } + + body { + """ + for (element in this) if (element is R) return element + throw NoSuchElementException("${f.doc.collection.capitalize()} contains no ${f.doc.element} matching the specified type ${"$"}{R::class.simpleName}.") + """ + } + } + val f_find = fn("find(predicate: (T) -> Boolean)") { includeDefault() include(CharSequences, ArraysOfUnsigned) From 9d5186836ee51f50e75ac53cdec2aca8493b41b5 Mon Sep 17 00:00:00 2001 From: Andrey Tabakov Date: Mon, 20 Oct 2025 18:55:33 +0300 Subject: [PATCH 3/5] Stdlib: add klib api --- .../klib-public-api/kotlin-stdlib.api | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api index 036b12c19108d..4080d6f280755 100644 --- a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api +++ b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api @@ -13860,6 +13860,24 @@ final inline fun <#A: kotlin/Any?> (kotlin.collections/Collection<#A>).kotlin.co // Targets: [js, wasmJs, wasmWasi] final inline fun <#A: kotlin/Any?> kotlin/emptyArray(): kotlin/Array<#A> // kotlin/emptyArray|emptyArray(){0§}[0] +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.collections.Iterable<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIs(): #A? // kotlin.collections/firstIs|firstIs@kotlin.collections.Iterable<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/findIs(): #A? // kotlin.sequences/findIs|findIs@kotlin.sequences.Sequence<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIs(): #A? // kotlin.sequences/firstIs|firstIs@kotlin.sequences.Sequence<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.Array<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIs(): #A? // kotlin.collections/firstIs|firstIs@kotlin.Array<*>(){0§}[0] + // Targets: [js, wasmJs] open annotation class kotlin.js/ExperimentalWasmJsInterop : kotlin/Annotation { // kotlin.js/ExperimentalWasmJsInterop|null[0] constructor () // kotlin.js/ExperimentalWasmJsInterop.|(){}[0] From 99d14e80e31471e3066d080aa4b406dd21ead646 Mon Sep 17 00:00:00 2001 From: Andrey Tabakov Date: Tue, 4 Nov 2025 13:54:17 +0300 Subject: [PATCH 4/5] Stdlib: add firstIsOrNull method and fix firstIs return type --- .../stdlib/common/src/generated/_Arrays.kt | 13 +++++++++-- .../common/src/generated/_Collections.kt | 13 +++++++++-- .../stdlib/common/src/generated/_Sequences.kt | 15 +++++++++++-- .../test/samples/collections/collections.kt | 2 +- .../klib-public-api/kotlin-stdlib.api | 15 ++++++++++--- .../src/templates/Elements.kt | 22 +++++++++++++++++-- 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index f8099287824f1..92889cb322b08 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -1038,7 +1038,7 @@ public inline fun CharArray.find(predicate: (Char) -> Boolean): Char? { */ @kotlin.internal.InlineOnly public inline fun Array<*>.findIs(): R? { - return find { element -> element is R } as R? + return firstIsOrNull() } /** @@ -1316,11 +1316,20 @@ public inline fun CharArray.first(predicate: (Char) -> Boolean): Char { * @throws [NoSuchElementException] if no such element of specified type R is found. */ @kotlin.internal.InlineOnly -public inline fun Array<*>.firstIs(): R? { +public inline fun Array<*>.firstIs(): R { for (element in this) if (element is R) return element throw NoSuchElementException("Array contains no element matching the specified type ${R::class.simpleName}.") } +/** + * Returns the first transformed ${f.element} matching specified type parameter R, or `null` if no such ${f.element} was found. + */ +@kotlin.internal.InlineOnly +public inline fun Array<*>.firstIsOrNull(): R? { + for (element in this) if (element is R) return element + return null +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this array in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/common/src/generated/_Collections.kt b/libraries/stdlib/common/src/generated/_Collections.kt index 1238b340339a3..b6c03dbe139ff 100644 --- a/libraries/stdlib/common/src/generated/_Collections.kt +++ b/libraries/stdlib/common/src/generated/_Collections.kt @@ -182,7 +182,7 @@ public inline fun Iterable.find(predicate: (T) -> Boolean): T? { */ @kotlin.internal.InlineOnly public inline fun Iterable<*>.findIs(): R? { - return find { element -> element is R } as R? + return firstIsOrNull() } /** @@ -247,11 +247,20 @@ public inline fun Iterable.first(predicate: (T) -> Boolean): T { * @throws [NoSuchElementException] if no such element of specified type R is found. */ @kotlin.internal.InlineOnly -public inline fun Iterable<*>.firstIs(): R? { +public inline fun Iterable<*>.firstIs(): R { for (element in this) if (element is R) return element throw NoSuchElementException("Collection contains no element matching the specified type ${R::class.simpleName}.") } +/** + * Returns the first transformed ${f.element} matching specified type parameter R, or `null` if no such ${f.element} was found. + */ +@kotlin.internal.InlineOnly +public inline fun Iterable<*>.firstIsOrNull(): R? { + for (element in this) if (element is R) return element + return null +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this collection in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/common/src/generated/_Sequences.kt b/libraries/stdlib/common/src/generated/_Sequences.kt index f45bfbc992f1c..d0b4a92716c3a 100644 --- a/libraries/stdlib/common/src/generated/_Sequences.kt +++ b/libraries/stdlib/common/src/generated/_Sequences.kt @@ -101,7 +101,7 @@ public inline fun Sequence.find(predicate: (T) -> Boolean): T? { */ @kotlin.internal.InlineOnly public inline fun Sequence<*>.findIs(): R? { - return find { element -> element is R } as R? + return firstIsOrNull() } /** @@ -148,11 +148,22 @@ public inline fun Sequence.first(predicate: (T) -> Boolean): T { * The operation is _terminal_. */ @kotlin.internal.InlineOnly -public inline fun Sequence<*>.firstIs(): R? { +public inline fun Sequence<*>.firstIs(): R { for (element in this) if (element is R) return element throw NoSuchElementException("Sequence contains no element matching the specified type ${R::class.simpleName}.") } +/** + * Returns the first transformed ${f.element} matching specified type parameter R, or `null` if no such ${f.element} was found. + * + * The operation is _terminal_. + */ +@kotlin.internal.InlineOnly +public inline fun Sequence<*>.firstIsOrNull(): R? { + for (element in this) if (element is R) return element + return null +} + /** * Returns the first non-null value produced by [transform] function being applied to elements of this sequence in iteration order, * or throws [NoSuchElementException] if no non-null value was produced. diff --git a/libraries/stdlib/samples/test/samples/collections/collections.kt b/libraries/stdlib/samples/test/samples/collections/collections.kt index 9a49678b961de..098151171e97b 100644 --- a/libraries/stdlib/samples/test/samples/collections/collections.kt +++ b/libraries/stdlib/samples/test/samples/collections/collections.kt @@ -1260,7 +1260,7 @@ class Collections { assertPrints(string, "one") assertEquals(number, 1) assertEquals(int, 1) - assertTrue { boolean == true } + assertTrue { boolean } val exception = assertFails { objects.firstIs() diff --git a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api index 4080d6f280755..e042c3288d058 100644 --- a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api +++ b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api @@ -13864,19 +13864,28 @@ final inline fun <#A: kotlin/Any?> kotlin/emptyArray(): kotlin/Array<#A> // kotl final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.collections.Iterable<*>(){0§}[0] // Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIs(): #A? // kotlin.collections/firstIs|firstIs@kotlin.collections.Iterable<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.collections.Iterable<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.collections.Iterable<*>(){0§}[0] // Targets: [js, wasmJs, wasmWasi] final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/findIs(): #A? // kotlin.sequences/findIs|findIs@kotlin.sequences.Sequence<*>(){0§}[0] // Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIs(): #A? // kotlin.sequences/firstIs|firstIs@kotlin.sequences.Sequence<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIs(): #A // kotlin.sequences/firstIs|firstIs@kotlin.sequences.Sequence<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIsOrNull(): #A? // kotlin.sequences/firstIsOrNull|firstIsOrNull@kotlin.sequences.Sequence<*>(){0§}[0] // Targets: [js, wasmJs, wasmWasi] final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.Array<*>(){0§}[0] // Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIs(): #A? // kotlin.collections/firstIs|firstIs@kotlin.Array<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.Array<*>(){0§}[0] + +// Targets: [js, wasmJs, wasmWasi] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.Array<*>(){0§}[0] // Targets: [js, wasmJs] open annotation class kotlin.js/ExperimentalWasmJsInterop : kotlin/Annotation { // kotlin.js/ExperimentalWasmJsInterop|null[0] diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index dff7133c5499c..9ad04e4ab0c11 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -620,7 +620,7 @@ object Elements : TemplateGroupBase() { } } - val f_firstIs = fn("firstIs()") { + val f_firstIsOrNull = fn("firstIsOrNull()") { include(Iterables, Sequences, ArraysOfObjects) } builder { inlineOnly() @@ -628,6 +628,24 @@ object Elements : TemplateGroupBase() { typeParam("reified R") returns("R?") + doc { """Returns the first transformed ${'$'}{f.element} matching specified type parameter R, or `null` if no such ${'$'}{f.element} was found.""" } + + body { + """ + for (element in this) if (element is R) return element + return null + """ + } + } + + val f_firstIs = fn("firstIs()") { + include(Iterables, Sequences, ArraysOfObjects) + } builder { + inlineOnly() + genericStarProjection = true + typeParam("reified R") + returns("R") + doc { """Returns the first ${f.element} matching the specified type R. @throws [NoSuchElementException] if no such ${f.element} of specified type R is found.""" } @@ -665,7 +683,7 @@ object Elements : TemplateGroupBase() { } body { """ - return find { element -> element is R } as R? + return firstIsOrNull() """ } } From a65ce503b0de6166d00d499d4e13b844ba3f410c Mon Sep 17 00:00:00 2001 From: Andrey Tabakov Date: Tue, 4 Nov 2025 18:47:25 +0300 Subject: [PATCH 5/5] Stdlib: add api --- .../klib-public-api/kotlin-stdlib.api | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api index e042c3288d058..d885503559efd 100644 --- a/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api +++ b/libraries/tools/binary-compatibility-validator/klib-public-api/kotlin-stdlib.api @@ -8963,8 +8963,17 @@ final inline fun <#A: reified kotlin/Any?, #B: kotlin.collections/MutableCollect final inline fun <#A: reified kotlin/Any?, #B: kotlin.collections/MutableCollection> (kotlin.sequences/Sequence<*>).kotlin.sequences/filterIsInstanceTo(#B): #B // kotlin.sequences/filterIsInstanceTo|filterIsInstanceTo@kotlin.sequences.Sequence<*>(0:1){0§;1§>}[0] final inline fun <#A: reified kotlin/Any?, #B: kotlin.collections/MutableCollection> (kotlin/Array<*>).kotlin.collections/filterIsInstanceTo(#B): #B // kotlin.collections/filterIsInstanceTo|filterIsInstanceTo@kotlin.Array<*>(0:1){0§;1§>}[0] final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/filterIsInstance(): kotlin.collections/List<#A> // kotlin.collections/filterIsInstance|filterIsInstance@kotlin.collections.Iterable<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.collections.Iterable<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.collections.Iterable<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.collections.Iterable<*>(){0§}[0] final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/filterIsInstance(): kotlin.sequences/Sequence<#A> // kotlin.sequences/filterIsInstance|filterIsInstance@kotlin.sequences.Sequence<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/findIs(): #A? // kotlin.sequences/findIs|findIs@kotlin.sequences.Sequence<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIs(): #A // kotlin.sequences/firstIs|firstIs@kotlin.sequences.Sequence<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIsOrNull(): #A? // kotlin.sequences/firstIsOrNull|firstIsOrNull@kotlin.sequences.Sequence<*>(){0§}[0] final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/filterIsInstance(): kotlin.collections/List<#A> // kotlin.collections/filterIsInstance|filterIsInstance@kotlin.Array<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.Array<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.Array<*>(){0§}[0] +final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.Array<*>(){0§}[0] final inline fun <#A: reified kotlin/Any?> kotlin.concurrent.atomics/AtomicArray(kotlin/Int, kotlin/Function1): kotlin.concurrent.atomics/AtomicArray<#A> // kotlin.concurrent.atomics/AtomicArray|AtomicArray(kotlin.Int;kotlin.Function1){0§}[0] final inline fun <#A: reified kotlin/Any?> kotlin.concurrent.atomics/atomicArrayOfNulls(kotlin/Int): kotlin.concurrent.atomics/AtomicArray<#A?> // kotlin.concurrent.atomics/atomicArrayOfNulls|atomicArrayOfNulls(kotlin.Int){0§}[0] final inline fun <#A: reified kotlin/Any?> kotlin.reflect/typeOf(): kotlin.reflect/KType // kotlin.reflect/typeOf|typeOf(){0§}[0] @@ -13860,33 +13869,6 @@ final inline fun <#A: kotlin/Any?> (kotlin.collections/Collection<#A>).kotlin.co // Targets: [js, wasmJs, wasmWasi] final inline fun <#A: kotlin/Any?> kotlin/emptyArray(): kotlin/Array<#A> // kotlin/emptyArray|emptyArray(){0§}[0] -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.collections.Iterable<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.collections.Iterable<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.collections/Iterable<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.collections.Iterable<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/findIs(): #A? // kotlin.sequences/findIs|findIs@kotlin.sequences.Sequence<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIs(): #A // kotlin.sequences/firstIs|firstIs@kotlin.sequences.Sequence<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin.sequences/Sequence<*>).kotlin.sequences/firstIsOrNull(): #A? // kotlin.sequences/firstIsOrNull|firstIsOrNull@kotlin.sequences.Sequence<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/findIs(): #A? // kotlin.collections/findIs|findIs@kotlin.Array<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIs(): #A // kotlin.collections/firstIs|firstIs@kotlin.Array<*>(){0§}[0] - -// Targets: [js, wasmJs, wasmWasi] -final inline fun <#A: reified kotlin/Any?> (kotlin/Array<*>).kotlin.collections/firstIsOrNull(): #A? // kotlin.collections/firstIsOrNull|firstIsOrNull@kotlin.Array<*>(){0§}[0] - // Targets: [js, wasmJs] open annotation class kotlin.js/ExperimentalWasmJsInterop : kotlin/Annotation { // kotlin.js/ExperimentalWasmJsInterop|null[0] constructor () // kotlin.js/ExperimentalWasmJsInterop.|(){}[0]