diff --git a/generators/builtins/ranges.kt b/generators/builtins/ranges.kt index 197fddd8458..4e9f04564e8 100644 --- a/generators/builtins/ranges.kt +++ b/generators/builtins/ranges.kt @@ -52,9 +52,18 @@ class GenerateRanges(out: PrintWriter) : BuiltInsSourceGenerator(out) { """/** * A range of values of type `$t`. */ -public class $range(start: $t, endInclusive: $t) : ${t}Progression(start, endInclusive, $increment), ClosedRange<$t> { +@OptIn(ExperimentalStdlibApi::class) +public class $range(start: $t, endInclusive: $t) : ${t}Progression(start, endInclusive, $increment), ClosedRange<$t>, OpenEndRange<$t> { override val start: $t get() = first override val endInclusive: $t get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with $t type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: $t get() { + if (last == $t.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1 + } override fun contains(value: $t): Boolean = first <= value && value <= last diff --git a/generators/builtins/unsignedTypes.kt b/generators/builtins/unsignedTypes.kt index 233b10a58f1..34e313c52ff 100644 --- a/generators/builtins/unsignedTypes.kt +++ b/generators/builtins/unsignedTypes.kt @@ -555,9 +555,18 @@ import kotlin.internal.* */ @SinceKotlin("1.5") @WasExperimental(ExperimentalUnsignedTypes::class) -public class ${elementType}Range(start: $elementType, endInclusive: $elementType) : ${elementType}Progression(start, endInclusive, 1), ClosedRange<${elementType}> { +@OptIn(ExperimentalStdlibApi::class) +public class ${elementType}Range(start: $elementType, endInclusive: $elementType) : ${elementType}Progression(start, endInclusive, 1), ClosedRange<${elementType}>, OpenEndRange<${elementType}> { override val start: $elementType get() = first override val endInclusive: $elementType get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with $elementType type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: $elementType get() { + if (last == $elementType.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1u + } override fun contains(value: $elementType): Boolean = first <= value && value <= last diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index f352c96ac69..2de787f9f6b 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -313,6 +313,7 @@ konanArtifacts { "-opt-in=kotlin.contracts.ExperimentalContracts", "-opt-in=kotlin.ExperimentalMultiplatform", "-opt-in=kotlin.native.internal.InternalForKotlinNative", + "-XXLanguage:+RangeUntilOperator", ) commonStdlibSrcDirs.forEach { commonSrcDir(it) } diff --git a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt index 25fe6a313a9..ee975f75c3e 100644 --- a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt +++ b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt @@ -280,6 +280,8 @@ fun > assertContains(range: ClosedRange, value: T, message: assertRangeContains(range, value, message, ClosedRange::contains) } +// TODO: assertContains for OpenEndRange + /** Asserts that the [range] contains the specified [value], with an optional [message]. */ @SinceKotlin("1.5") fun assertContains(range: CharRange, value: Char, message: String? = null) { diff --git a/libraries/stdlib/common/build.gradle b/libraries/stdlib/common/build.gradle index d70a6c53009..2788527f799 100644 --- a/libraries/stdlib/common/build.gradle +++ b/libraries/stdlib/common/build.gradle @@ -47,6 +47,7 @@ compileKotlinCommon { "-opt-in=kotlin.ExperimentalMultiplatform", "-opt-in=kotlin.contracts.ExperimentalContracts", "-Xallow-kotlin-package", + "-XXLanguage:+RangeUntilOperator", ] } } @@ -57,6 +58,7 @@ compileTestKotlinCommon { "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalUnsignedTypes", "-opt-in=kotlin.ExperimentalStdlibApi", + "-XXLanguage:+RangeUntilOperator", ] } } diff --git a/libraries/stdlib/common/src/generated/_Ranges.kt b/libraries/stdlib/common/src/generated/_Ranges.kt index b1f2baaab8f..78e6c054bcc 100644 --- a/libraries/stdlib/common/src/generated/_Ranges.kt +++ b/libraries/stdlib/common/src/generated/_Ranges.kt @@ -458,6 +458,8 @@ public operator fun ClosedRange.contains(value: Float): Boolean { return contains(value.toDouble()) } +// TODO: for OpenEndRange + /** * Checks if the specified [value] belongs to this range. */ diff --git a/libraries/stdlib/jdk7/build.gradle b/libraries/stdlib/jdk7/build.gradle index ffcce3c6e83..e7ada5854ab 100644 --- a/libraries/stdlib/jdk7/build.gradle +++ b/libraries/stdlib/jdk7/build.gradle @@ -78,6 +78,7 @@ compileTestKotlin { "-opt-in=kotlin.io.path.ExperimentalPathApi", "-Xcommon-sources=${fileTree('../test').join(',')}", "-Xsuppress-deprecated-jvm-target-warning", + "-XXLanguage:+RangeUntilOperator", ] } diff --git a/libraries/stdlib/jdk8/build.gradle b/libraries/stdlib/jdk8/build.gradle index 446653d706e..053d558093d 100644 --- a/libraries/stdlib/jdk8/build.gradle +++ b/libraries/stdlib/jdk8/build.gradle @@ -77,6 +77,7 @@ compileTestKotlin { "-opt-in=kotlin.ExperimentalStdlibApi", "-opt-in=kotlin.io.path.ExperimentalPathApi", "-Xcommon-sources=${fileTree('../test').join(',')}", + "-XXLanguage:+RangeUntilOperator", ] } diff --git a/libraries/stdlib/js-ir-minimal-for-test/build.gradle.kts b/libraries/stdlib/js-ir-minimal-for-test/build.gradle.kts index 74f018ba8be..d972a783301 100644 --- a/libraries/stdlib/js-ir-minimal-for-test/build.gradle.kts +++ b/libraries/stdlib/js-ir-minimal-for-test/build.gradle.kts @@ -137,7 +137,8 @@ tasks.withType> { "-opt-in=kotlin.contracts.ExperimentalContracts", "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalUnsignedTypes", - "-opt-in=kotlin.ExperimentalStdlibApi" + "-opt-in=kotlin.ExperimentalStdlibApi", + "-XXLanguage:+RangeUntilOperator", ) } diff --git a/libraries/stdlib/js-ir/build.gradle.kts b/libraries/stdlib/js-ir/build.gradle.kts index f7df4ee0e36..87cf8995d69 100644 --- a/libraries/stdlib/js-ir/build.gradle.kts +++ b/libraries/stdlib/js-ir/build.gradle.kts @@ -141,7 +141,8 @@ tasks.withType>().configureEach { "-opt-in=kotlin.contracts.ExperimentalContracts", "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalUnsignedTypes", - "-opt-in=kotlin.ExperimentalStdlibApi" + "-opt-in=kotlin.ExperimentalStdlibApi", + "-XXLanguage:+RangeUntilOperator", ) } diff --git a/libraries/stdlib/js-v1/build.gradle b/libraries/stdlib/js-v1/build.gradle index ca4560a3391..48667d361f7 100644 --- a/libraries/stdlib/js-v1/build.gradle +++ b/libraries/stdlib/js-v1/build.gradle @@ -134,6 +134,7 @@ compileKotlin2Js { "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalMultiplatform", "-opt-in=kotlin.contracts.ExperimentalContracts", + "-XXLanguage:+RangeUntilOperator", ] } } @@ -145,6 +146,7 @@ compileTestKotlin2Js { "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalUnsignedTypes", "-opt-in=kotlin.ExperimentalStdlibApi", + "-XXLanguage:+RangeUntilOperator", ] } } diff --git a/libraries/stdlib/jvm/build.gradle b/libraries/stdlib/jvm/build.gradle index ad951330b7e..037d0c1ac82 100644 --- a/libraries/stdlib/jvm/build.gradle +++ b/libraries/stdlib/jvm/build.gradle @@ -115,6 +115,7 @@ compileKotlin { "-Xuse-14-inline-classes-mangling-scheme", "-Xsuppress-deprecated-jvm-target-warning", "-Xbuiltins-from-sources", + "-XXLanguage:+RangeUntilOperator", ] moduleName = "kotlin-stdlib" } @@ -127,6 +128,7 @@ compileTestKotlin { "-opt-in=kotlin.ExperimentalUnsignedTypes", "-opt-in=kotlin.ExperimentalStdlibApi", "-Xsuppress-deprecated-jvm-target-warning", + "-XXLanguage:+RangeUntilOperator", ] // This is needed for JavaTypeTest; typeOf for non-reified type parameters doesn't work otherwise, for implementation reasons. freeCompilerArgs.remove("-Xno-optimized-callable-references") diff --git a/libraries/stdlib/src/kotlin/ranges/PrimitiveRanges.kt b/libraries/stdlib/src/kotlin/ranges/PrimitiveRanges.kt index 8823534a14b..3f01dce480d 100644 --- a/libraries/stdlib/src/kotlin/ranges/PrimitiveRanges.kt +++ b/libraries/stdlib/src/kotlin/ranges/PrimitiveRanges.kt @@ -10,9 +10,18 @@ package kotlin.ranges /** * A range of values of type `Char`. */ -public class CharRange(start: Char, endInclusive: Char) : CharProgression(start, endInclusive, 1), ClosedRange { +@OptIn(ExperimentalStdlibApi::class) +public class CharRange(start: Char, endInclusive: Char) : CharProgression(start, endInclusive, 1), ClosedRange, OpenEndRange { override val start: Char get() = first override val endInclusive: Char get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with Char type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: Char get() { + if (last == Char.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1 + } override fun contains(value: Char): Boolean = first <= value && value <= last @@ -41,9 +50,18 @@ public class CharRange(start: Char, endInclusive: Char) : CharProgression(start, /** * A range of values of type `Int`. */ -public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange { +@OptIn(ExperimentalStdlibApi::class) +public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange, OpenEndRange { override val start: Int get() = first override val endInclusive: Int get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with Int type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: Int get() { + if (last == Int.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1 + } override fun contains(value: Int): Boolean = first <= value && value <= last @@ -72,9 +90,18 @@ public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, end /** * A range of values of type `Long`. */ -public class LongRange(start: Long, endInclusive: Long) : LongProgression(start, endInclusive, 1), ClosedRange { +@OptIn(ExperimentalStdlibApi::class) +public class LongRange(start: Long, endInclusive: Long) : LongProgression(start, endInclusive, 1), ClosedRange, OpenEndRange { override val start: Long get() = first override val endInclusive: Long get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with Long type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: Long get() { + if (last == Long.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1 + } override fun contains(value: Long): Boolean = first <= value && value <= last diff --git a/libraries/stdlib/src/kotlin/ranges/Range.kt b/libraries/stdlib/src/kotlin/ranges/Range.kt index b27931d008d..695592f0599 100644 --- a/libraries/stdlib/src/kotlin/ranges/Range.kt +++ b/libraries/stdlib/src/kotlin/ranges/Range.kt @@ -6,10 +6,10 @@ package kotlin.ranges /** - * Represents a range of values (for example, numbers or characters). + * Represents a range of values (for example, numbers or characters) where both the lower and upper bounds are included in the range. * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/ranges.html) for more information. */ -public interface ClosedRange> { +public interface ClosedRange> { /** * The minimum value in the range. */ @@ -22,6 +22,8 @@ public interface ClosedRange> { /** * Checks whether the specified [value] belongs to the range. + * + * A value belongs to the closed range if it is greater than or equal to the [start] bound and less than or equal to the [endInclusive] bound. */ public operator fun contains(value: T): Boolean = value >= start && value <= endInclusive @@ -32,3 +34,38 @@ public interface ClosedRange> { */ public fun isEmpty(): Boolean = start > endInclusive } + +/** + * Represents a range of values (for example, numbers or characters) where the upper bound is not included in the range. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/ranges.html) for more information. + */ +@SinceKotlin("1.7") +@ExperimentalStdlibApi +public interface OpenEndRange> { + /** + * The minimum value in the range. + */ + public val start: T + + /** + * The maximum value in the range (exclusive). + * + * @throws IllegalStateException can be thrown if the exclusive end bound cannot be represented + * with a value of type [T]. + */ + public val endExclusive: T + + /** + * Checks whether the specified [value] belongs to the range. + * + * A value belongs to the open-ended range if it is greater than or equal to the [start] bound and strictly less than the [endExclusive] bound. + */ + public operator fun contains(value: T): Boolean = value >= start && value < endExclusive + + /** + * Checks whether the range is empty. + * + * The open-ended range is empty if its start value is greater than or equal to the end value. + */ + public fun isEmpty(): Boolean = start >= endExclusive +} \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/ranges/Ranges.kt b/libraries/stdlib/src/kotlin/ranges/Ranges.kt index 05c13820de1..f911f77eefc 100644 --- a/libraries/stdlib/src/kotlin/ranges/Ranges.kt +++ b/libraries/stdlib/src/kotlin/ranges/Ranges.kt @@ -36,6 +36,37 @@ private open class ComparableRange>( */ public operator fun > T.rangeTo(that: T): ClosedRange = ComparableRange(this, that) +/** + * Represents a range of [Comparable] values. + */ +@OptIn(ExperimentalStdlibApi::class) +private open class ComparableOpenEndRange>( + override val start: T, + override val endExclusive: T +) : OpenEndRange { + + override fun equals(other: Any?): Boolean { + return other is ComparableOpenEndRange<*> && (isEmpty() && other.isEmpty() || + start == other.start && endExclusive == other.endExclusive) + } + + override fun hashCode(): Int { + return if (isEmpty()) -1 else 31 * start.hashCode() + endExclusive.hashCode() + } + + override fun toString(): String = "$start..<$endExclusive" +} + +/** + * Creates an open-ended range from this [Comparable] value to the specified [that] value. + * + * This value needs to be smaller than [that] value, otherwise the returned range will be empty. + * @sample samples.ranges.Ranges.rangeFromComparable + */ +@SinceKotlin("1.7") +@ExperimentalStdlibApi +public operator fun > T.rangeUntil(that: T): OpenEndRange = ComparableOpenEndRange(this, that) + /** * Represents a range of floating point numbers. @@ -96,6 +127,47 @@ private class ClosedDoubleRange( @SinceKotlin("1.1") public operator fun Double.rangeTo(that: Double): ClosedFloatingPointRange = ClosedDoubleRange(this, that) +/** + * An open-ended range of values of type `Double`. + * + * Numbers are compared with the ends of this range according to IEEE-754. + */ +@OptIn(ExperimentalStdlibApi::class) +private class OpenEndDoubleRange( + start: Double, + endExclusive: Double +) : OpenEndRange { + private val _start = start + private val _endExclusive = endExclusive + override val start: Double get() = _start + override val endExclusive: Double get() = _endExclusive + + private fun lessThanOrEquals(a: Double, b: Double): Boolean = a <= b + + override fun contains(value: Double): Boolean = value >= _start && value < _endExclusive + override fun isEmpty(): Boolean = !(_start < _endExclusive) + + override fun equals(other: Any?): Boolean { + return other is OpenEndDoubleRange && (isEmpty() && other.isEmpty() || + _start == other._start && _endExclusive == other._endExclusive) + } + + override fun hashCode(): Int { + return if (isEmpty()) -1 else 31 * _start.hashCode() + _endExclusive.hashCode() + } + + override fun toString(): String = "$_start..<$_endExclusive" +} + +/** + * Creates an open-ended range from this [Double] value to the specified [that] value. + * + * Numbers are compared with the ends of this range according to IEEE-754. + */ +@SinceKotlin("1.7") +@ExperimentalStdlibApi +public operator fun Double.rangeUntil(that: Double): OpenEndRange = OpenEndDoubleRange(this, that) + /** * A closed range of values of type `Float`. @@ -138,6 +210,48 @@ private class ClosedFloatRange( public operator fun Float.rangeTo(that: Float): ClosedFloatingPointRange = ClosedFloatRange(this, that) +/** + * An open-ended range of values of type `Float`. + * + * Numbers are compared with the ends of this range according to IEEE-754. + */ +@OptIn(ExperimentalStdlibApi::class) +private class OpenEndFloatRange( + start: Float, + endExclusive: Float +) : OpenEndRange { + private val _start = start + private val _endExclusive = endExclusive + override val start: Float get() = _start + override val endExclusive: Float get() = _endExclusive + + private fun lessThanOrEquals(a: Float, b: Float): Boolean = a <= b + + override fun contains(value: Float): Boolean = value >= _start && value < _endExclusive + override fun isEmpty(): Boolean = !(_start < _endExclusive) + + override fun equals(other: Any?): Boolean { + return other is OpenEndFloatRange && (isEmpty() && other.isEmpty() || + _start == other._start && _endExclusive == other._endExclusive) + } + + override fun hashCode(): Int { + return if (isEmpty()) -1 else 31 * _start.hashCode() + _endExclusive.hashCode() + } + + override fun toString(): String = "$_start..<$_endExclusive" +} + +/** + * Creates an open-ended range from this [Float] value to the specified [that] value. + * + * Numbers are compared with the ends of this range according to IEEE-754. + */ +@SinceKotlin("1.7") +@ExperimentalStdlibApi +public operator fun Float.rangeUntil(that: Float): OpenEndRange = OpenEndFloatRange(this, that) + + /** * Returns `true` if this iterable range contains the specified [element]. * @@ -145,9 +259,19 @@ public operator fun Float.rangeTo(that: Float): ClosedFloatingPointRange */ @SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline operator fun R.contains(element: T?): Boolean where T : Any, R : Iterable, R : ClosedRange = +public inline operator fun R.contains(element: T?): Boolean where T : Any, R : ClosedRange, R : Iterable = element != null && contains(element) +/** + * Returns `true` if this iterable range contains the specified [element]. + * + * Always returns `false` if the [element] is `null`. + */ +@SinceKotlin("1.7") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline operator fun R.contains(element: T?): Boolean where T : Any, R : OpenEndRange, R : Iterable = + element != null && contains(element) internal fun checkStepIsPositive(isPositive: Boolean, step: Number) { if (!isPositive) throw IllegalArgumentException("Step must be positive, was: $step.") diff --git a/libraries/stdlib/unsigned/src/kotlin/UIntRange.kt b/libraries/stdlib/unsigned/src/kotlin/UIntRange.kt index bacfd7b31fe..3fe08dee301 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UIntRange.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UIntRange.kt @@ -16,9 +16,18 @@ import kotlin.internal.* */ @SinceKotlin("1.5") @WasExperimental(ExperimentalUnsignedTypes::class) -public class UIntRange(start: UInt, endInclusive: UInt) : UIntProgression(start, endInclusive, 1), ClosedRange { +@OptIn(ExperimentalStdlibApi::class) +public class UIntRange(start: UInt, endInclusive: UInt) : UIntProgression(start, endInclusive, 1), ClosedRange, OpenEndRange { override val start: UInt get() = first override val endInclusive: UInt get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with UInt type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: UInt get() { + if (last == UInt.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1u + } override fun contains(value: UInt): Boolean = first <= value && value <= last diff --git a/libraries/stdlib/unsigned/src/kotlin/ULongRange.kt b/libraries/stdlib/unsigned/src/kotlin/ULongRange.kt index 794ef069503..7cdfb7d878e 100644 --- a/libraries/stdlib/unsigned/src/kotlin/ULongRange.kt +++ b/libraries/stdlib/unsigned/src/kotlin/ULongRange.kt @@ -16,9 +16,18 @@ import kotlin.internal.* */ @SinceKotlin("1.5") @WasExperimental(ExperimentalUnsignedTypes::class) -public class ULongRange(start: ULong, endInclusive: ULong) : ULongProgression(start, endInclusive, 1), ClosedRange { +@OptIn(ExperimentalStdlibApi::class) +public class ULongRange(start: ULong, endInclusive: ULong) : ULongProgression(start, endInclusive, 1), ClosedRange, OpenEndRange { override val start: ULong get() = first override val endInclusive: ULong get() = last + + @SinceKotlin("1.7") + @ExperimentalStdlibApi + @Deprecated("Can throw an exception when it's impossible to represent the value with ULong type, for example, when the range includes MAX_VALUE. It's recommended to use 'endInclusive' property that doesn't throw.") + override val endExclusive: ULong get() { + if (last == ULong.MAX_VALUE) error("Cannot return the exclusive upper bound of a range that includes MAX_VALUE.") + return last + 1u + } override fun contains(value: ULong): Boolean = first <= value && value <= last diff --git a/libraries/stdlib/wasm/build.gradle.kts b/libraries/stdlib/wasm/build.gradle.kts index 98808f07d28..006a01601b6 100644 --- a/libraries/stdlib/wasm/build.gradle.kts +++ b/libraries/stdlib/wasm/build.gradle.kts @@ -117,7 +117,8 @@ tasks.withType>().configureEach { "-opt-in=kotlin.contracts.ExperimentalContracts", "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalUnsignedTypes", - "-opt-in=kotlin.ExperimentalStdlibApi" + "-opt-in=kotlin.ExperimentalStdlibApi", + "-XXLanguage:+RangeUntilOperator", ) } diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/StdlibTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/StdlibTest.kt index 744566093c7..741f248cc4c 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/StdlibTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/StdlibTest.kt @@ -20,7 +20,7 @@ import org.junit.jupiter.api.TestFactory TC( name = "default", runnerType = TestRunnerType.DEFAULT, - freeCompilerArgs = [ENABLE_MPP, STDLIB_IS_A_FRIEND, ENABLE_X_STDLIB_API], + freeCompilerArgs = [ENABLE_MPP, STDLIB_IS_A_FRIEND, ENABLE_X_STDLIB_API, ENABLE_RANGE_UNTIL], sourceLocations = [ "libraries/stdlib/test/**.kt", "libraries/stdlib/common/test/**.kt", @@ -33,7 +33,7 @@ import org.junit.jupiter.api.TestFactory TC( name = "worker", runnerType = TestRunnerType.WORKER, - freeCompilerArgs = [ENABLE_MPP, STDLIB_IS_A_FRIEND, ENABLE_X_STDLIB_API], + freeCompilerArgs = [ENABLE_MPP, STDLIB_IS_A_FRIEND, ENABLE_X_STDLIB_API, ENABLE_RANGE_UNTIL], sourceLocations = [ "libraries/stdlib/test/**.kt", "libraries/stdlib/common/test/**.kt", @@ -54,5 +54,6 @@ class StdlibTest : AbstractNativeBlackBoxTest() { private const val ENABLE_MPP = "-Xmulti-platform" internal const val STDLIB_IS_A_FRIEND = "-friend-modules=$KOTLIN_NATIVE_DISTRIBUTION/klib/common/stdlib" -private const val ENABLE_X_STDLIB_API = "-opt-in=kotlin.RequiresOptIn,kotlin.ExperimentalStdlibApi" +private const val ENABLE_X_STDLIB_API = "-opt-in=kotlin.ExperimentalStdlibApi" +private const val ENABLE_RANGE_UNTIL = "-XXLanguage:+RangeUntilOperator" // keep until 1.8 private const val DISABLED_STDLIB_TEST = "test.collections.CollectionTest.abstractCollectionToArray" \ No newline at end of file