Added support of callable references on suspend functions
This commit is contained in:
+3
@@ -37,6 +37,8 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
|
||||
|
||||
fun getKFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KFunction$n")
|
||||
|
||||
fun getKSuspendFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KSuspendFunction$n")
|
||||
|
||||
val kProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
@@ -44,6 +46,7 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
|
||||
val kTypeProjection: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
|
||||
val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
|
||||
val kSuspendFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
|
||||
val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope)
|
||||
val kProperty1Impl: ClassDescriptor by ClassLookup(internalScope)
|
||||
val kProperty2Impl: ClassDescriptor by ClassLookup(internalScope)
|
||||
|
||||
+5
@@ -385,6 +385,7 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
||||
val refClass = symbolTable.referenceClass(context.getKonanInternalClass("Ref"))
|
||||
|
||||
val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl)
|
||||
val kSuspendFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kSuspendFunctionImpl)
|
||||
|
||||
val kMutableProperty0 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0)
|
||||
val kMutableProperty1 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1)
|
||||
@@ -486,6 +487,10 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
||||
val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS)
|
||||
.map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) }
|
||||
|
||||
// Since KSuspendFunctionN inherits Function{N+1} and we only have 0..22 range, skip the last one for now.
|
||||
val kSuspendFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS - 1)
|
||||
.map { symbolTable.referenceClass(context.reflectionTypes.getKSuspendFunction(it)) }
|
||||
|
||||
fun getKFunctionType(returnType: IrType, parameterTypes: List<IrType>): IrType {
|
||||
val kFunctionClassSymbol = kFunctions[parameterTypes.size]
|
||||
return kFunctionClassSymbol.typeWith(parameterTypes + returnType)
|
||||
|
||||
-23
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.ir
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
@@ -46,9 +44,6 @@ val IrTypeParameterSymbol.defaultType: IrType get() = IrSimpleTypeImpl(
|
||||
|
||||
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
|
||||
|
||||
fun IrType.makeNullableAsSpecified(nullable: Boolean): IrType =
|
||||
if (nullable) this.makeNullable() else this.makeNotNull()
|
||||
|
||||
fun IrType.containsNull(): Boolean = if (this is IrSimpleType) {
|
||||
if (this.hasQuestionMark) {
|
||||
true
|
||||
@@ -67,21 +62,3 @@ fun IrType.containsNull(): Boolean = if (this is IrSimpleType) {
|
||||
// TODO: get rid of these:
|
||||
fun IrType.isSubtypeOf(other: KotlinType): Boolean = this.toKotlinType().isSubtypeOf(other)
|
||||
fun IrType.isSubtypeOf(other: IrType): Boolean = this.isSubtypeOf(other.toKotlinType())
|
||||
|
||||
val IrType.isFunctionOrKFunctionType: Boolean
|
||||
get() = when (this) {
|
||||
is IrSimpleType -> {
|
||||
val kind = classifier.descriptor.getFunctionalClassKind()
|
||||
kind == FunctionClassDescriptor.Kind.Function || kind == FunctionClassDescriptor.Kind.KFunction
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
internal tailrec fun IrType.getErasedTypeClass(): IrClassSymbol {
|
||||
val classifier = this.classifierOrFail
|
||||
return when (classifier) {
|
||||
is IrClassSymbol -> classifier
|
||||
is IrTypeParameterSymbol -> classifier.owner.superTypes.first().getErasedTypeClass()
|
||||
else -> error(classifier)
|
||||
}
|
||||
}
|
||||
|
||||
+53
-39
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.ir.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -26,6 +25,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
@@ -103,7 +103,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
break
|
||||
}
|
||||
|
||||
if (!expression.type.isFunctionOrKFunctionType) {
|
||||
if (!expression.type.isFunction() && !expression.type.isKFunction()
|
||||
&& !expression.type.isKSuspendFunction()) {
|
||||
// Not a subject of this lowering.
|
||||
return expression
|
||||
}
|
||||
@@ -131,9 +132,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
private val symbols = context.ir.symbols
|
||||
private val irBuiltIns = context.irBuiltIns
|
||||
|
||||
private val continuationClassDescriptor = symbols.continuationClassDescriptor
|
||||
|
||||
private val getContinuationSymbol = symbols.getContinuation
|
||||
private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol
|
||||
|
||||
private inner class FunctionReferenceBuilder(val parent: IrDeclarationParent,
|
||||
val functionReference: IrFunctionReference) {
|
||||
@@ -183,48 +183,58 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
)
|
||||
}
|
||||
|
||||
private val kFunctionImplSymbol = symbols.kFunctionImpl
|
||||
private fun IrClass.getInvokeFunction() = simpleFunctions().single { it.name.asString() == "invoke" }
|
||||
|
||||
private val kFunctionImplSymbol = symbols.kFunctionImpl
|
||||
private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single()
|
||||
private val kSuspendFunctionImplSymbol = symbols.kSuspendFunctionImpl
|
||||
private val kSuspendFunctionImplConstructorSymbol = kSuspendFunctionImplSymbol.constructors.single()
|
||||
|
||||
val isKFunction = functionReference.type.isKFunction()
|
||||
val isKSuspendFunction = functionReference.type.isKSuspendFunction()
|
||||
|
||||
fun build(): BuiltFunctionReference {
|
||||
|
||||
val superClassType = if (isKFunction) {
|
||||
kFunctionImplSymbol.typeWith(referencedFunction.returnType)
|
||||
} else {
|
||||
irBuiltIns.anyType
|
||||
}
|
||||
|
||||
val superTypes = mutableListOf(superClassType)
|
||||
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
|
||||
val functionIrClass = if (isKFunction) {
|
||||
symbols.kFunctions[numberOfParameters].owner
|
||||
} else {
|
||||
symbols.functions[numberOfParameters].owner
|
||||
}
|
||||
|
||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
val functionClassTypeParameters = functionParameterTypes + referencedFunction.returnType
|
||||
superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters)
|
||||
|
||||
var suspendFunctionIrClass: IrClass? = null
|
||||
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
|
||||
if (lastParameterType != null && lastParameterType.classifierOrNull?.descriptor == continuationClassDescriptor) {
|
||||
lastParameterType as IrSimpleType
|
||||
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||
suspendFunctionIrClass = symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
|
||||
superTypes += suspendFunctionIrClass.symbol.typeWith(suspendFunctionClassTypeParameters)
|
||||
val superTypes = mutableListOf<IrType>()
|
||||
val functionClass: IrClass
|
||||
val suspendFunctionClass: IrClass?
|
||||
if (isKSuspendFunction) {
|
||||
superTypes += kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
|
||||
functionClass = symbols.functions[numberOfParameters + 1].owner
|
||||
val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType)
|
||||
superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType)
|
||||
suspendFunctionClass = symbols.kSuspendFunctions[numberOfParameters].owner
|
||||
superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
|
||||
}
|
||||
else {
|
||||
superTypes += if (isKFunction)
|
||||
kFunctionImplSymbol.typeWith(referencedFunction.returnType)
|
||||
else
|
||||
irBuiltIns.anyType
|
||||
functionClass = (if (isKFunction) symbols.kFunctions else symbols.functions)[numberOfParameters].owner
|
||||
superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
|
||||
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
|
||||
if (lastParameterType?.classifierOrNull != continuationClassSymbol)
|
||||
suspendFunctionClass = null
|
||||
else {
|
||||
lastParameterType as IrSimpleType
|
||||
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||
suspendFunctionClass = symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
|
||||
superTypes += suspendFunctionClass.symbol.typeWith(suspendFunctionClassTypeParameters)
|
||||
}
|
||||
}
|
||||
|
||||
val constructor = buildConstructor()
|
||||
buildInvokeMethod(functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" })
|
||||
suspendFunctionIrClass?.let { buildInvokeMethod(it.simpleFunctions().single { it.name.asString() == "invoke" }) }
|
||||
if (!isKSuspendFunction)
|
||||
buildInvokeMethod(functionClass.getInvokeFunction())
|
||||
suspendFunctionClass?.let {
|
||||
val invokeMethod = buildInvokeMethod(it.getInvokeFunction())
|
||||
if (isKSuspendFunction)
|
||||
invokeMethod.overriddenSymbols += functionClass.getInvokeFunction().symbol
|
||||
}
|
||||
|
||||
functionReferenceClass.superTypes += superTypes
|
||||
functionReferenceClass.addFakeOverrides()
|
||||
@@ -254,9 +264,13 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody {
|
||||
if (!isKFunction)
|
||||
+irDelegatingConstructorCall(irBuiltIns.anyClass.owner.constructors.single())
|
||||
else +irDelegatingConstructorCall(kFunctionImplConstructorSymbol.owner).apply {
|
||||
val superConstructor = when {
|
||||
isKFunction -> kFunctionImplConstructorSymbol.owner
|
||||
isKSuspendFunction -> kSuspendFunctionImplConstructorSymbol.owner
|
||||
else -> irBuiltIns.anyClass.owner.constructors.single()
|
||||
}
|
||||
+irDelegatingConstructorCall(superConstructor).apply {
|
||||
if (!isKFunction && !isKSuspendFunction) return@apply
|
||||
// TODO: Remove as soon as IR declarations have their originalDescriptor.
|
||||
val name = (referencedFunction.descriptor as? WrappedSimpleFunctionDescriptor)?.originalDescriptor?.name
|
||||
?: referencedFunction.name
|
||||
@@ -302,7 +316,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
superFunction.valueParameters.mapIndexedTo(valueParameters) { index, parameter ->
|
||||
parameter.copyTo(this, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index,
|
||||
parameter.copyTo(function, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index,
|
||||
type = parameter.type.substitute(typeArgumentsMap))
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,6 @@ open class KFunctionImpl<out R>(override val name: String, val fqName: String, v
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return (if (name == "<init>") "constructor" else "function " + name) + " (Kotlin reflection is not available)"
|
||||
return "${if (name == "<init>") "constructor" else "function " + name}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package kotlin.native.internal
|
||||
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.KFunction
|
||||
|
||||
@FixmeReflection
|
||||
internal abstract class KSuspendFunctionImpl<out R>(
|
||||
override val name: String, val fqName: String,
|
||||
val bound: Boolean, val receiver: Any?,
|
||||
override val returnType: KType
|
||||
): KFunction<R> {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is KSuspendFunctionImpl<*>) return false
|
||||
return fqName == other.fqName && bound == other.bound && receiver == other.receiver
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return (fqName.hashCode() * 31 + if (bound) 1 else 0) * 31 + receiver.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "suspend function $name"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
@file:Suppress("SUPERTYPE_IS_SUSPEND_FUNCTION_TYPE")
|
||||
|
||||
package kotlin.reflect
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
// (0..22).joinToString("\n") { i -> "interface KSuspendFunction$i<${(1..i).joinToString("") { j -> "in P$j, " }}out R> : SuspendFunction$i<${(1..i).joinToString("") { j -> "P$j, " }}R>, KFunction<R>\n" }
|
||||
|
||||
interface KSuspendFunction0<out R> : SuspendFunction0<R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction1<in P1, out R> : SuspendFunction1<P1, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction2<in P1, in P2, out R> : SuspendFunction2<P1, P2, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction3<in P1, in P2, in P3, out R> : SuspendFunction3<P1, P2, P3, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction4<in P1, in P2, in P3, in P4, out R> : SuspendFunction4<P1, P2, P3, P4, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction5<in P1, in P2, in P3, in P4, in P5, out R> : SuspendFunction5<P1, P2, P3, P4, P5, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction6<in P1, in P2, in P3, in P4, in P5, in P6, out R> : SuspendFunction6<P1, P2, P3, P4, P5, P6, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction7<in P1, in P2, in P3, in P4, in P5, in P6, in P7, out R> : SuspendFunction7<P1, P2, P3, P4, P5, P6, P7, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction8<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, out R> : SuspendFunction8<P1, P2, P3, P4, P5, P6, P7, P8, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction9<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, out R> : SuspendFunction9<P1, P2, P3, P4, P5, P6, P7, P8, P9, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction10<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, out R> : SuspendFunction10<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction11<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, out R> : SuspendFunction11<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction12<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, out R> : SuspendFunction12<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction13<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, out R> : SuspendFunction13<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction14<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, out R> : SuspendFunction14<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction15<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, out R> : SuspendFunction15<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction16<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, out R> : SuspendFunction16<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction17<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, out R> : SuspendFunction17<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction18<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, out R> : SuspendFunction18<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction19<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, out R> : SuspendFunction19<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction20<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, out R> : SuspendFunction20<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, R>, KFunction<R>
|
||||
|
||||
interface KSuspendFunction21<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, out R> : SuspendFunction21<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, R>, KFunction<R>
|
||||
|
||||
// Comment for now. The reason: https://github.com/JetBrains/kotlin/blob/ad1b795a69925e6ee8c79cbbd05cce8cd27a6704/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt#L555
|
||||
//interface KSuspendFunction22<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : SuspendFunction22<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R>, KFunction<R>
|
||||
Reference in New Issue
Block a user