From 98bf0e278f2a7b9d0b2a8ec962493dff8e2893ff Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 27 Dec 2019 16:12:16 +0300 Subject: [PATCH] Fix problem with empty vararg of boxed primitives in JVM_IR When calling a generic Java generic method with vararg parameters with empty vararg, incorrect array creation instruction was generated for primitive type: NEWARRAY T_INT instead of ANEWARRAY java/lang/Integer. Here for Java method public static void takesVarargOfT(T x1, T... xs) {} corresponding vararg parameter was considered to be of type 'Array?', which is not a non-null array type, so, NewArray intrinsic failed to generate proper bytecode. --- .../kotlin/backend/jvm/intrinsics/NewArray.kt | 3 +- .../backend/jvm/lower/VarargLowering.kt | 3 +- .../vararg/emptyVarargOfBoxedPrimitiveType.kt | 43 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ 7 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt index 8888475ed19..648768c37e3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.ir.getArrayElementType import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.types.isArray +import org.jetbrains.kotlin.ir.types.isNullableArray import org.jetbrains.org.objectweb.asm.Type object NewArray : IntrinsicMethod() { @@ -19,7 +20,7 @@ object NewArray : IntrinsicMethod() { codegen.gen(expression.getValueArgument(0)!!, Type.INT_TYPE, codegen.context.irBuiltIns.intType, data) return with(codegen) { val elementIrType = expression.type.getArrayElementType(context.irBuiltIns) - if (expression.type.isArray()) { + if (expression.type.isArray() || expression.type.isNullableArray()) { putReifiedOperationMarkerIfTypeIsReifiedParameter(elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY) mv.newarray(typeMapper.boxType(elementIrType)) } else { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt index c3592a3aaa3..08e83f230ed 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly @@ -56,7 +57,7 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass, val parameter = function.owner.valueParameters[i] if (parameter.varargElementType != null && !parameter.hasDefaultValue()) { // Compute the correct type for the array argument. - val arrayType = parameter.type.substitute(expression.typeSubstitutionMap) + val arrayType = parameter.type.substitute(expression.typeSubstitutionMap).makeNotNull() expression.putValueArgument(i, createBuilder().irArrayOf(arrayType)) } } diff --git a/compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt b/compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt new file mode 100644 index 00000000000..abd1b937c92 --- /dev/null +++ b/compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt @@ -0,0 +1,43 @@ +// TARGET_BACKEND: JVM +// FILE: emptyVarargOfBoxedPrimitiveType.kt + +fun box(): String { + takesVarargOfInt(1) + takesVarargOfT(1) + + J.takesVarargOfInt(1) + J.takesVarargOfInteger(1) + J.takesVarargOfT(1) + + takesVarargOfInt(1, 2) + takesVarargOfT(1, 2) + + J.takesVarargOfInt(1, 2) + J.takesVarargOfInteger(1, 2) + J.takesVarargOfT(1, 2) + + return "OK" +} + +fun takesVarargOfInt(x: Int, vararg xs: Int) {} +fun takesVarargOfT(x: T, vararg xs: T) {} + +// FILE: J.java +public class J { + public static void takesVarargOfInt(int x1, int... xs) {} + + public static void takesVarargOfInteger(Integer x1, Integer... xs) {} + + public static void takesVarargOfT(T x1, T... xs) { + Class x1Class = x1.getClass(); + Class xsClass = xs.getClass(); + Class xsComponentClass = xsClass.getComponentType(); + if (!xsComponentClass.equals(x1Class)) { + throw new AssertionError( + "Wrong array component type " + xsComponentClass + + " for array class " + xsClass + + ", expected: " + x1Class + ); + } + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 2bc123f15ca..3cf11f8f4cb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -28301,6 +28301,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt"); } + @TestMetadata("emptyVarargOfBoxedPrimitiveType.kt") + public void testEmptyVarargOfBoxedPrimitiveType() throws Exception { + runTest("compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt"); + } + @TestMetadata("kt1978.kt") public void testKt1978() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 7da98a0dc8f..68724f752bb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -27118,6 +27118,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt"); } + @TestMetadata("emptyVarargOfBoxedPrimitiveType.kt") + public void testEmptyVarargOfBoxedPrimitiveType() throws Exception { + runTest("compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt"); + } + @TestMetadata("kt1978.kt") public void testKt1978() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index cad7742ebaa..2cfac38b1ba 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -26800,6 +26800,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt"); } + @TestMetadata("emptyVarargOfBoxedPrimitiveType.kt") + public void testEmptyVarargOfBoxedPrimitiveType() throws Exception { + runTest("compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt"); + } + @TestMetadata("kt1978.kt") public void testKt1978() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index ef59010f2bf..2a453b20757 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -26800,6 +26800,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/vararg/doNotCopyImmediatelyCreatedArrays.kt"); } + @TestMetadata("emptyVarargOfBoxedPrimitiveType.kt") + public void testEmptyVarargOfBoxedPrimitiveType() throws Exception { + runTest("compiler/testData/codegen/box/vararg/emptyVarargOfBoxedPrimitiveType.kt"); + } + @TestMetadata("kt1978.kt") public void testKt1978() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt1978.kt");