From fbf24248384234204b08b04e51b94e27a503671f Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 5 Oct 2015 18:04:46 +0300 Subject: [PATCH] Spread should always copy arrays. --- .../kotlin/codegen/ExpressionCodegen.java | 14 ++++++++-- .../boxWithStdlib/vararg/spreadCopiesArray.kt | 27 +++++++++++++++++++ .../jetbrains/kotlin/codegen/VarArgTest.java | 5 +++- ...lackBoxWithStdlibCodegenTestGenerated.java | 6 +++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/vararg/spreadCopiesArray.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 63303aa6331..0882a148711 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2683,14 +2683,24 @@ public class ExpressionCodegen extends JetVisitor implem } if (hasSpread) { + boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); if (size == 1) { - gen(arguments.get(0).getArgumentExpression(), type); + // Arrays.copyOf(array, newLength) + ValueArgument argument = arguments.get(0); + Type arrayType = arrayOfReferences ? Type.getType("[Ljava/lang/Object;") + : Type.getType("[" + elementType.getDescriptor()); + gen(argument.getArgumentExpression(), type); + v.dup(); + v.arraylength(); + v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false); + if (arrayOfReferences) { + v.checkcast(type); + } } else { String owner; String addDescriptor; String toArrayDescriptor; - boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); if (arrayOfReferences) { owner = "kotlin/jvm/internal/SpreadBuilder"; addDescriptor = "(Ljava/lang/Object;)V"; diff --git a/compiler/testData/codegen/boxWithStdlib/vararg/spreadCopiesArray.kt b/compiler/testData/codegen/boxWithStdlib/vararg/spreadCopiesArray.kt new file mode 100644 index 00000000000..674e652e23a --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/vararg/spreadCopiesArray.kt @@ -0,0 +1,27 @@ +import kotlin.test.* + +fun copyArray(vararg data: T): Array = data + +inline fun reifiedCopyArray(vararg data: T): Array = data + +fun copyIntArray(vararg data: Int): IntArray = data + +fun box(): String { + val sarr = arrayOf("OK") + val sarr2 = copyArray(*sarr) + sarr[0] = "Array was not copied" + assertEquals(sarr2[0], "OK", "Failed: Array") + + var rsarr = arrayOf("OK") + var rsarr2 = reifiedCopyArray(*rsarr) + rsarr[0] = "Array was not copied" + assertEquals(rsarr2[0], "OK", "Failed: Array, reified copy") + + val iarr = IntArray(1) + iarr[0] = 1 + val iarr2 = copyIntArray(*iarr) + iarr[0] = 42 + assertEquals(iarr2[0], 1, "Failed: IntArray") + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/VarArgTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/VarArgTest.java index b56c1b5d4af..38fd2481ce0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/VarArgTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/VarArgTest.java @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.test.ConfigurationKind; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; public class VarArgTest extends CodegenTestCase { @Override @@ -89,7 +90,9 @@ public class VarArgTest extends CodegenTestCase { loadText("private fun asList(vararg elems: String) = elems; fun test(ts: Array) = asList(*ts); "); Method main = generateFunction("test"); String[] args = {"mama", "papa"}; - assertTrue(args == main.invoke(null, new Object[]{ args } )); + String[] result = (String []) main.invoke(null, new Object[] {args}); + assertTrue(args != result); + assertTrue(Arrays.equals(args, result)); } public void testArrayAsVararg2() throws InvocationTargetException, IllegalAccessException { diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index a566ebbe515..8575c95b222 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -4591,6 +4591,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/vararg"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("spreadCopiesArray.kt") + public void testSpreadCopiesArray() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/vararg/spreadCopiesArray.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("varargInFunParam.kt") public void testVarargInFunParam() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/vararg/varargInFunParam.kt");