Implement correct is check for SuspendFunction

Let callable references implement SuspendFunction
Do not generate CHECKCAST SuspendFunction when LV is 1.2

 #KT-25825: Fixed
This commit is contained in:
Ilmir Usmanov
2018-08-10 20:22:06 +03:00
parent 9eb612a605
commit 4a7703ed66
13 changed files with 202 additions and 40 deletions
@@ -4658,7 +4658,7 @@ The "returned" value of try expression with no finally is either the last expres
return null; return null;
} }
CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type); CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type, state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
return null; return null;
}); });
} }
@@ -57,6 +57,12 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
createCoroutineSuperClass("RestrictedSuspendLambda") createCoroutineSuperClass("RestrictedSuspendLambda")
} }
private val suspendFunctionInterface by lazy {
if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, "SuspendFunction", ClassKind.INTERFACE)
else null
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor { private fun createCoroutineSuperClass(className: String): ClassDescriptor {
return if (languageVersionSettings.isReleaseCoroutines()) return if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, className) createClass(kotlinCoroutinesJvmInternalPackage, className)
@@ -145,7 +151,8 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
referencedFunction.isSuspend referencedFunction.isSuspend
) )
return listOf(functionReference.defaultType, functionType) val suspendFunctionType = if (referencedFunction.isSuspend) suspendFunctionInterface?.defaultType else null
return listOfNotNull(functionReference.defaultType, functionType, suspendFunctionType)
} }
fun getSupertypeForPropertyReference(descriptor: VariableDescriptorWithAccessors, isMutable: Boolean, isBound: Boolean): KotlinType { fun getSupertypeForPropertyReference(descriptor: VariableDescriptorWithAccessors, isMutable: Boolean, isBound: Boolean): KotlinType {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -59,10 +59,12 @@ import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
import java.util.* import java.util.*
@JvmOverloads
fun generateIsCheck( fun generateIsCheck(
v: InstructionAdapter, v: InstructionAdapter,
kotlinType: KotlinType, kotlinType: KotlinType,
asmType: Type asmType: Type,
isReleaseCoroutines: Boolean = false
) { ) {
if (TypeUtils.isNullableType(kotlinType)) { if (TypeUtils.isNullableType(kotlinType)) {
val nope = Label() val nope = Label()
@@ -73,7 +75,7 @@ fun generateIsCheck(
ifnull(nope) ifnull(nope)
TypeIntrinsics.instanceOf(this, kotlinType, asmType) TypeIntrinsics.instanceOf(this, kotlinType, asmType, isReleaseCoroutines)
goTo(end) goTo(end)
@@ -84,15 +86,17 @@ fun generateIsCheck(
mark(end) mark(end)
} }
} else { } else {
TypeIntrinsics.instanceOf(v, kotlinType, asmType) TypeIntrinsics.instanceOf(v, kotlinType, asmType, isReleaseCoroutines)
} }
} }
@JvmOverloads
fun generateAsCast( fun generateAsCast(
v: InstructionAdapter, v: InstructionAdapter,
kotlinType: KotlinType, kotlinType: KotlinType,
asmType: Type, asmType: Type,
isSafe: Boolean isSafe: Boolean,
isReleaseCoroutines: Boolean = false
) { ) {
if (!isSafe) { if (!isSafe) {
if (!TypeUtils.isNullableType(kotlinType)) { if (!TypeUtils.isNullableType(kotlinType)) {
@@ -101,7 +105,7 @@ fun generateAsCast(
} else { } else {
with(v) { with(v) {
dup() dup()
TypeIntrinsics.instanceOf(v, kotlinType, asmType) TypeIntrinsics.instanceOf(v, kotlinType, asmType, isReleaseCoroutines)
val ok = Label() val ok = Label()
ifne(ok) ifne(ok)
pop() pop()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* * that can be found in the license/LICENSE.txt file.
* 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 org.jetbrains.kotlin.codegen.intrinsics package org.jetbrains.kotlin.codegen.intrinsics
@@ -19,8 +8,10 @@ package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -28,7 +19,8 @@ import org.jetbrains.org.objectweb.asm.tree.*
import kotlin.text.Regex import kotlin.text.Regex
object TypeIntrinsics { object TypeIntrinsics {
@JvmStatic fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type) { @JvmStatic
fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type, isReleaseCoroutines: Boolean) {
val functionTypeArity = getFunctionTypeArity(jetType) val functionTypeArity = getFunctionTypeArity(jetType)
if (functionTypeArity >= 0) { if (functionTypeArity >= 0) {
v.iconst(functionTypeArity) v.iconst(functionTypeArity)
@@ -36,6 +28,30 @@ object TypeIntrinsics {
return return
} }
if (isReleaseCoroutines) {
val suspendFunctionTypeArity = getSuspendFunctionTypeArity(jetType)
if (suspendFunctionTypeArity >= 0) {
val notSuspendLambda = Label()
val end = Label()
with(v) {
dup()
instanceOf(AsmTypes.SUSPEND_FUNCTION_TYPE)
ifeq(notSuspendLambda)
iconst(suspendFunctionTypeArity + 1)
typeIntrinsic(IS_FUNCTON_OF_ARITY_METHOD_NAME, IS_FUNCTON_OF_ARITY_DESCRIPTOR)
goTo(end)
mark(notSuspendLambda)
pop()
iconst(0)
mark(end)
}
return
}
}
val isMutableCollectionMethodName = getIsMutableCollectionMethodName(jetType) val isMutableCollectionMethodName = getIsMutableCollectionMethodName(jetType)
if (isMutableCollectionMethodName != null) { if (isMutableCollectionMethodName != null) {
v.typeIntrinsic(isMutableCollectionMethodName, IS_MUTABLE_COLLECTION_METHOD_DESCRIPTOR) v.typeIntrinsic(isMutableCollectionMethodName, IS_MUTABLE_COLLECTION_METHOD_DESCRIPTOR)
@@ -148,16 +164,26 @@ object TypeIntrinsics {
} }
private val KOTLIN_FUNCTION_INTERFACE_REGEX = Regex("^kotlin\\.Function([0-9]+)$") private val KOTLIN_FUNCTION_INTERFACE_REGEX = Regex("^kotlin\\.Function([0-9]+)$")
// TODO: move to correct package
private val KOTLIN_SUSPEND_FUNCTION_INTERFACE_REGEX = Regex("^kotlin\\.SuspendFunction([0-9]+)$")
/** /**
* @return function type arity (non-negative), or -1 if the given type is not a function type * @return function type arity (non-negative), or -1 if the given type is not a function type
*/ */
private fun getFunctionTypeArity(jetType: KotlinType): Int { private fun getFunctionTypeArity(kotlinType: KotlinType): Int = getFunctionTypeArityByRegex(kotlinType, KOTLIN_FUNCTION_INTERFACE_REGEX)
val classFqName = getClassFqName(jetType) ?: return -1
val match = KOTLIN_FUNCTION_INTERFACE_REGEX.find(classFqName.asString()) ?: return -1 private fun getFunctionTypeArityByRegex(kotlinType: KotlinType, regex: Regex): Int {
val classFqName = getClassFqName(kotlinType) ?: return -1
val match = regex.find(classFqName.asString()) ?: return -1
return Integer.valueOf(match.groups[1]!!.value) return Integer.valueOf(match.groups[1]!!.value)
} }
/**
* @return function type arity (non-negative, counting continuation), or -1 if the given type is not a function type
*/
private fun getSuspendFunctionTypeArity(kotlinType: KotlinType): Int =
getFunctionTypeArityByRegex(kotlinType, KOTLIN_SUSPEND_FUNCTION_INTERFACE_REGEX)
private fun typeIntrinsicNode(methodName: String, methodDescriptor: String): MethodInsnNode = private fun typeIntrinsicNode(methodName: String, methodDescriptor: String): MethodInsnNode =
MethodInsnNode(Opcodes.INVOKESTATIC, INTRINSICS_CLASS, methodName, methodDescriptor, false) MethodInsnNode(Opcodes.INVOKESTATIC, INTRINSICS_CLASS, methodName, methodDescriptor, false)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* * that can be found in the license/LICENSE.txt file.
* 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 org.jetbrains.kotlin.resolve.jvm; package org.jetbrains.kotlin.resolve.jvm;
@@ -74,6 +63,8 @@ public class AsmTypes {
public static final Type K_MUTABLE_PROPERTY1_TYPE = reflect("KMutableProperty1"); public static final Type K_MUTABLE_PROPERTY1_TYPE = reflect("KMutableProperty1");
public static final Type K_MUTABLE_PROPERTY2_TYPE = reflect("KMutableProperty2"); public static final Type K_MUTABLE_PROPERTY2_TYPE = reflect("KMutableProperty2");
public static final Type SUSPEND_FUNCTION_TYPE = Type.getObjectType("kotlin/coroutines/jvm/internal/SuspendFunction");
public static final String REFLECTION = "kotlin/jvm/internal/Reflection"; public static final String REFLECTION = "kotlin/jvm/internal/Reflection";
public static final String REF_TYPE_PREFIX = "kotlin/jvm/internal/Ref$"; public static final String REF_TYPE_PREFIX = "kotlin/jvm/internal/Ref$";
@@ -0,0 +1,19 @@
// IGNORE_BACKEND: JS_IR, JS
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// LANGUAGE_VERSION: 1.2
import helpers.*
import kotlin.coroutines.*
val lambda1 = { x: Any -> } as (Any) -> Unit
val suspendLambda0: suspend () -> Unit = {}
fun box(): String {
assert(lambda1 is SuspendFunction0<*>) { "Failed: lambda1 !is SuspendFunction0<*>" }
assert(suspendLambda0 is Function1<*, *>) { "Failed: suspendLambda0 is Function1<*, *>" }
assert(suspendLambda0 is SuspendFunction0<*>) { "Failed: suspendLambda0 is SuspendFunction0<*>" }
return "OK"
}
@@ -0,0 +1,61 @@
// IGNORE_BACKEND: JS_IR, JS
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// LANGUAGE_VERSION: 1.3
import helpers.*
import kotlin.coroutines.*
fun fn1(x: Any) {}
suspend fun suspendFn0() {}
val lambda1 = { x: Any -> } as (Any) -> Unit
val suspendLambda0: suspend () -> Unit = {}
fun Any.extFun(a: Any) {}
suspend fun Any.suspendExtFun() {}
class A {
fun foo(a: Any) {}
suspend fun suspendFoo() {}
}
fun box(): String {
val f1 = ::fn1 as Any
val sf0 = ::suspendFn0 as Any
val ef = Any::extFun as Any
val sef = Any::suspendExtFun as Any
val afoo = A::foo
val safoo = A::suspendFoo
fun local1(x: Any) {}
suspend fun suspendLocal0() {}
val localFun1 = ::local1 as Any
val suspendLocalFun0 = ::suspendLocal0 as Any
assert(f1 !is SuspendFunction0<*>) { "Failed: f1 !is SuspendFunction0<*>" }
assert(sf0 is SuspendFunction0<*>) { "Failed: f1 is SuspendFunction0<*>" }
assert(sf0 is Function1<*, *>) { "Failed: suspendF0 is Function1<*, *>" }
assert(lambda1 !is SuspendFunction0<*>) { "Failed: lambda1 !is SuspendFunction0<*>" }
assert(suspendLambda0 is Function1<*, *>) { "Failed: suspendLambda0 is Function1<*, *>" }
assert(suspendLambda0 is SuspendFunction0<*>) { "Failed: suspendLambda0 is SuspendFunction0<*>" }
assert(localFun1 !is SuspendFunction0<*>) { "Failed: localFun1 !is SuspendFunction0<*, *>" }
assert(suspendLocalFun0 is Function1<*, *>) { "Failed: suspendLocalFun0 is Function1<*, *>" }
assert(suspendLocalFun0 is SuspendFunction0<*>) { "Failed: suspendLocalFun0 is SuspendFunction0<*>" }
assert(ef !is SuspendFunction1<*, *>) { "Failed: ef !is SuspendFunction1<*, *>" }
assert(sef is SuspendFunction1<*, *>) { "Failed: sef is SuspendFunction1<*, *>" }
assert(sef is Function2<*, *, *>) { "Failed: sef is Function2<*, *, *>" }
assert(afoo !is SuspendFunction1<*, *>) { "afoo !is SuspendFunction1<*, *>" }
assert(safoo is Function2<*, *, *>) { "safoo is Function2<*, *, *>" }
assert(safoo is SuspendFunction1<*, *>) { "asfoo is SuspendFunction1<*, *>" }
return "OK"
}
@@ -6505,6 +6505,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines");
} }
@TestMetadata("suspendFunction12.kt")
public void testSuspendFunction12() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunction12.kt");
}
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionIsAs.kt");
}
@TestMetadata("suspendOperatorPlusAssign.kt") @TestMetadata("suspendOperatorPlusAssign.kt")
public void testSuspendOperatorPlusAssign_1_2() throws Exception { public void testSuspendOperatorPlusAssign_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental");
@@ -6505,6 +6505,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines");
} }
@TestMetadata("suspendFunction12.kt")
public void testSuspendFunction12() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunction12.kt");
}
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionIsAs.kt");
}
@TestMetadata("suspendOperatorPlusAssign.kt") @TestMetadata("suspendOperatorPlusAssign.kt")
public void testSuspendOperatorPlusAssign_1_2() throws Exception { public void testSuspendOperatorPlusAssign_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental");
@@ -6505,6 +6505,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines");
} }
@TestMetadata("suspendFunction12.kt")
public void testSuspendFunction12() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunction12.kt");
}
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionIsAs.kt");
}
@TestMetadata("suspendOperatorPlusAssign.kt") @TestMetadata("suspendOperatorPlusAssign.kt")
public void testSuspendOperatorPlusAssign_1_2() throws Exception { public void testSuspendOperatorPlusAssign_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental");
@@ -5665,6 +5665,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines.experimental");
} }
@TestMetadata("suspendFunction12.kt")
public void testSuspendFunction12() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunction12.kt");
}
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionIsAs.kt");
}
@TestMetadata("suspendOperatorPlusAssign.kt") @TestMetadata("suspendOperatorPlusAssign.kt")
public void testSuspendOperatorPlusAssign_1_2() throws Exception { public void testSuspendOperatorPlusAssign_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental");
@@ -6220,6 +6220,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendDestructuringInLambdas.kt", "kotlin.coroutines");
} }
@TestMetadata("suspendFunction12.kt")
public void testSuspendFunction12() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunction12.kt");
}
@TestMetadata("suspendFunctionIsAs.kt")
public void testSuspendFunctionIsAs() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/suspendFunctionIsAs.kt");
}
@TestMetadata("suspendOperatorPlusAssign.kt") @TestMetadata("suspendOperatorPlusAssign.kt")
public void testSuspendOperatorPlusAssign_1_2() throws Exception { public void testSuspendOperatorPlusAssign_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt", "kotlin.coroutines.experimental");
@@ -125,12 +125,16 @@ internal object CompletedContinuation : Continuation<Any?> {
override fun toString(): String = "This continuation is already complete" override fun toString(): String = "This continuation is already complete"
} }
@SinceKotlin("1.3")
// To distinguish suspend function types from ordinary function types all suspend function type shall implement this interface
internal interface SuspendFunction
@SinceKotlin("1.3") @SinceKotlin("1.3")
// Restricted suspension lambdas inherit from this class // Restricted suspension lambdas inherit from this class
internal abstract class RestrictedSuspendLambda( internal abstract class RestrictedSuspendLambda(
private val arity: Int, private val arity: Int,
completion: Continuation<Any?>? completion: Continuation<Any?>?
) : RestrictedContinuationImpl(completion), FunctionBase { ) : RestrictedContinuationImpl(completion), FunctionBase, SuspendFunction {
constructor(arity: Int) : this(arity, null) constructor(arity: Int) : this(arity, null)
public override fun getArity(): Int = arity public override fun getArity(): Int = arity
@@ -147,7 +151,7 @@ internal abstract class RestrictedSuspendLambda(
internal abstract class SuspendLambda( internal abstract class SuspendLambda(
private val arity: Int, private val arity: Int,
completion: Continuation<Any?>? completion: Continuation<Any?>?
) : ContinuationImpl(completion), FunctionBase { ) : ContinuationImpl(completion), FunctionBase, SuspendFunction {
constructor(arity: Int) : this(arity, null) constructor(arity: Int) : this(arity, null)
public override fun getArity(): Int = arity public override fun getArity(): Int = arity