diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/unitUpperBound.fir.txt b/compiler/fir/analysis-tests/testData/resolve/inference/unitUpperBound.fir.txt index a9ad8499b28..2306ee28e69 100644 --- a/compiler/fir/analysis-tests/testData/resolve/inference/unitUpperBound.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/inference/unitUpperBound.fir.txt @@ -6,7 +6,7 @@ FILE: unitUpperBound.kt public final fun foo(x: R|kotlin/collections/List|): R|kotlin/Unit| { lvar w: R|kotlin/Int| = Int(1) - R|/x|.R|kotlin/collections/ifEmpty||, R|kotlin/Any|>( = ifEmpty@fun (): R|kotlin/Any| { + R|/x|.R|kotlin/collections/ifEmpty||, R|kotlin/Any|>( = ifEmpty@fun (): R|kotlin/Any| { R|/w| = R|/w|.R|kotlin/Int.plus|(Int(2)) } ) diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index c511a4a79c3..73883d72d3e 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -13,6 +13,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed @@ -649,6 +650,9 @@ public expect fun CharArray.elementAt(index: Int): Char */ @kotlin.internal.InlineOnly public inline fun Array.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -659,6 +663,9 @@ public inline fun Array.elementAtOrElse(index: Int, defaultValue: (In */ @kotlin.internal.InlineOnly public inline fun ByteArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Byte): Byte { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -669,6 +676,9 @@ public inline fun ByteArray.elementAtOrElse(index: Int, defaultValue: (Int) -> B */ @kotlin.internal.InlineOnly public inline fun ShortArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Short): Short { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -679,6 +689,9 @@ public inline fun ShortArray.elementAtOrElse(index: Int, defaultValue: (Int) -> */ @kotlin.internal.InlineOnly public inline fun IntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Int): Int { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -689,6 +702,9 @@ public inline fun IntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> In */ @kotlin.internal.InlineOnly public inline fun LongArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Long): Long { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -699,6 +715,9 @@ public inline fun LongArray.elementAtOrElse(index: Int, defaultValue: (Int) -> L */ @kotlin.internal.InlineOnly public inline fun FloatArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Float): Float { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -709,6 +728,9 @@ public inline fun FloatArray.elementAtOrElse(index: Int, defaultValue: (Int) -> */ @kotlin.internal.InlineOnly public inline fun DoubleArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Double): Double { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -719,6 +741,9 @@ public inline fun DoubleArray.elementAtOrElse(index: Int, defaultValue: (Int) -> */ @kotlin.internal.InlineOnly public inline fun BooleanArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Boolean): Boolean { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -729,6 +754,9 @@ public inline fun BooleanArray.elementAtOrElse(index: Int, defaultValue: (Int) - */ @kotlin.internal.InlineOnly public inline fun CharArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1352,6 +1380,9 @@ public inline fun CharArray.firstOrNull(predicate: (Char) -> Boolean): Char? { */ @kotlin.internal.InlineOnly public inline fun Array.getOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1360,6 +1391,9 @@ public inline fun Array.getOrElse(index: Int, defaultValue: (Int) -> */ @kotlin.internal.InlineOnly public inline fun ByteArray.getOrElse(index: Int, defaultValue: (Int) -> Byte): Byte { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1368,6 +1402,9 @@ public inline fun ByteArray.getOrElse(index: Int, defaultValue: (Int) -> Byte): */ @kotlin.internal.InlineOnly public inline fun ShortArray.getOrElse(index: Int, defaultValue: (Int) -> Short): Short { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1376,6 +1413,9 @@ public inline fun ShortArray.getOrElse(index: Int, defaultValue: (Int) -> Short) */ @kotlin.internal.InlineOnly public inline fun IntArray.getOrElse(index: Int, defaultValue: (Int) -> Int): Int { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1384,6 +1424,9 @@ public inline fun IntArray.getOrElse(index: Int, defaultValue: (Int) -> Int): In */ @kotlin.internal.InlineOnly public inline fun LongArray.getOrElse(index: Int, defaultValue: (Int) -> Long): Long { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1392,6 +1435,9 @@ public inline fun LongArray.getOrElse(index: Int, defaultValue: (Int) -> Long): */ @kotlin.internal.InlineOnly public inline fun FloatArray.getOrElse(index: Int, defaultValue: (Int) -> Float): Float { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1400,6 +1446,9 @@ public inline fun FloatArray.getOrElse(index: Int, defaultValue: (Int) -> Float) */ @kotlin.internal.InlineOnly public inline fun DoubleArray.getOrElse(index: Int, defaultValue: (Int) -> Double): Double { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1408,6 +1457,9 @@ public inline fun DoubleArray.getOrElse(index: Int, defaultValue: (Int) -> Doubl */ @kotlin.internal.InlineOnly public inline fun BooleanArray.getOrElse(index: Int, defaultValue: (Int) -> Boolean): Boolean { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -1416,6 +1468,9 @@ public inline fun BooleanArray.getOrElse(index: Int, defaultValue: (Int) -> Bool */ @kotlin.internal.InlineOnly public inline fun CharArray.getOrElse(index: Int, defaultValue: (Int) -> Char): Char { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } diff --git a/libraries/stdlib/common/src/generated/_Collections.kt b/libraries/stdlib/common/src/generated/_Collections.kt index 5b0a9d4c862..2d06d3401ac 100644 --- a/libraries/stdlib/common/src/generated/_Collections.kt +++ b/libraries/stdlib/common/src/generated/_Collections.kt @@ -13,6 +13,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed @@ -103,6 +104,9 @@ public inline fun List.elementAt(index: Int): T { * @sample samples.collections.Collections.Elements.elementAtOrElse */ public fun Iterable.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } if (this is List) return this.getOrElse(index, defaultValue) if (index < 0) @@ -124,6 +128,9 @@ public fun Iterable.elementAtOrElse(index: Int, defaultValue: (Int) -> T) */ @kotlin.internal.InlineOnly public inline fun List.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -294,6 +301,9 @@ public inline fun Iterable.firstOrNull(predicate: (T) -> Boolean): T? { */ @kotlin.internal.InlineOnly public inline fun List.getOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } diff --git a/libraries/stdlib/common/src/generated/_Comparisons.kt b/libraries/stdlib/common/src/generated/_Comparisons.kt index ad7591920a5..3a4786cf392 100644 --- a/libraries/stdlib/common/src/generated/_Comparisons.kt +++ b/libraries/stdlib/common/src/generated/_Comparisons.kt @@ -13,6 +13,7 @@ package kotlin.comparisons // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** diff --git a/libraries/stdlib/common/src/generated/_Maps.kt b/libraries/stdlib/common/src/generated/_Maps.kt index 7f2dbf6dacd..99b8141bed5 100644 --- a/libraries/stdlib/common/src/generated/_Maps.kt +++ b/libraries/stdlib/common/src/generated/_Maps.kt @@ -13,6 +13,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed diff --git a/libraries/stdlib/common/src/generated/_Ranges.kt b/libraries/stdlib/common/src/generated/_Ranges.kt index d9ba54e25e7..39a1e358515 100644 --- a/libraries/stdlib/common/src/generated/_Ranges.kt +++ b/libraries/stdlib/common/src/generated/_Ranges.kt @@ -13,6 +13,7 @@ package kotlin.ranges // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** diff --git a/libraries/stdlib/common/src/generated/_Sequences.kt b/libraries/stdlib/common/src/generated/_Sequences.kt index 80fffc1675a..8ef0ec96714 100644 --- a/libraries/stdlib/common/src/generated/_Sequences.kt +++ b/libraries/stdlib/common/src/generated/_Sequences.kt @@ -13,6 +13,7 @@ package kotlin.sequences // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** @@ -43,6 +44,9 @@ public fun Sequence.elementAt(index: Int): T { * @sample samples.collections.Collections.Elements.elementAtOrElse */ public fun Sequence.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } if (index < 0) return defaultValue(index) val iterator = iterator() diff --git a/libraries/stdlib/common/src/generated/_Sets.kt b/libraries/stdlib/common/src/generated/_Sets.kt index 711e541648e..3dbbd8b8daa 100644 --- a/libraries/stdlib/common/src/generated/_Sets.kt +++ b/libraries/stdlib/common/src/generated/_Sets.kt @@ -13,6 +13,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed diff --git a/libraries/stdlib/common/src/generated/_Strings.kt b/libraries/stdlib/common/src/generated/_Strings.kt index bfbde442f55..18314e30f56 100644 --- a/libraries/stdlib/common/src/generated/_Strings.kt +++ b/libraries/stdlib/common/src/generated/_Strings.kt @@ -13,6 +13,7 @@ package kotlin.text // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** @@ -29,6 +30,9 @@ public expect fun CharSequence.elementAt(index: Int): Char */ @kotlin.internal.InlineOnly public inline fun CharSequence.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -132,6 +136,9 @@ public inline fun CharSequence.firstOrNull(predicate: (Char) -> Boolean): Char? */ @kotlin.internal.InlineOnly public inline fun CharSequence.getOrElse(index: Int, defaultValue: (Int) -> Char): Char { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index 3a927923402..6ceb03956a5 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -14,6 +14,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed @@ -323,6 +324,9 @@ public expect fun UShortArray.elementAt(index: Int): UShort @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UIntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> UInt): UInt { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -335,6 +339,9 @@ public inline fun UIntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> U @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun ULongArray.elementAtOrElse(index: Int, defaultValue: (Int) -> ULong): ULong { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -347,6 +354,9 @@ public inline fun ULongArray.elementAtOrElse(index: Int, defaultValue: (Int) -> @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UByteArray.elementAtOrElse(index: Int, defaultValue: (Int) -> UByte): UByte { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -359,6 +369,9 @@ public inline fun UByteArray.elementAtOrElse(index: Int, defaultValue: (Int) -> @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UShortArray.elementAtOrElse(index: Int, defaultValue: (Int) -> UShort): UShort { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -689,6 +702,9 @@ public inline fun UShortArray.firstOrNull(predicate: (UShort) -> Boolean): UShor @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UIntArray.getOrElse(index: Int, defaultValue: (Int) -> UInt): UInt { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -699,6 +715,9 @@ public inline fun UIntArray.getOrElse(index: Int, defaultValue: (Int) -> UInt): @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun ULongArray.getOrElse(index: Int, defaultValue: (Int) -> ULong): ULong { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -709,6 +728,9 @@ public inline fun ULongArray.getOrElse(index: Int, defaultValue: (Int) -> ULong) @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UByteArray.getOrElse(index: Int, defaultValue: (Int) -> UByte): UByte { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } @@ -719,6 +741,9 @@ public inline fun UByteArray.getOrElse(index: Int, defaultValue: (Int) -> UByte) @ExperimentalUnsignedTypes @kotlin.internal.InlineOnly public inline fun UShortArray.getOrElse(index: Int, defaultValue: (Int) -> UShort): UShort { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } diff --git a/libraries/stdlib/common/src/generated/_UCollections.kt b/libraries/stdlib/common/src/generated/_UCollections.kt index 8942688491d..e2b1155f1b6 100644 --- a/libraries/stdlib/common/src/generated/_UCollections.kt +++ b/libraries/stdlib/common/src/generated/_UCollections.kt @@ -13,6 +13,7 @@ package kotlin.collections // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* import kotlin.ranges.contains import kotlin.ranges.reversed diff --git a/libraries/stdlib/common/src/generated/_UComparisons.kt b/libraries/stdlib/common/src/generated/_UComparisons.kt index 6b109853d75..7484cd6ae75 100644 --- a/libraries/stdlib/common/src/generated/_UComparisons.kt +++ b/libraries/stdlib/common/src/generated/_UComparisons.kt @@ -13,6 +13,7 @@ package kotlin.comparisons // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** diff --git a/libraries/stdlib/common/src/generated/_URanges.kt b/libraries/stdlib/common/src/generated/_URanges.kt index 7927285a591..10cfd11266d 100644 --- a/libraries/stdlib/common/src/generated/_URanges.kt +++ b/libraries/stdlib/common/src/generated/_URanges.kt @@ -13,6 +13,7 @@ package kotlin.ranges // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** diff --git a/libraries/stdlib/common/src/generated/_USequences.kt b/libraries/stdlib/common/src/generated/_USequences.kt index 95a0cb25c8e..b80d3c7bdcd 100644 --- a/libraries/stdlib/common/src/generated/_USequences.kt +++ b/libraries/stdlib/common/src/generated/_USequences.kt @@ -13,6 +13,7 @@ package kotlin.sequences // See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib // +import kotlin.contracts.* import kotlin.random.* /** diff --git a/libraries/stdlib/jdk8/src/kotlin/jvm/optionals/Optionals.kt b/libraries/stdlib/jdk8/src/kotlin/jvm/optionals/Optionals.kt index 3065cbd214e..0a1d228259f 100644 --- a/libraries/stdlib/jdk8/src/kotlin/jvm/optionals/Optionals.kt +++ b/libraries/stdlib/jdk8/src/kotlin/jvm/optionals/Optionals.kt @@ -6,6 +6,7 @@ package kotlin.jvm.optionals import java.util.Optional +import kotlin.contracts.* /** * Returns this [Optional]'s value if [present][Optional.isPresent], or otherwise `null`. @@ -26,8 +27,12 @@ public fun Optional.getOrDefault(defaultValue: T): T = if (isPr */ @SinceKotlin("1.8") @WasExperimental(ExperimentalStdlibApi::class) -public inline fun Optional.getOrElse(defaultValue: () -> T): T = - if (isPresent) get() else defaultValue() +public inline fun Optional.getOrElse(defaultValue: () -> T): T { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isPresent) get() else defaultValue() +} /** * Appends this [Optional]'s value to the given [destination] collection if [present][Optional.isPresent]. diff --git a/libraries/stdlib/src/kotlin/collections/Arrays.kt b/libraries/stdlib/src/kotlin/collections/Arrays.kt index 9a1f0e1eac6..f789c74b42b 100644 --- a/libraries/stdlib/src/kotlin/collections/Arrays.kt +++ b/libraries/stdlib/src/kotlin/collections/Arrays.kt @@ -63,8 +63,12 @@ public inline fun Array<*>?.isNullOrEmpty(): Boolean { @SinceKotlin("1.3") @kotlin.internal.InlineOnly @Suppress("UPPER_BOUND_CANNOT_BE_ARRAY") -public inline fun C.ifEmpty(defaultValue: () -> R): R where C : Array<*>, C : R = - if (isEmpty()) defaultValue() else this +public inline fun C.ifEmpty(defaultValue: () -> R): R where C : Array<*>, C : R { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isEmpty()) defaultValue() else this +} @OptIn(ExperimentalUnsignedTypes::class) diff --git a/libraries/stdlib/src/kotlin/collections/Collections.kt b/libraries/stdlib/src/kotlin/collections/Collections.kt index 86997d36813..23ac3061636 100644 --- a/libraries/stdlib/src/kotlin/collections/Collections.kt +++ b/libraries/stdlib/src/kotlin/collections/Collections.kt @@ -278,8 +278,12 @@ public inline fun List?.orEmpty(): List = this ?: emptyList() */ @SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline fun C.ifEmpty(defaultValue: () -> R): R where C : Collection<*>, C : R = - if (isEmpty()) defaultValue() else this +public inline fun C.ifEmpty(defaultValue: () -> R): R where C : Collection<*>, C : R { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isEmpty()) defaultValue() else this +} /** diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index 721b4045dbf..83fbc13552c 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -235,8 +235,12 @@ public inline fun Map?.orEmpty(): Map = this ?: emptyMap() */ @SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline fun M.ifEmpty(defaultValue: () -> R): R where M : Map<*, *>, M : R = - if (isEmpty()) defaultValue() else this +public inline fun M.ifEmpty(defaultValue: () -> R): R where M : Map<*, *>, M : R { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isEmpty()) defaultValue() else this +} /** * Checks if the map contains the given key. @@ -334,7 +338,12 @@ public inline fun Map.Entry.toPair(): Pair = Pair(key, value) * @sample samples.collections.Maps.Usage.getOrElse */ @kotlin.internal.InlineOnly -public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue() +public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return get(key) ?: defaultValue() +} internal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V { diff --git a/libraries/stdlib/src/kotlin/text/Strings.kt b/libraries/stdlib/src/kotlin/text/Strings.kt index 11c5f2c50ea..87cc1bf3188 100644 --- a/libraries/stdlib/src/kotlin/text/Strings.kt +++ b/libraries/stdlib/src/kotlin/text/Strings.kt @@ -8,6 +8,7 @@ package kotlin.text +import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.jvm.JvmName @@ -355,8 +356,12 @@ public inline fun String?.orEmpty(): String = this ?: "" */ @SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline fun C.ifEmpty(defaultValue: () -> R): R where C : CharSequence, C : R = - if (isEmpty()) defaultValue() else this +public inline fun C.ifEmpty(defaultValue: () -> R): R where C : CharSequence, C : R { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isEmpty()) defaultValue() else this +} /** * Returns this char sequence if it is not empty and doesn't consist solely of whitespace characters, @@ -366,8 +371,12 @@ public inline fun C.ifEmpty(defaultValue: () -> R): R where C : CharSeque */ @SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline fun C.ifBlank(defaultValue: () -> R): R where C : CharSequence, C : R = - if (isBlank()) defaultValue() else this +public inline fun C.ifBlank(defaultValue: () -> R): R where C : CharSequence, C : R { + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } + return if (isBlank()) defaultValue() else this +} /** * Returns the range of valid character indices for this char sequence. diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index 00d2ada9a77..917be8dacd8 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -342,6 +342,9 @@ object Elements : TemplateGroupBase() { returns("T") body { """ + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } if (this is List) return this.getOrElse(index, defaultValue) if (index < 0) @@ -358,6 +361,9 @@ object Elements : TemplateGroupBase() { } body(Sequences) { """ + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } if (index < 0) return defaultValue(index) val iterator = iterator() @@ -374,6 +380,9 @@ object Elements : TemplateGroupBase() { inlineOnly() body { """ + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) """ } @@ -388,6 +397,9 @@ object Elements : TemplateGroupBase() { inlineOnly() body { """ + contract { + callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE) + } return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) """ } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/Writers.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/Writers.kt index 9c137f747f0..af266af8a3e 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/Writers.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/Writers.kt @@ -105,6 +105,7 @@ fun List.writeTo(file: File, targetedSource: TargetedSourceFile) } } if (target.platform == Platform.Common) { + writer.appendLine("import kotlin.contracts.*") writer.appendLine("import kotlin.random.*") } if (sourceFile.packageName == "kotlin.collections") {