FIR: fix suspend type serialization

This commit is contained in:
Mikhail Glukhikh
2021-01-20 17:21:08 +03:00
parent afe335e504
commit 4cd6266bce
8 changed files with 64 additions and 22 deletions
@@ -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
@@ -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) {
@@ -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 {
+19
View File
@@ -0,0 +1,19 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// MODULE: lib
// FILE: A.kt
class CoroutineScope
suspend fun <T> runWithTimeout(
block: suspend CoroutineScope.() -> T
): T? = null
// MODULE: main(lib)
// FILE: B.kt
suspend fun foo(): Boolean = runWithTimeout {
false
} ?: true
fun box(): String = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: A.kt
// WITH_RUNTIME
// WITH_COROUTINES
@@ -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
@@ -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
@@ -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);
}