diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 70037cfadb9..0da9a2ee212 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -13711,6 +13711,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testExtensionAlias() throws Exception { runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt"); } + + @Test + @TestMetadata("SuspendExtension.kt") + public void testSuspendExtension() throws Exception { + runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt"); + } } @Nested diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index c4ea60f4f85..2787ce4a395 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.serialization -import org.jetbrains.kotlin.builtins.functions.FunctionClassKind import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -28,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.varargElementType import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType +import org.jetbrains.kotlin.fir.resolve.inference.suspendFunctionTypeToFunctionTypeWithContinuation import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.sealedInheritors import org.jetbrains.kotlin.fir.serialization.constant.EnumValue @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.fir.serialization.constant.IntValue import org.jetbrains.kotlin.fir.serialization.constant.StringValue import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue import org.jetbrains.kotlin.fir.symbols.StandardClassIds -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef @@ -579,7 +578,9 @@ class FirElementSerializer private constructor( } is ConeClassLikeType -> { if (type.isSuspendFunctionType(session)) { - val runtimeFunctionType = transformSuspendFunctionToRuntimeFunctionType(type) + val runtimeFunctionType = type.suspendFunctionTypeToFunctionTypeWithContinuation( + session, CONTINUATION_INTERFACE_CLASS_ID + ) val functionType = typeProto(runtimeFunctionType) functionType.flags = Flags.getTypeFlags(true) return functionType @@ -658,23 +659,6 @@ class FirElementSerializer private constructor( } } - private fun transformSuspendFunctionToRuntimeFunctionType(type: ConeClassLikeType): ConeClassLikeType { - val suspendClassId = type.classId!! - val relativeClassName = suspendClassId.relativeClassName.asString() - val kind = - if (relativeClassName.startsWith("K")) FunctionClassKind.KFunction - else FunctionClassKind.Function - val runtimeClassId = ClassId(kind.packageFqName, Name.identifier(relativeClassName.replaceFirst("Suspend", ""))) - val continuationClassId = CONTINUATION_INTERFACE_CLASS_ID - return ConeClassLikeLookupTagImpl(runtimeClassId).constructClassType( - (type.typeArguments.toList() + ConeClassLikeLookupTagImpl(continuationClassId).constructClassType( - arrayOf(type.typeArguments.last()), - isNullable = false - )).toTypedArray(), - type.isNullable - ) - } - private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: ConeClassLikeType) { val classifierSymbol = type.lookupTag.toSymbol(session) if (classifierSymbol != null) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt index 602f1792166..ea7ebfaf344 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt @@ -89,7 +89,24 @@ fun ConeKotlinType.suspendFunctionTypeToFunctionType(session: FirSession): ConeC if (isKFunctionType(session)) FunctionClassKind.KFunction else FunctionClassKind.Function val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1)) - return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false) + return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false, attributes = attributes) +} + +fun ConeKotlinType.suspendFunctionTypeToFunctionTypeWithContinuation(session: FirSession, continuationClassId: ClassId): ConeClassLikeType { + require(this.isSuspendFunctionType(session)) + val kind = + if (isKFunctionType(session)) FunctionClassKind.KFunction + else FunctionClassKind.Function + val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size)) + return ConeClassLikeTypeImpl( + ConeClassLikeLookupTagImpl(functionalTypeId), + typeArguments = (type.typeArguments.dropLast(1) + ConeClassLikeLookupTagImpl(continuationClassId).constructClassType( + arrayOf(type.typeArguments.last()), + isNullable = false + ) + type.typeArguments.last()).toTypedArray(), + isNullable = false, + attributes = attributes + ) } fun ConeKotlinType.isSubtypeOfFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): Boolean { diff --git a/compiler/testData/codegen/box/fir/SuspendExtension.kt b/compiler/testData/codegen/box/fir/SuspendExtension.kt new file mode 100644 index 00000000000..aed34a6a6e5 --- /dev/null +++ b/compiler/testData/codegen/box/fir/SuspendExtension.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM +// MODULE: lib +// FILE: A.kt + +class CoroutineScope + +suspend fun runWithTimeout( + block: suspend CoroutineScope.() -> T +): T? = null + +// MODULE: main(lib) +// FILE: B.kt + +suspend fun foo(): Boolean = runWithTimeout { + false +} ?: true + +fun box(): String = "OK" \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt index 5d1626cbf08..d857af0cd9d 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // FILE: A.kt // WITH_RUNTIME // WITH_COROUTINES diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 7dac22b9a70..3e005c6199c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -13711,6 +13711,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testExtensionAlias() throws Exception { runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt"); } + + @Test + @TestMetadata("SuspendExtension.kt") + public void testSuspendExtension() throws Exception { + runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt"); + } } @Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 07e9c9bff98..3b5da1b20ab 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -13711,6 +13711,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testExtensionAlias() throws Exception { runTest("compiler/testData/codegen/box/fir/ExtensionAlias.kt"); } + + @Test + @TestMetadata("SuspendExtension.kt") + public void testSuspendExtension() throws Exception { + runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt"); + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b5edeb1f535..93d7d5e89fa 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12034,6 +12034,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class Fir extends AbstractLightAnalysisModeTest { + @TestMetadata("SuspendExtension.kt") + public void ignoreSuspendExtension() throws Exception { + runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); }