JVM: fix type mapping of big arity suspend function types
The code in IrTypeMapper was incorrectly translated from KotlinTypeMapper during the development of JVM IR. The `classDescriptor.hasBigArity` condition in KotlinTypeMapper was checking if the class represents a function or a suspend function with big arity, and the suspend function part was lost during conversion. This resulted in incorrect generic signature being generated, which led to malformed type exceptions from reflection, and compilation errors from kapt stub generation. Also, change a comment in irCodegenUtils to avoid confusion of numbered function types (kotlin.jvm.functions.Function1, ...) with the big-arity type kotlin.jvm.functions.FunctionN. #KT-58375 Fixed
This commit is contained in:
committed by
Space Team
parent
f659b63aef
commit
c06ec84bb1
+6
@@ -12954,6 +12954,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
|
||||
+6
@@ -12954,6 +12954,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
|
||||
+2
-2
@@ -241,8 +241,8 @@ internal fun IrTypeMapper.mapClassSignature(irClass: IrClass, type: Type, genera
|
||||
if (generateBodies && irClass.superTypes.any { it.isSuspendFunction() || it.isKSuspendFunction() }) {
|
||||
// Do not generate this class in the kapt3 mode (generateBodies=false), because kapt3 transforms supertypes correctly in the
|
||||
// "correctErrorTypes" mode only when the number of supertypes between PSI and bytecode is equal. Otherwise it tries to "correct"
|
||||
// the FunctionN type and fails, because that type doesn't need an import in the Kotlin source (kotlin.FunctionN), but needs one
|
||||
// in the Java source (kotlin.jvm.functions.FunctionN), and kapt3 doesn't perform any Kotlin->Java name lookup.
|
||||
// the Function{n} type and fails, because that type doesn't need an import in the Kotlin source (kotlin.Function{n}), but needs one
|
||||
// in the Java source (kotlin.jvm.functions.Function{n}), and kapt3 doesn't perform any Kotlin->Java name lookup.
|
||||
kotlinMarkerInterfaces.add("kotlin/coroutines/jvm/internal/SuspendFunction")
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.AbstractTypeMapper
|
||||
@@ -195,9 +196,7 @@ open class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapp
|
||||
val parameters = classifier.typeParameters.map(IrTypeParameter::symbol)
|
||||
val arguments = type.arguments
|
||||
|
||||
if ((classifier.symbol.isFunction() && arguments.size > BuiltInFunctionArity.BIG_ARITY)
|
||||
|| classifier.symbol.isKFunction() || classifier.symbol.isKSuspendFunction()
|
||||
) {
|
||||
if (isBigArityFunction(classifier, arguments) || classifier.symbol.isKFunction() || classifier.symbol.isKSuspendFunction()) {
|
||||
writeGenericArguments(sw, listOf(arguments.last()), listOf(parameters.last()), mode)
|
||||
return
|
||||
}
|
||||
@@ -205,11 +204,15 @@ open class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapp
|
||||
writeGenericArguments(sw, arguments, parameters, mode)
|
||||
}
|
||||
|
||||
private fun isBigArityFunction(classifier: IrClass, arguments: List<IrTypeArgument>): Boolean =
|
||||
arguments.size > BuiltInFunctionArity.BIG_ARITY &&
|
||||
(classifier.symbol.isFunction() || classifier.symbol.isSuspendFunction())
|
||||
|
||||
private fun writeGenericArguments(
|
||||
sw: JvmSignatureWriter,
|
||||
arguments: List<IrTypeArgument>,
|
||||
parameters: List<IrTypeParameterSymbol>,
|
||||
mode: TypeMappingMode
|
||||
mode: TypeMappingMode,
|
||||
) {
|
||||
with(KotlinTypeMapper) {
|
||||
typeSystem.writeGenericArguments(sw, arguments, parameters, mode) { type, sw, mode ->
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
// WITH_COROUTINES
|
||||
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
import kotlin.reflect.full.*
|
||||
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
interface Flow<T>
|
||||
|
||||
class C
|
||||
|
||||
suspend fun foo(
|
||||
f: suspend (C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C) -> String
|
||||
): String =
|
||||
f(C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C(), C())
|
||||
|
||||
fun box(): String {
|
||||
var res = "Fail"
|
||||
builder {
|
||||
val f: suspend (C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C) -> String = {
|
||||
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ->
|
||||
"OK"
|
||||
}
|
||||
res = ::foo.callSuspend(f)
|
||||
}
|
||||
return res
|
||||
}
|
||||
+6
@@ -12684,6 +12684,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
|
||||
+6
@@ -12954,6 +12954,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
|
||||
+6
@@ -12954,6 +12954,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
|
||||
+5
@@ -10216,6 +10216,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bigArityLambda.kt")
|
||||
public void testBigArityLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/bigArityLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callSuspend.kt")
|
||||
public void testCallSuspend() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt");
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
@kotlin.Metadata()
|
||||
public abstract interface Flow<T extends java.lang.Object> {
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class SuspendFunctionWithBigArityKt {
|
||||
|
||||
public SuspendFunctionWithBigArityKt() {
|
||||
super();
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final <T1 extends java.lang.Object, T2 extends java.lang.Object, T3 extends java.lang.Object, T4 extends java.lang.Object, T5 extends java.lang.Object, T6 extends java.lang.Object, T7 extends java.lang.Object, T8 extends java.lang.Object, T9 extends java.lang.Object, T10 extends java.lang.Object, T11 extends java.lang.Object, T12 extends java.lang.Object, T13 extends java.lang.Object, T14 extends java.lang.Object, T15 extends java.lang.Object, T16 extends java.lang.Object, T17 extends java.lang.Object, T18 extends java.lang.Object, T19 extends java.lang.Object, T20 extends java.lang.Object, T21 extends java.lang.Object, T22 extends java.lang.Object, T23 extends java.lang.Object, R extends java.lang.Object>Flow<R> combine(@org.jetbrains.annotations.NotNull()
|
||||
Flow<T1> flow, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T2> flow2, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T3> flow3, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T4> flow4, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T5> flow5, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T6> flow6, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T7> flow7, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T8> flow8, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T9> flow9, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T10> flow10, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T11> flow11, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T12> flow12, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T13> flow13, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T14> flow14, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T15> flow15, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T16> flow16, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T17> flow17, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T18> flow18, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T19> flow19, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T20> flow20, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T21> flow21, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T22> flow22, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T23> flow23, @org.jetbrains.annotations.NotNull()
|
||||
kotlin.jvm.functions.FunctionN<? extends R> transform) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
interface Flow<T>
|
||||
|
||||
fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, R> combine(
|
||||
flow: Flow<T1>,
|
||||
flow2: Flow<T2>,
|
||||
flow3: Flow<T3>,
|
||||
flow4: Flow<T4>,
|
||||
flow5: Flow<T5>,
|
||||
flow6: Flow<T6>,
|
||||
flow7: Flow<T7>,
|
||||
flow8: Flow<T8>,
|
||||
flow9: Flow<T9>,
|
||||
flow10: Flow<T10>,
|
||||
flow11: Flow<T11>,
|
||||
flow12: Flow<T12>,
|
||||
flow13: Flow<T13>,
|
||||
flow14: Flow<T14>,
|
||||
flow15: Flow<T15>,
|
||||
flow16: Flow<T16>,
|
||||
flow17: Flow<T17>,
|
||||
flow18: Flow<T18>,
|
||||
flow19: Flow<T19>,
|
||||
flow20: Flow<T20>,
|
||||
flow21: Flow<T21>,
|
||||
flow22: Flow<T22>,
|
||||
flow23: Flow<T23>,
|
||||
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) -> R
|
||||
): Flow<R> = combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9, flow10, flow11, flow12, flow13, flow14, flow15, flow16, flow17, flow18, flow19, flow20, flow21, flow22, flow23) { args: Array<*> ->
|
||||
transform(
|
||||
args[0] as T1,
|
||||
args[1] as T2,
|
||||
args[2] as T3,
|
||||
args[3] as T4,
|
||||
args[4] as T5,
|
||||
args[5] as T6,
|
||||
args[6] as T7,
|
||||
args[7] as T8,
|
||||
args[8] as T9,
|
||||
args[9] as T10,
|
||||
args[10] as T11,
|
||||
args[11] as T12,
|
||||
args[12] as T13,
|
||||
args[13] as T14,
|
||||
args[14] as T15,
|
||||
args[15] as T16,
|
||||
args[16] as T17,
|
||||
args[17] as T18,
|
||||
args[18] as T19,
|
||||
args[19] as T20,
|
||||
args[20] as T21,
|
||||
args[21] as T22,
|
||||
args[22] as T23,
|
||||
)
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
@kotlin.Metadata()
|
||||
public abstract interface Flow<T extends java.lang.Object> {
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class SuspendFunctionWithBigArityKt {
|
||||
|
||||
public SuspendFunctionWithBigArityKt() {
|
||||
super();
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final <T1 extends java.lang.Object, T2 extends java.lang.Object, T3 extends java.lang.Object, T4 extends java.lang.Object, T5 extends java.lang.Object, T6 extends java.lang.Object, T7 extends java.lang.Object, T8 extends java.lang.Object, T9 extends java.lang.Object, T10 extends java.lang.Object, T11 extends java.lang.Object, T12 extends java.lang.Object, T13 extends java.lang.Object, T14 extends java.lang.Object, T15 extends java.lang.Object, T16 extends java.lang.Object, T17 extends java.lang.Object, T18 extends java.lang.Object, T19 extends java.lang.Object, T20 extends java.lang.Object, T21 extends java.lang.Object, T22 extends java.lang.Object, T23 extends java.lang.Object, R extends java.lang.Object>Flow<R> combine(@org.jetbrains.annotations.NotNull()
|
||||
Flow<T1> flow, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T2> flow2, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T3> flow3, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T4> flow4, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T5> flow5, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T6> flow6, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T7> flow7, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T8> flow8, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T9> flow9, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T10> flow10, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T11> flow11, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T12> flow12, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T13> flow13, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T14> flow14, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T15> flow15, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T16> flow16, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T17> flow17, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T18> flow18, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T19> flow19, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T20> flow20, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T21> flow21, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T22> flow22, @org.jetbrains.annotations.NotNull()
|
||||
Flow<T23> flow23, @org.jetbrains.annotations.NotNull()
|
||||
kotlin.jvm.functions.FunctionN<? extends java.lang.Object> transform) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+6
@@ -631,6 +631,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/suspendFunctionSupertype.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunctionWithBigArity.kt")
|
||||
public void testSuspendFunctionWithBigArity() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/suspendFunctionWithBigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
|
||||
+6
@@ -631,6 +631,12 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/suspendFunctionSupertype.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("suspendFunctionWithBigArity.kt")
|
||||
public void testSuspendFunctionWithBigArity() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/suspendFunctionWithBigArity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user