diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/AbstractBoundedValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/AbstractBoundedValue.kt new file mode 100644 index 00000000000..123b2ef281f --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/AbstractBoundedValue.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen.range + +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +abstract class AbstractBoundedValue( + protected val codegen: ExpressionCodegen, + protected val rangeCall: ResolvedCall, + override val isLowInclusive: Boolean = true, + override val isHighInclusive: Boolean = true +) : BoundedValue { + override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!) + + override fun putInstance(v: InstructionAdapter, type: Type) { + codegen.invokeFunction(rangeCall.call, rangeCall, StackValue.none()).put(type, v) + } +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt index e75dece7c10..168acae1c71 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt @@ -25,19 +25,21 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class ArrayIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) override fun getBoundedValue(codegen: ExpressionCodegen) = - SimpleBoundedValue( - codegen, rangeCall, - lowBound = StackValue.constant(0, asmElementType), - highBound = StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) - v.arraylength() - } - ) + object : AbstractBoundedValue(codegen, rangeCall) { + override fun putHighLow(v: InstructionAdapter, type: Type) { + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.arraylength() + StackValue.coerce(Type.INT_TYPE, type, v) + + StackValue.constant(0, asmElementType).put(type, v) + } + } override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt index 2968b0500c9..f5892c8126e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt @@ -25,19 +25,21 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) override fun getBoundedValue(codegen: ExpressionCodegen) = - SimpleBoundedValue( - codegen, rangeCall, - lowBound = StackValue.constant(0, asmElementType), - highBound = StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) - v.invokeinterface("java/lang/CharSequence", "length", "()I") - } - ) + object : AbstractBoundedValue(codegen, rangeCall) { + override fun putHighLow(v: InstructionAdapter, type: Type) { + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.invokeinterface("java/lang/CharSequence", "length", "()I") + StackValue.coerce(Type.INT_TYPE, type, v) + + StackValue.constant(0, asmElementType).put(type, v) + } + } override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt index 70cd5c4a9f9..8e29ea3e9f7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt @@ -25,19 +25,21 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class CollectionIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) override fun getBoundedValue(codegen: ExpressionCodegen) = - SimpleBoundedValue( - codegen, rangeCall, - lowBound = StackValue.constant(0, asmElementType), - highBound = StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) - v.invokeinterface("java/util/Collection", "size", "()I") - } - ) + object : AbstractBoundedValue(codegen, rangeCall) { + override fun putHighLow(v: InstructionAdapter, type: Type) { + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.invokeinterface("java/util/Collection", "size", "()I") + StackValue.coerce(Type.INT_TYPE, type, v) + + StackValue.constant(0, asmElementType).put(type, v) + } + } override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt index c12d11c65dc..54fb1f31d0a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt @@ -37,7 +37,10 @@ interface BoundedValue { fun putInstance(v: InstructionAdapter, type: Type) + // It is necessary to maintain the proper evaluation order as of Kotlin 1.0 and 1.1 + // to evaluate range bounds left to right and put them on stack as 'high; low'. fun putHighLow(v: InstructionAdapter, type: Type) + val isLowInclusive: Boolean val isHighInclusive: Boolean } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt index 5e33222801f..11b0f02a391 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt @@ -16,23 +16,20 @@ package org.jetbrains.kotlin.codegen.range -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.codegen.generateCallReceiver -import org.jetbrains.kotlin.codegen.generateCallSingleArgument +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class SimpleBoundedValue( - private val codegen: ExpressionCodegen, - private val rangeCall: ResolvedCall, + codegen: ExpressionCodegen, + rangeCall: ResolvedCall, private val lowBound: StackValue, - override val isLowInclusive: Boolean, + isLowInclusive: Boolean, private val highBound: StackValue, - override val isHighInclusive: Boolean -): BoundedValue { + isHighInclusive: Boolean +): AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) { constructor( codegen: ExpressionCodegen, rangeCall: ResolvedCall, @@ -54,18 +51,9 @@ class SimpleBoundedValue( highBound: StackValue ) : this(codegen, rangeCall, lowBound, true, highBound, true) - override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!) - - override fun putInstance(v: InstructionAdapter, type: Type) { - codegen.invokeFunction(rangeCall.call, rangeCall, StackValue.none()).put(type, v) - } - override fun putHighLow(v: InstructionAdapter, type: Type) { - highBound.put(type, v) lowBound.put(type, v) - } - - companion object { - + highBound.put(type, v) + AsmUtil.swap(v, type, type) } } \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt new file mode 100644 index 00000000000..51fc4e2ae8a --- /dev/null +++ b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt @@ -0,0 +1,27 @@ +// WITH_RUNTIME + +val order = StringBuilder() + +inline fun expectOrder(at: String, expected: String, body: () -> Unit) { + order.setLength(0) + body() + if (order.toString() != expected) throw AssertionError("$at: expected: $expected, actual: $order") +} + +fun list(): List { + order.append("L") + return emptyList() +} + + +fun x(i: Int): Int { + order.append("X") + return i +} + +fun box(): String { + expectOrder("1 in []", "LX") { x(1) in list() } + expectOrder("1 !in []", "LX") { x(1) !in list() } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt new file mode 100644 index 00000000000..07b5497f520 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt @@ -0,0 +1,35 @@ +// WITH_RUNTIME + +val order = StringBuilder() + +inline fun expectOrder(at: String, expected: String, body: () -> Unit) { + order.setLength(0) + body() + if (order.toString() != expected) { + throw AssertionError("$at: expected: '$expected', actual: '$order'") + } +} + +class Z(val x: Int) : Comparable { + override fun compareTo(other: Z): Int { + order.append("c:$x,${other.x} ") + return x.compareTo(other.x) + } +} + +fun z(i: Int): Z { + order.append("z:$i ") + return Z(i) +} + +fun box(): String { + expectOrder("z0 in z1 .. z3", "z:1 z:3 z:0 c:1,0 ") { z(0) in z(1) .. z(3) } + expectOrder("z2 in z1 .. z3", "z:1 z:3 z:2 c:1,2 c:3,2 ") { z(2) in z(1) .. z(3) } + expectOrder("z4 in z1 .. z3", "z:1 z:4 z:2 c:1,2 c:4,2 ") { z(2) in z(1) .. z(4) } + + expectOrder("z0 !in z1 .. z3", "z:1 z:3 z:0 c:1,0 ") { z(0) !in z(1) .. z(3) } + expectOrder("z2 !in z1 .. z3", "z:1 z:3 z:2 c:1,2 c:3,2 ") { z(2) !in z(1) .. z(3) } + expectOrder("z4 !in z1 .. z3", "z:1 z:4 z:2 c:1,2 c:4,2 ") { z(2) !in z(1) .. z(4) } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt new file mode 100644 index 00000000000..5a13483ad40 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt @@ -0,0 +1,31 @@ +// WITH_RUNTIME + +val order = StringBuilder() + +inline fun expectOrder(at: String, expected: String, body: () -> Unit) { + order.setLength(0) + body() + if (order.toString() != expected) throw AssertionError("$at: expected: $expected, actual: $order") +} + +fun low(i: Int): Int { + order.append("L") + return i +} + +fun high(i: Int): Int { + order.append("H") + return i +} + +fun x(i: Int): Int { + order.append("X") + return i +} + +fun box(): String { + expectOrder("0 in 1 .. 3", "HLX") { x(0) in high(3) downTo low(1) } + expectOrder("0 !in 1 .. 3", "HLX") { x(0) !in high(3) downTo low(1) } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt new file mode 100644 index 00000000000..214fc6abe5b --- /dev/null +++ b/compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt @@ -0,0 +1,31 @@ +// WITH_RUNTIME + +val order = StringBuilder() + +inline fun expectOrder(at: String, expected: String, body: () -> Unit) { + order.setLength(0) + body() + if (order.toString() != expected) throw AssertionError("$at: expected: $expected, actual: $order") +} + +fun low(i: Int): Int { + order.append("L") + return i +} + +fun high(i: Int): Int { + order.append("H") + return i +} + +fun x(i: Int): Int { + order.append("X") + return i +} + +fun box(): String { + expectOrder("0 in 1 .. 3", "LHX") { x(0) in low(1) .. high(3) } + expectOrder("0 !in 1 .. 3", "LHX") { x(0) !in low(1) .. high(3) } + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d74a0ddd50b..9b71798c5a9 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13177,6 +13177,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/contains"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("evaluationOrderForCollection.kt") + public void testEvaluationOrderForCollection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForComparableRange.kt") + public void testEvaluationOrderForComparableRange() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForDownTo.kt") + public void testEvaluationOrderForDownTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForRangeLiteral.kt") + public void testEvaluationOrderForRangeLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt"); + doTest(fileName); + } + @TestMetadata("inArray.kt") public void testInArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3d2cffbc624..29342fbc97d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13177,6 +13177,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/contains"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("evaluationOrderForCollection.kt") + public void testEvaluationOrderForCollection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForComparableRange.kt") + public void testEvaluationOrderForComparableRange() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForDownTo.kt") + public void testEvaluationOrderForDownTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForRangeLiteral.kt") + public void testEvaluationOrderForRangeLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt"); + doTest(fileName); + } + @TestMetadata("inArray.kt") public void testInArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8b5e0daec52..3ff36f5a864 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13177,6 +13177,30 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/contains"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("evaluationOrderForCollection.kt") + public void testEvaluationOrderForCollection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForComparableRange.kt") + public void testEvaluationOrderForComparableRange() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForDownTo.kt") + public void testEvaluationOrderForDownTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForRangeLiteral.kt") + public void testEvaluationOrderForRangeLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt"); + doTest(fileName); + } + @TestMetadata("inArray.kt") public void testInArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 91f6e7cd97b..bcabe9defa1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -14785,6 +14785,30 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/contains"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("evaluationOrderForCollection.kt") + public void testEvaluationOrderForCollection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForCollection.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForComparableRange.kt") + public void testEvaluationOrderForComparableRange() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForComparableRange.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForDownTo.kt") + public void testEvaluationOrderForDownTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForDownTo.kt"); + doTest(fileName); + } + + @TestMetadata("evaluationOrderForRangeLiteral.kt") + public void testEvaluationOrderForRangeLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/evaluationOrderForRangeLiteral.kt"); + doTest(fileName); + } + @TestMetadata("inArray.kt") public void testInArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");