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.codegen.inline.ReifiedTypeInliner
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.types.isArray
|
import org.jetbrains.kotlin.ir.types.isArray
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNullableArray
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
object NewArray : IntrinsicMethod() {
|
object NewArray : IntrinsicMethod() {
|
||||||
@@ -19,7 +20,7 @@ object NewArray : IntrinsicMethod() {
|
|||||||
codegen.gen(expression.getValueArgument(0)!!, Type.INT_TYPE, codegen.context.irBuiltIns.intType, data)
|
codegen.gen(expression.getValueArgument(0)!!, Type.INT_TYPE, codegen.context.irBuiltIns.intType, data)
|
||||||
return with(codegen) {
|
return with(codegen) {
|
||||||
val elementIrType = expression.type.getArrayElementType(context.irBuiltIns)
|
val elementIrType = expression.type.getArrayElementType(context.irBuiltIns)
|
||||||
if (expression.type.isArray()) {
|
if (expression.type.isArray() || expression.type.isNullableArray()) {
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY)
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY)
|
||||||
mv.newarray(typeMapper.boxType(elementIrType))
|
mv.newarray(typeMapper.boxType(elementIrType))
|
||||||
} else {
|
} 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.declarations.IrPackageFragment
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass,
|
|||||||
val parameter = function.owner.valueParameters[i]
|
val parameter = function.owner.valueParameters[i]
|
||||||
if (parameter.varargElementType != null && !parameter.hasDefaultValue()) {
|
if (parameter.varargElementType != null && !parameter.hasDefaultValue()) {
|
||||||
// Compute the correct type for the array argument.
|
// 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))
|
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");
|
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")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
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");
|
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")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
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");
|
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")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
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");
|
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")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user