diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 7af44a421be..8e8e2b1ea69 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.isExported import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.getFunctionalClassKind import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.builtins.isSuspendFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName @@ -159,6 +160,15 @@ internal val FunctionDescriptor.isFunctionInvoke: Boolean this.isOperator && this.name == OperatorNameConventions.INVOKE } +internal val FunctionDescriptor.isSuspendFunctionInvoke: Boolean + get() { + val dispatchReceiver = dispatchReceiverParameter + ?: return false + + return dispatchReceiver.type.isSuspendFunctionType && + this.isOperator && this.name == OperatorNameConventions.INVOKE + } + internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit() internal val T.allOverriddenDescriptors: List diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt index 009f2a2bd64..0276e1398f4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.replace import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNotNullable @@ -60,6 +61,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai else null } transformCallableReferencesToSuspendLambdas(irDeclarationContainer) + transformCallsToExtensionSuspendFunctions(irDeclarationContainer) } private fun markSuspendLambdas(irDeclarationContainer: IrDeclarationContainer) { @@ -107,6 +109,37 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } } + private fun transformCallsToExtensionSuspendFunctions(irDeclarationContainer: IrDeclarationContainer) { + irDeclarationContainer.declarations.forEach { + it.transformChildrenVoid(object: IrElementTransformerVoid() { + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + val descriptor = expression.descriptor as? FunctionDescriptor + ?: return expression + + if (!descriptor.isSuspendFunctionInvoke || descriptor.extensionReceiverParameter == null) + return expression + + val invokeFunctionDescriptor = descriptor.dispatchReceiverParameter!!.type.memberScope + .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single() + return IrCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + descriptor = invokeFunctionDescriptor + ).apply { + dispatchReceiver = expression.dispatchReceiver + putValueArgument(0, expression.extensionReceiver) + invokeFunctionDescriptor.valueParameters.drop(1).forEach { + putValueArgument(it.index, expression.getValueArgument(it.index - 1)) + } + } + } + }) + } + } + private enum class SuspendFunctionKind { NO_SUSPEND_CALLS, DELEGATING, @@ -191,6 +224,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private val getContinuationDescriptor = context.builtIns.getKonanInternalFunctions("getContinuation").single() private val returnIfSuspendedDescriptor = context.builtIns.getKonanInternalFunctions("returnIfSuspended").single() + private fun KotlinType.replace(types: List) = this.replace(types.map(::TypeProjectionImpl)) + private fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor { val typeSubstitutor = TypeSubstitutor.create( typeParameters @@ -272,8 +307,25 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private var coroutineId = 0 + private val COROUTINES_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental")) + private val COROUTINES_INTRINSICS_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental", "intrinsics")) + private val KOTLIN_FQ_NAME = FqName("kotlin") + + private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope + private val coroutinesIntrinsicsScope = context.irModule!!.descriptor.getPackage(COROUTINES_INTRINSICS_FQ_NAME).memberScope + private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope + + private val continuationClassDescriptor = coroutinesScope + .getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + private val COROUTINE_SUSPENDED = coroutinesIntrinsicsScope + .getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND).first() + private inner class CoroutineBuilder(val irFunction: IrFunction, val callableReference: IrCallableReference?) { + private val functionParameters = irFunction.descriptor.explicitParameters + private val boundFunctionParameters = callableReference?.getArguments()?.map { it.first } + private val unboundFunctionParameters = boundFunctionParameters?.let { functionParameters - it } + private var tempIndex = 0 private var suspensionPointIdIndex = 0 private lateinit var suspendResult: VariableDescriptor @@ -283,66 +335,87 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private lateinit var argumentToPropertiesMap: Map private val coroutineMembers = mutableListOf() - private val COROUTINES_INTRINSICS_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental", "intrinsics")) - private val coroutinesIntrinsicsScope = context.irModule!!.descriptor.getPackage(COROUTINES_INTRINSICS_FQ_NAME).memberScope - private val coroutineImplClassDescriptor = context.builtIns.getKonanInternalClass("CoroutineImpl") private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) .single { it.valueParameters.size == 1 } private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0] - private val COROUTINE_SUSPENDED = coroutinesIntrinsicsScope - .getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND).first() - fun build(): BuiltCoroutine { + val superTypes = mutableListOf(coroutineImplClassDescriptor.defaultType) + var suspendFunctionClassDescriptor: ClassDescriptor? = null + var functionClassDescriptor: ClassDescriptor? = null + if (unboundFunctionParameters != null) { + // Suspend lambda inherits SuspendFunction. + val numberOfParameters = unboundFunctionParameters.size + suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier( + Name.identifier("SuspendFunction$numberOfParameters"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + superTypes += suspendFunctionClassDescriptor.defaultType.replace( + unboundFunctionParameters.map { it.type } + irFunction.descriptor.returnType!! + ) + + functionClassDescriptor = kotlinPackageScope.getContributedClassifier( + Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!)) + superTypes += functionClassDescriptor.defaultType.replace( + unboundFunctionParameters.map { it.type } // Main arguments, + + continuationType // and continuation. + + context.builtIns.nullableAnyType) // Return type + } coroutineClassDescriptor = ClassDescriptorImpl( /* containingDeclaration = */ irFunction.descriptor.containingDeclaration, /* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName, /* modality = */ Modality.FINAL, /* kind = */ ClassKind.CLASS, - /* superTypes = */ listOf(coroutineImplClassDescriptor.defaultType), + /* superTypes = */ superTypes, /* source = */ SourceElement.NO_SOURCE, /* isExternal = */ false ) - val overriddenMap = mutableMapOf() + val overriddenMap = mutableMapOf() val constructors = mutableSetOf() val coroutineConstructorBuilder = createConstructorBuilder() constructors.add(coroutineConstructorBuilder.descriptor) - var coroutineFactoryConstructorBuilder: DescriptorWithIrBuilder? = null - var createMethodBuilder: DescriptorWithIrBuilder? = null - if (callableReference != null) { - // Suspend lambda - create factory methods. - val boundArgs = callableReference.getArguments() - val boundParams = boundArgs.map { it.first } - - val allParams = irFunction.descriptor.explicitParameters - val unboundParams = allParams - boundParams - - coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundParams) - constructors.add(coroutineFactoryConstructorBuilder.descriptor) - val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) - .atMostOne { it.valueParameters.size == unboundParams.size + 1 } - createMethodBuilder = createCreateMethodBuilder(unboundParams, createFunctionDescriptor, coroutineConstructorBuilder.descriptor) - - if (createFunctionDescriptor != null) - overriddenMap += createFunctionDescriptor to createMethodBuilder.descriptor - } - val doResumeFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single() - val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunctionDescriptor) - overriddenMap += doResumeFunctionDescriptor to doResumeMethodBuilder.descriptor - val contributedDescriptors = coroutineImplClassDescriptor.unsubstitutedMemberScope + var coroutineFactoryConstructorBuilder: DescriptorWithIrBuilder? = null + var createMethodBuilder: DescriptorWithIrBuilder? = null + var invokeMethodBuilder: DescriptorWithIrBuilder? = null + if (callableReference != null) { + // Suspend lambda - create factory methods. + coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!) + constructors.add(coroutineFactoryConstructorBuilder.descriptor) + + val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) + .atMostOne { it.valueParameters.size == unboundFunctionParameters!!.size + 1 } + createMethodBuilder = createCreateMethodBuilder( + unboundArgs = unboundFunctionParameters!!, + superFunctionDescriptor = createFunctionDescriptor, + coroutineConstructorDescriptor = coroutineConstructorBuilder.descriptor) + if (createFunctionDescriptor != null) + overriddenMap += createFunctionDescriptor to createMethodBuilder.descriptor + + val invokeFunctionDescriptor = functionClassDescriptor!!.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single() + val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor!!.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single() + invokeMethodBuilder = createInvokeMethodBuilder( + suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor, + functionInvokeFunctionDescriptor = invokeFunctionDescriptor, + createFunctionDescriptor = createMethodBuilder.descriptor, + doResumeFunctionDescriptor = doResumeMethodBuilder.descriptor) + } + + val inheritedFromCoroutineImpl = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedDescriptors() .map { overriddenMap[it] ?: it.createFakeOverrideDescriptor(coroutineClassDescriptor) } - .filterNotNull() - .toList() + val contributedDescriptors = ( + inheritedFromCoroutineImpl + invokeMethodBuilder?.descriptor + ).filterNotNull().toList() coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null) coroutineConstructorBuilder.initialize() @@ -358,6 +431,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai coroutineMembers.add(it.ir) } + invokeMethodBuilder?.let { + it.initialize() + coroutineMembers.add(it.ir) + } + doResumeMethodBuilder.initialize() coroutineMembers.add(doResumeMethodBuilder.ir) @@ -369,10 +447,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai members = coroutineMembers ) return BuiltCoroutine( - coroutineClass = coroutineClass, + coroutineClass = coroutineClass, coroutineConstructorDescriptor = coroutineFactoryConstructorBuilder?.descriptor ?: coroutineConstructorBuilder.descriptor, - doResumeFunctionDescriptor = doResumeMethodBuilder.descriptor) + doResumeFunctionDescriptor = doResumeMethodBuilder.descriptor) } private fun createConstructorBuilder() @@ -380,7 +458,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single() private lateinit var constructorParameters: List - private lateinit var functionParameters: List override fun buildDescriptor(): ClassConstructorDescriptorImpl { return ClassConstructorDescriptorImpl.create( @@ -392,8 +469,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } override fun doInitialize() { - val functionDescriptor = irFunction.descriptor - functionParameters = functionDescriptor.explicitParameters constructorParameters = ( functionParameters + coroutineImplConstructorDescriptor.valueParameters[0] // completion. @@ -543,7 +618,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( irCall(coroutineConstructorDescriptor).apply { - val functionParameters = irFunction.descriptor.explicitParameters var unboundIndex = 0 val unboundArgsSet = unboundArgs.toSet() functionParameters.map { @@ -563,6 +637,69 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } } + private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor, + functionInvokeFunctionDescriptor: FunctionDescriptor, + createFunctionDescriptor: FunctionDescriptor, + doResumeFunctionDescriptor: FunctionDescriptor) + = object: DescriptorWithIrBuilder() { + + override fun buildDescriptor() = SimpleFunctionDescriptorImpl.create( + /* containingDeclaration = */ coroutineClassDescriptor, + /* annotations = */ Annotations.EMPTY, + /* name = */ Name.identifier("invoke"), + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* source = */ SourceElement.NO_SOURCE) + + override fun doInitialize() { + val valueParameters = createFunctionDescriptor.valueParameters + // Skip completion - invoke() already has it implicitly as a suspend function. + .take(createFunctionDescriptor.valueParameters.size - 1) + .map { it.copyAsValueParameter(this.descriptor, it.index) } + + this.descriptor.initialize( + /* receiverParameterType = */ null, + /* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter, + /* typeParameters = */ emptyList(), + /* unsubstitutedValueParameters = */ valueParameters, + /* unsubstitutedReturnType = */ irFunction.descriptor.returnType, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE).apply { + overriddenDescriptors += suspendFunctionInvokeFunctionDescriptor + overriddenDescriptors += functionInvokeFunctionDescriptor + isSuspend = true + } + } + + override fun buildIr(): IrFunction { + val startOffset = irFunction.startOffset + val endOffset = irFunction.endOffset + val ourDescriptor = this.descriptor + val irBuilder = context.createIrBuilder(this.descriptor, startOffset, endOffset) + return IrFunctionImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_COROUTINE_IMPL, + descriptor = this.descriptor).apply { + body = irBuilder.irBlockBody(startOffset, endOffset) { + +irReturn( + irCall(doResumeFunctionDescriptor).apply { + dispatchReceiver = irCall(createFunctionDescriptor).apply { + dispatchReceiver = irThis() + ourDescriptor.valueParameters.forEach { + putValueArgument(it.index, irGet(it)) + } + putValueArgument(ourDescriptor.valueParameters.size, + irCall(getContinuationDescriptor.substitute(ourDescriptor.returnType!!))) + } + putValueArgument(0, irUnit()) // value + putValueArgument(1, irNull()) // exception + } + ) + } + } + } + } + private fun createPropertyGetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType) = object: DescriptorWithIrBuilder() { diff --git a/runtime/src/main/kotlin/kotlin/SuspendFunction.kt b/runtime/src/main/kotlin/kotlin/SuspendFunction.kt new file mode 100644 index 00000000000..fe1818a7311 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/SuspendFunction.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin + +/** + * Represents a value of a functional type, such as a lambda, an anonymous function or a function reference. + * + * @param R return type of the function. + */ +@FixmeReflection +public interface SuspendFunction diff --git a/runtime/src/main/kotlin/kotlin/SuspendFunctions.kt b/runtime/src/main/kotlin/kotlin/SuspendFunctions.kt new file mode 100644 index 00000000000..b34b6cd5ad1 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/SuspendFunctions.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin + +// (0..22).joinToString("\n") { i -> "interface SuspendFunction$i<${(1..i).joinToString("") { j -> "in P$j, " }}out R> : SuspendFunction {\n operator suspend fun invoke(${(1..i).joinToString { j -> "p$j: P$j" }}): R\n}\n" } + +interface SuspendFunction0 : SuspendFunction { + operator suspend fun invoke(): R +} + +interface SuspendFunction1 : SuspendFunction { + operator suspend fun invoke(p1: P1): R +} + +interface SuspendFunction2 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2): R +} + +interface SuspendFunction3 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3): R +} + +interface SuspendFunction4 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4): R +} + +interface SuspendFunction5 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R +} + +interface SuspendFunction6 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R +} + +interface SuspendFunction7 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R +} + +interface SuspendFunction8 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R +} + +interface SuspendFunction9 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R +} + +interface SuspendFunction10 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R +} + +interface SuspendFunction11 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R +} + +interface SuspendFunction12 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R +} + +interface SuspendFunction13 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R +} + +interface SuspendFunction14 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R +} + +interface SuspendFunction15 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R +} + +interface SuspendFunction16 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R +} + +interface SuspendFunction17 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R +} + +interface SuspendFunction18 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R +} + +interface SuspendFunction19 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R +} + +interface SuspendFunction20 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R +} + +interface SuspendFunction21 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R +} + +interface SuspendFunction22 : SuspendFunction { + operator suspend fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R +}