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 <T> void takesVarargOfT(T x1, T... xs) {}
corresponding vararg parameter was considered to be of type 'Array<T>?',
which is not a non-null array type, so, NewArray intrinsic failed to generate
proper bytecode.
This commit is contained in:
@@ -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 {
|
||||
|
||||
+2
-1
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <T> 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 <T> 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user