[JVM_IR] Determine correct type of empty varargs array.

When calling vararg methods with a generic vararg type without
passing explicit parameters, we have to allocate an empty array
of the right type. We failed to do so previously, as we did
not take the type arguments for the dispatch receiver into
account.
This commit is contained in:
Mads Ager
2020-10-29 08:10:39 +01:00
committed by Alexander Udalov
parent ffc003c051
commit 1ecf5943ab
9 changed files with 179 additions and 8 deletions
@@ -1066,6 +1066,34 @@ public class FirBlackBoxAgainstJavaCodegenTestGenerated extends AbstractFirBlack
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/varargs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Varargs extends AbstractFirBlackBoxAgainstJavaCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
}
public void testAllFilesPresentInVarargs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/varargs"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("varargsOverride.kt")
public void testVarargsOverride() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride.kt");
}
@TestMetadata("varargsOverride2.kt")
public void testVarargsOverride2() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride2.kt");
}
@TestMetadata("varargsOverride3.kt")
public void testVarargsOverride3() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride3.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/visibility")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -401,8 +401,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
body = context.createJvmIrBuilder(symbol, startOffset, endOffset).run {
var unboundIndex = 0
irExprBody(irCall(callee).apply {
for ((typeParameter, typeArgument) in typeArgumentsMap) {
putTypeArgument(typeParameter.owner.index, typeArgument)
for (typeParameter in irFunctionReference.symbol.owner.allTypeParameters) {
putTypeArgument(typeParameter.index, typeArgumentsMap[typeParameter.symbol])
}
for (parameter in callee.explicitParameters) {
@@ -389,7 +389,6 @@ fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
val result = mutableListOf<IrTypeParameter>()
var current: IrDeclarationParent? = klass
while (current != null) {
// result += current.typeParameters
(current as? IrTypeParametersContainer)?.let { result += it.typeParameters }
current =
when (current) {
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isSubtypeOf
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.utils.DFS
@@ -518,9 +515,24 @@ val IrFunction.allTypeParameters: List<IrTypeParameter>
else
typeParameters
fun IrMemberAccessExpression<*>.getTypeSubstitutionMap(irFunction: IrFunction): Map<IrTypeParameterSymbol, IrType> {
val typeParameters = irFunction.allTypeParameters
return if (typeParameters.isEmpty()) emptyMap() else typeParameters.withIndex().associate {
val dispatchReceiverTypeArguments = (dispatchReceiver?.type as? IrSimpleType)?.arguments ?: emptyList()
if (typeParameters.isEmpty() && dispatchReceiverTypeArguments.isEmpty()) {
return emptyMap()
}
val result = mutableMapOf<IrTypeParameterSymbol, IrType>()
if (dispatchReceiverTypeArguments.isNotEmpty()) {
val parentTypeParameters = extractTypeParameters(irFunction.parentClassOrNull!!)
parentTypeParameters.withIndex().forEach { (index, typeParam) ->
dispatchReceiverTypeArguments[index].typeOrNull?.let {
result[typeParam.symbol] = it
}
}
}
return typeParameters.withIndex().associateTo(result) {
it.value.symbol to getTypeArgument(it.index)!!
}
}
@@ -0,0 +1,18 @@
// FILE: A.java
public abstract class A<T> {
protected abstract String doIt(T... args);
public String test(T... args) {
return doIt(args);
}
}
// FILE: 1.kt
val a: A<Void> =
object : A<Void>() {
override fun doIt(vararg parameters: Void): String = "OK"
}
fun box(): String = a.test()
@@ -0,0 +1,21 @@
// FILE: A.java
public abstract class A<T> {
protected abstract String doIt(T... args);
public <S extends T> String test(S... args) {
return doIt(args);
}
}
// FILE: 1.kt
open class Super
class Sub: Super()
val a: A<Super> =
object : A<Super>() {
override fun doIt(vararg parameters: Super): String = "OK"
}
fun box(): String = a.test<Sub>()
@@ -0,0 +1,37 @@
// FILE: A.java
public abstract class A<T> {
protected abstract String doIt(T... args);
class B<S extends T, U extends S> {
public String test(T... args) {
return doIt(args);
}
public String test2(S... args) {
return doIt(args);
}
public String test3(U... args) {
return doIt(args);
}
}
}
// FILE: 1.kt
open class Super
open class Sub: Super()
class Sub2: Sub()
val a: A<Super> =
object : A<Super>() {
override fun doIt(vararg parameters: Super): String = "OK"
}
fun box(): String {
val b = a.B<Sub, Sub2>()
if (b.test() != "OK") return "FAIL1"
if (b.test2() != "OK") return "FAIL2"
return b.test3()
}
@@ -1096,6 +1096,34 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxAga
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/varargs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Varargs extends AbstractBlackBoxAgainstJavaCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInVarargs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/varargs"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("varargsOverride.kt")
public void testVarargsOverride() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride.kt");
}
@TestMetadata("varargsOverride2.kt")
public void testVarargsOverride2() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride2.kt");
}
@TestMetadata("varargsOverride3.kt")
public void testVarargsOverride3() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride3.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/visibility")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1066,6 +1066,34 @@ public class IrBlackBoxAgainstJavaCodegenTestGenerated extends AbstractIrBlackBo
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/varargs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Varargs extends AbstractIrBlackBoxAgainstJavaCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInVarargs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/varargs"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("varargsOverride.kt")
public void testVarargsOverride() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride.kt");
}
@TestMetadata("varargsOverride2.kt")
public void testVarargsOverride2() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride2.kt");
}
@TestMetadata("varargsOverride3.kt")
public void testVarargsOverride3() throws Exception {
runTest("compiler/testData/codegen/boxAgainstJava/varargs/varargsOverride3.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/visibility")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)