diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt index 72183896520..7e7772c11ce 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt @@ -70,22 +70,22 @@ fun getRangeOrProgressionElementType(rangeType: KotlinType): KotlinType? { val builtIns = rangeTypeDescriptor.builtIns return when { - isTopLevelInPackage(rangeTypeDescriptor, "CharRange", "kotlin.ranges") -> builtIns.charType - isTopLevelInPackage(rangeTypeDescriptor, "IntRange", "kotlin.ranges") -> builtIns.intType - isTopLevelInPackage(rangeTypeDescriptor, "LongRange", "kotlin.ranges") -> builtIns.longType + rangeTypeDescriptor.isTopLevelInPackage("CharRange", "kotlin.ranges") -> builtIns.charType + rangeTypeDescriptor.isTopLevelInPackage("IntRange", "kotlin.ranges") -> builtIns.intType + rangeTypeDescriptor.isTopLevelInPackage("LongRange", "kotlin.ranges") -> builtIns.longType - isTopLevelInPackage(rangeTypeDescriptor, "CharProgression", "kotlin.ranges") -> builtIns.charType - isTopLevelInPackage(rangeTypeDescriptor, "IntProgression", "kotlin.ranges") -> builtIns.intType - isTopLevelInPackage(rangeTypeDescriptor, "LongProgression", "kotlin.ranges") -> builtIns.longType + rangeTypeDescriptor.isTopLevelInPackage("CharProgression", "kotlin.ranges") -> builtIns.charType + rangeTypeDescriptor.isTopLevelInPackage("IntProgression", "kotlin.ranges") -> builtIns.intType + rangeTypeDescriptor.isTopLevelInPackage("LongProgression", "kotlin.ranges") -> builtIns.longType - isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType - isTopLevelInPackage(rangeTypeDescriptor, "ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType + rangeTypeDescriptor.isTopLevelInPackage("ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType + rangeTypeDescriptor.isTopLevelInPackage("ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType - isTopLevelInPackage(rangeTypeDescriptor, "ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type + rangeTypeDescriptor.isTopLevelInPackage("ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type - isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type + rangeTypeDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type - isTopLevelInPackage(rangeTypeDescriptor, "ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type + rangeTypeDescriptor.isTopLevelInPackage("ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type else -> null } @@ -113,7 +113,7 @@ private inline fun CallableDescriptor.isTopLevelExtensionOnType( packageFQN: String, receiverTypePredicate: (KotlinType) -> Boolean ): Boolean { - if (!isTopLevelInPackage(this, name, packageFQN)) return false + if (!this.isTopLevelInPackage(name, packageFQN)) return false val extensionReceiverType = original.extensionReceiverParameter?.type ?: return false return receiverTypePredicate(extensionReceiverType) } @@ -153,6 +153,12 @@ fun isIterableWithIndex(descriptor: CallableDescriptor) = KotlinBuiltIns.isIterableOrNullableIterable(it) } +fun isSequenceWithIndex(descriptor: CallableDescriptor) = + descriptor.isTopLevelExtensionOnType("withIndex", "kotlin.sequences") { + val typeDescriptor = it.constructor.declarationDescriptor ?: return false + typeDescriptor.isTopLevelInPackage("Sequence", "kotlin.sequences") + } + fun isCharSequenceIndices(descriptor: CallableDescriptor) = descriptor.isTopLevelExtensionOnType("indices", "kotlin.text") { KotlinBuiltIns.isCharSequenceOrNullableCharSequence(it) @@ -168,13 +174,13 @@ fun isComparableRangeTo(descriptor: CallableDescriptor) = val extensionReceiverTypeDescriptor = it.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false val upperBoundType = extensionReceiverTypeDescriptor.upperBounds.singleOrNull() ?: return false val upperBoundClassDescriptor = upperBoundType.constructor.declarationDescriptor as? ClassDescriptor ?: return false - isTopLevelInPackage(upperBoundClassDescriptor, "Comparable", "kotlin") + upperBoundClassDescriptor.isTopLevelInPackage("Comparable", "kotlin") } fun isClosedRangeContains(descriptor: CallableDescriptor): Boolean { if (descriptor.name.asString() != "contains") return false val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false - if (!isTopLevelInPackage(containingClassDescriptor, "ClosedRange", "kotlin.ranges")) return false + if (!containingClassDescriptor.isTopLevelInPackage("ClosedRange", "kotlin.ranges")) return false return true } @@ -218,21 +224,21 @@ private fun isPrimitiveNumberType(type: KotlinType) = fun isClosedFloatingPointRangeContains(descriptor: CallableDescriptor): Boolean { if (descriptor.name.asString() != "contains") return false val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false - if (!isTopLevelInPackage(containingClassDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return false + if (!containingClassDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges")) return false return true } fun getClosedFloatingPointRangeElementType(rangeType: KotlinType): KotlinType? { val classDescriptor = rangeType.constructor.declarationDescriptor as? ClassDescriptor ?: return null - if (!isTopLevelInPackage(classDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return null + if (!classDescriptor.isTopLevelInPackage("ClosedFloatingPointRange", "kotlin.ranges")) return null return rangeType.arguments.singleOrNull()?.type } -private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, packageName: String): Boolean { - if (name != descriptor.name.asString()) return false +private fun DeclarationDescriptor.isTopLevelInPackage(name: String, packageName: String): Boolean { + if (name != this.name.asString()) return false - val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false + val containingDeclaration = containingDeclaration as? PackageFragmentDescriptor ?: return false val packageFqName = containingDeclaration.fqName.asString() return packageName == packageFqName } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/IterableWithIndexRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/IterableWithIndexRangeValue.kt index 1940022b0e2..e49959c6fc0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/IterableWithIndexRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/IterableWithIndexRangeValue.kt @@ -7,11 +7,12 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator -import org.jetbrains.kotlin.codegen.range.forLoop.IterableWithIndexForLoopGenerator +import org.jetbrains.kotlin.codegen.range.forLoop.IteratorWithIndexForLoopGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.org.objectweb.asm.Type class IterableWithIndexRangeValue(rangeCall: ResolvedCall) : AbstractDestructuredPairRangeValue(rangeCall) { @@ -21,6 +22,9 @@ class IterableWithIndexRangeValue(rangeCall: ResolvedCall ): ForLoopGenerator = - IterableWithIndexForLoopGenerator(codegen, forExpression, loopParameter, rangeCall) + IteratorWithIndexForLoopGenerator( + codegen, forExpression, loopParameter, rangeCall, + iteratorOwnerType = Type.getType(java.lang.Iterable::class.java) + ) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt index 6f1ccc60482..b799221a8a8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt @@ -130,6 +130,8 @@ private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: Reso ArrayWithIndexRangeValue(rangeCall) isIterableWithIndex(rangeCallee) -> IterableWithIndexRangeValue(rangeCall) + isSequenceWithIndex(rangeCallee) -> + SequenceWithIndexRangeValue(rangeCall) isCharSequenceWithIndex(rangeCallee) -> CharSequenceWithIndexRangeValue(rangeCall) isComparableRangeTo(rangeCallee) -> diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SequenceWithIndexRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SequenceWithIndexRangeValue.kt new file mode 100644 index 00000000000..2acf7ef1ed4 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SequenceWithIndexRangeValue.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen.range + +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator +import org.jetbrains.kotlin.codegen.range.forLoop.IteratorWithIndexForLoopGenerator +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.psi.KtDestructuringDeclaration +import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.org.objectweb.asm.Type + +class SequenceWithIndexRangeValue(rangeCall: ResolvedCall) : AbstractDestructuredPairRangeValue(rangeCall) { + + override fun createDestructuredPairForLoopGenerator( + codegen: ExpressionCodegen, + forExpression: KtForExpression, + loopParameter: KtDestructuringDeclaration, + rangeCall: ResolvedCall + ): ForLoopGenerator = + IteratorWithIndexForLoopGenerator( + codegen, forExpression, loopParameter, rangeCall, + iteratorOwnerType = Type.getType(Sequence::class.java) + ) + +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IterableWithIndexForLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IteratorWithIndexForLoopGenerator.kt similarity index 88% rename from compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IterableWithIndexForLoopGenerator.kt rename to compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IteratorWithIndexForLoopGenerator.kt index e8774055236..4fa2effe1f2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IterableWithIndexForLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/IteratorWithIndexForLoopGenerator.kt @@ -16,11 +16,12 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Type -class IterableWithIndexForLoopGenerator( +class IteratorWithIndexForLoopGenerator( codegen: ExpressionCodegen, forExpression: KtForExpression, loopParameter: KtDestructuringDeclaration, - rangeCall: ResolvedCall + rangeCall: ResolvedCall, + private val iteratorOwnerType: Type ) : AbstractWithIndexForLoopGenerator(codegen, forExpression, loopParameter, rangeCall) { private var iteratorVar = -1 @@ -37,8 +38,8 @@ class IterableWithIndexForLoopGenerator( .store(StackValue.constant(0, Type.INT_TYPE), v) iteratorVar = createLoopTempVariable(asmTypeForIterator) - codegen.generateCallReceiver(rangeCall).put(Type.getType(Iterable::class.java), v) - v.invokeinterface("java/lang/Iterable", "iterator", "()Ljava/util/Iterator;") + codegen.generateCallReceiver(rangeCall).put(iteratorOwnerType, v) + v.invokeinterface(iteratorOwnerType.internalName, "iterator", "()Ljava/util/Iterator;") StackValue.local(iteratorVar, asmTypeForIterator).store(StackValue.onStack(asmTypeForIterator), v) } diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt new file mode 100644 index 00000000000..7f6c239f1e0 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME + +val xs = listOf().asSequence() + +fun box(): String { + val s = StringBuilder() + for ((index, x) in xs.withIndex()) { + return "Loop over empty list should not be executed" + } + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt new file mode 100644 index 00000000000..88796c7f316 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt @@ -0,0 +1,14 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((index, x) in xs.withIndex()) { + s.append("$index:$x;") + } + + val ss = s.toString() + return if (ss == "0:a;1:b;2:c;3:d;") "OK" else "fail: '$ss'" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt new file mode 100644 index 00000000000..a71fdae9033 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt @@ -0,0 +1,14 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((i, _) in xs.withIndex()) { + s.append("$i;") + } + + val ss = s.toString() + return if (ss == "0;1;2;3;") "OK" else "fail: '$ss'" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt new file mode 100644 index 00000000000..6496606222f --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt @@ -0,0 +1,14 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((_, x) in xs.withIndex()) { + s.append("$x;") + } + + val ss = s.toString() + return if (ss == "a;b;c;d;") "OK" else "fail: '$ss'" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt new file mode 100644 index 00000000000..22483aea42e --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND: JS, NATIVE +// FULL_JDK +// WITH_RUNTIME + +val xsl = arrayListOf("a", "b", "c", "d") +val xs = xsl.asSequence() + +fun box(): String { + val s = StringBuilder() + + var cmeThrown = false + try { + for ((index, x) in xs.withIndex()) { + s.append("$index:$x;") + xsl.clear() + } + } catch (e: java.util.ConcurrentModificationException) { + cmeThrown = true + } + + if (!cmeThrown) return "Fail: CME should be thrown" + + val ss = s.toString() + return if (ss == "0:a;") "OK" else "fail: '$ss'" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt new file mode 100644 index 00000000000..67196f6fadd --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt @@ -0,0 +1,17 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun useAny(x: Any) {} + +fun box(): String { + val s = StringBuilder() + + for ((index: Any, x) in xs.withIndex()) { + useAny(index) + s.append("$index:$x;") + } + + val ss = s.toString() + return if (ss == "0:a;1:b;2:c;3:d;") "OK" else "fail: '$ss'" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt new file mode 100644 index 00000000000..b6a3adc2c6c --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt @@ -0,0 +1,18 @@ +// WITH_RUNTIME + +val xs = listOf().asSequence() + +fun box(): String { + val s = StringBuilder() + for ((index, x) in xs.withIndex()) { + return "Loop over empty list should not be executed" + } + return "OK" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndex.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndex.kt new file mode 100644 index 00000000000..6c3924cd7f2 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndex.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((index, x) in xs.withIndex()) { + s.append("$index:$x;") + } + + val ss = s.toString() + return if (ss == "0:a;1:b;2:c;3:d;") "OK" else "fail: '$ss'" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt new file mode 100644 index 00000000000..34e7fec0508 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((i, _) in xs.withIndex()) { + s.append("$i;") + } + + val ss = s.toString() + return if (ss == "0;1;2;3;") "OK" else "fail: '$ss'" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt new file mode 100644 index 00000000000..a5a3d8bc998 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun box(): String { + val s = StringBuilder() + + for ((_, x) in xs.withIndex()) { + s.append("$x;") + } + + val ss = s.toString() + return if (ss == "a;b;c;d;") "OK" else "fail: '$ss'" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt new file mode 100644 index 00000000000..0dbad69823f --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt @@ -0,0 +1,32 @@ +// IGNORE_BACKEND: JS, NATIVE +// FULL_JDK +// WITH_RUNTIME + +val xsl = arrayListOf("a", "b", "c", "d") +val xs = xsl.asSequence() + +fun box(): String { + val s = StringBuilder() + + var cmeThrown = false + try { + for ((index, x) in xs.withIndex()) { + s.append("$index:$x;") + xsl.clear() + } + } catch (e: java.util.ConcurrentModificationException) { + cmeThrown = true + } + + if (!cmeThrown) return "Fail: CME should be thrown" + + val ss = s.toString() + return if (ss == "0:a;") "OK" else "fail: '$ss'" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt new file mode 100644 index 00000000000..b7cb31d1814 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt @@ -0,0 +1,24 @@ +// WITH_RUNTIME + +val xs = listOf("a", "b", "c", "d").asSequence() + +fun useAny(x: Any) {} + +fun box(): String { + val s = StringBuilder() + + for ((index: Any, x) in xs.withIndex()) { + useAny(index) + s.append("$index:$x;") + } + + val ss = s.toString() + return if (ss == "0:a;1:b;2:c;3:d;") "OK" else "fail: '$ss'" +} + +// 0 withIndex +// 1 iterator +// 1 hasNext +// 1 next +// 0 component1 +// 0 component2 \ 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 19351001ac5..d9d33b6650c 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 @@ -5319,6 +5319,51 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ForInSequenceWithIndex extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInForInSequenceWithIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("forInEmptySequenceWithIndex.kt") + public void testForInEmptySequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndex.kt") + public void testForInSequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoElementVar.kt") + public void testForInSequenceWithIndexNoElementVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoIndexVar.kt") + public void testForInSequenceWithIndexNoIndexVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexThrowsCME.kt") + public void testForInSequenceWithIndexThrowsCME() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt") + public void testForInSequenceWithIndexWithExplicitlyTypedIndexVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/controlStructures/returnsNothing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index ee4df40ffb0..9d141ebaeae 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5319,6 +5319,51 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ForInSequenceWithIndex extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInForInSequenceWithIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("forInEmptySequenceWithIndex.kt") + public void testForInEmptySequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndex.kt") + public void testForInSequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoElementVar.kt") + public void testForInSequenceWithIndexNoElementVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoIndexVar.kt") + public void testForInSequenceWithIndexNoIndexVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexThrowsCME.kt") + public void testForInSequenceWithIndexThrowsCME() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt") + public void testForInSequenceWithIndexWithExplicitlyTypedIndexVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/controlStructures/returnsNothing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 4d17da1ce53..b9dd203bbc9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1604,6 +1604,51 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ForInSequenceWithIndex extends AbstractBytecodeTextTest { + public void testAllFilesPresentInForInSequenceWithIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("forInEmptySequenceWithIndex.kt") + public void testForInEmptySequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndex.kt") + public void testForInSequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoElementVar.kt") + public void testForInSequenceWithIndexNoElementVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoIndexVar.kt") + public void testForInSequenceWithIndexNoIndexVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexThrowsCME.kt") + public void testForInSequenceWithIndexThrowsCME() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt") + public void testForInSequenceWithIndexWithExplicitlyTypedIndexVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/bytecodeText/hashCode") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6958327430f..c7d71769d8b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -5319,6 +5319,51 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ForInSequenceWithIndex extends AbstractLightAnalysisModeTest { + public void testAllFilesPresentInForInSequenceWithIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("forInEmptySequenceWithIndex.kt") + public void testForInEmptySequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndex.kt") + public void testForInSequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoElementVar.kt") + public void testForInSequenceWithIndexNoElementVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoIndexVar.kt") + public void testForInSequenceWithIndexNoIndexVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexThrowsCME.kt") + public void testForInSequenceWithIndexThrowsCME() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt") + public void testForInSequenceWithIndexWithExplicitlyTypedIndexVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/controlStructures/returnsNothing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) 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 977fe88a5a2..e9884d1db95 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 @@ -5913,6 +5913,57 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ForInSequenceWithIndex extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInForInSequenceWithIndex() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("forInEmptySequenceWithIndex.kt") + public void testForInEmptySequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInEmptySequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndex.kt") + public void testForInSequenceWithIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndex.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoElementVar.kt") + public void testForInSequenceWithIndexNoElementVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoElementVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexNoIndexVar.kt") + public void testForInSequenceWithIndexNoIndexVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexNoIndexVar.kt"); + doTest(fileName); + } + + @TestMetadata("forInSequenceWithIndexThrowsCME.kt") + public void testForInSequenceWithIndexThrowsCME() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexThrowsCME.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + + @TestMetadata("forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt") + public void testForInSequenceWithIndexWithExplicitlyTypedIndexVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/controlStructures/returnsNothing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)