diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index f4564c10679..4564f7764d5 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.getFunctionalClassKind import org.jetbrains.kotlin.builtins.isSuspendFunctionType +import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotated @@ -451,6 +452,12 @@ class DescriptorSerializer private constructor( return lowerBound } + if (type.isSuspendFunctionType) { + val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type)) + functionType.flags = Flags.getTypeFlags(true) + return functionType + } + val descriptor = type.constructor.declarationDescriptor when (descriptor) { is ClassDescriptor, is TypeAliasDescriptor -> { @@ -489,25 +496,12 @@ class DescriptorSerializer private constructor( } private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: PossiblyInnerType) { - val classifierDescriptor: ClassifierDescriptorWithTypeParameters - val isSuspendType: Boolean - - val originalClassifierDescriptor = type.classifierDescriptor - if (originalClassifierDescriptor.getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction) { - classifierDescriptor = originalClassifierDescriptor.builtIns.getFunction(originalClassifierDescriptor.declaredTypeParameters.size) - isSuspendType = true - } - else { - classifierDescriptor = originalClassifierDescriptor - isSuspendType = false - } - + val classifierDescriptor = type.classifierDescriptor val classifierId = getClassifierId(classifierDescriptor) when (classifierDescriptor) { is ClassDescriptor -> builder.className = classifierId is TypeAliasDescriptor -> builder.typeAliasName = classifierId } - builder.flags = Flags.getTypeFlags(isSuspendType) for (projection in type.arguments) { builder.addArgument(typeArgument(projection)) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt index 26e3701e451..f789065117e 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt @@ -32,7 +32,7 @@ class JvmMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) { var skipCheck: Boolean = false @JvmField - val INSTANCE = JvmMetadataVersion(1, 1, 4) + val INSTANCE = JvmMetadataVersion(1, 1, 5) @JvmField val INVALID_VERSION = JvmMetadataVersion() diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index 012ee0630e1..e63d478db65 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -64,22 +64,6 @@ interface TypeMappingConfiguration { const val NON_EXISTENT_CLASS_NAME = "error/NonExistentClass" -private val FAKE_CONTINUATION_CLASS_DESCRIPTOR = - MutableClassDescriptor( - ErrorUtils.getErrorModule(), - ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false, - DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.shortName(), SourceElement.NO_SOURCE - ).apply { - modality = Modality.ABSTRACT - visibility = Visibilities.PUBLIC - setTypeParameterDescriptors( - TypeParameterDescriptorImpl.createWithDefaultBound( - this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0 - ).let(::listOf) - ) - createTypeConstructor() - } - private val CONTINUATION_INTERNAL_NAME = JvmClassName.byClassId(ClassId.topLevel(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME)).internalName @@ -93,23 +77,7 @@ fun mapType( ): T { if (kotlinType.isSuspendFunctionType) { return mapType( - createFunctionType( - kotlinType.builtIns, - kotlinType.annotations, - kotlinType.getReceiverTypeFromFunctionType(), - kotlinType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType) + - KotlinTypeFactory.simpleType( - Annotations.EMPTY, - // Continuation interface is not a part of built-ins anymore, it has been moved to stdlib. - // While it must be somewhere in the dependencies, but here we don't have a reference to the module, - // and it's rather complicated to inject it by now, so we just use a fake class descriptor. - FAKE_CONTINUATION_CLASS_DESCRIPTOR.typeConstructor, - listOf(kotlinType.getReturnTypeFromFunctionType().asTypeProjection()), nullable = false - ), - // TODO: names - null, - kotlinType.builtIns.nullableAnyType - ), + transformSuspendFunctionToRuntimeFunctionType(kotlinType), factory, mode, typeMappingConfiguration, descriptorTypeWriter, writeGenericType ) diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/suspendFunctionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/suspendFunctionTypes.kt new file mode 100644 index 00000000000..169c2dd9f40 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/suspendFunctionTypes.kt @@ -0,0 +1,100 @@ +/* + * 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 org.jetbrains.kotlin.builtins + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor +import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.types.typeUtil.builtIns + + +val FAKE_CONTINUATION_CLASS_DESCRIPTOR = + MutableClassDescriptor( + EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME), + ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false, + DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.shortName(), SourceElement.NO_SOURCE + ).apply { + modality = Modality.ABSTRACT + visibility = Visibilities.PUBLIC + setTypeParameterDescriptors( + TypeParameterDescriptorImpl.createWithDefaultBound( + this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0 + ).let(::listOf) + ) + createTypeConstructor() + } + + +fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType): SimpleType { + assert(suspendFunType.isSuspendFunctionType) { + "This type should be suspend function type: $suspendFunType" + } + + return createFunctionType( + suspendFunType.builtIns, + suspendFunType.annotations, + suspendFunType.getReceiverTypeFromFunctionType(), + suspendFunType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType) + + KotlinTypeFactory.simpleType( + Annotations.EMPTY, + // Continuation interface is not a part of built-ins anymore, it has been moved to stdlib. + // While it must be somewhere in the dependencies, but here we don't have a reference to the module, + // and it's rather complicated to inject it by now, so we just use a fake class descriptor. + FAKE_CONTINUATION_CLASS_DESCRIPTOR.typeConstructor, + listOf(suspendFunType.getReturnTypeFromFunctionType().asTypeProjection()), nullable = false + ), + // TODO: names + null, + suspendFunType.builtIns.nullableAnyType + ).makeNullableAsSpecified(suspendFunType.isMarkedNullable) +} + +fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType): SimpleType? { + assert(funType.isFunctionType) { + "This type should be function type: $funType" + } + + val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null + if (continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe != DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME + || continuationArgumentType.arguments.size != 1 + ) { + return null + } + + val suspendReturnType = continuationArgumentType.arguments.single().type + + return createFunctionType( + funType.builtIns, + funType.annotations, + funType.getReceiverTypeFromFunctionType(), + funType.getValueParameterTypesFromFunctionType().dropLast(1).map(TypeProjection::getType), + // TODO: names + null, + suspendReturnType, + suspendFunction = true + ).makeNullableAsSpecified(funType.isMarkedNullable) +} \ No newline at end of file diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt index 9a57008a8dc..0286829e54c 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt @@ -16,18 +16,19 @@ package org.jetbrains.kotlin.serialization.deserialization -import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory +import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.serialization.Flags import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedAnnotationsWithPossibleTargets import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeParameterDescriptor import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.toReadOnlyList import java.util.* @@ -99,7 +100,12 @@ class TypeDeserializer( typeArgument(constructor.parameters.getOrNull(index), proto) }.toReadOnlyList() - val simpleType = KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) + val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) { + createSuspendFunctionType(annotations, constructor, arguments, proto.nullable) + } + else { + KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) + } val abbreviatedTypeProto = proto.abbreviatedType(c.typeTable) ?: return simpleType return simpleType.withAbbreviation(simpleType(abbreviatedTypeProto, additionalAnnotations)) @@ -108,13 +114,8 @@ class TypeDeserializer( private fun typeConstructor(proto: ProtoBuf.Type): TypeConstructor = when { proto.hasClassName() -> { - if (Flags.SUSPEND_TYPE.get(proto.flags)) { - getSuspendFunctionTypeConstructor(proto) - } - else { - classDescriptors(proto.className)?.typeConstructor - ?: c.components.notFoundClasses.getClass(proto, c.nameResolver, c.typeTable) - } + classDescriptors(proto.className)?.typeConstructor + ?: c.components.notFoundClasses.getClass(proto, c.nameResolver, c.typeTable) } proto.hasTypeParameter() -> typeParameterTypeConstructor(proto.typeParameter) @@ -132,14 +133,30 @@ class TypeDeserializer( else -> ErrorUtils.createErrorTypeConstructor("Unknown type") } - private fun getSuspendFunctionTypeConstructor(proto: ProtoBuf.Type): TypeConstructor { - val classId = c.nameResolver.getClassId(proto.className) - val arity = BuiltInFictitiousFunctionClassFactory.getFunctionalClassArity(classId.shortClassName.asString(), classId.packageFqName) - - return if (arity != null) - c.containingDeclaration.builtIns.getSuspendFunction(arity - 1).typeConstructor - else - ErrorUtils.createErrorTypeConstructor("Class is not a FunctionN ${classId.asString()}") + private fun createSuspendFunctionType( + annotations: Annotations, + functionTypeConstructor: TypeConstructor, + arguments: List, + nullable: Boolean + ): SimpleType { + val result = when (functionTypeConstructor.parameters.size - arguments.size) { + 0 -> { + val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable) + functionType.check { it.isFunctionType }?.let(::transformRuntimeFunctionTypeToSuspendFunction) + } + // This case for types written by eap compiler 1.1 + 1 -> { + val arity = arguments.size - 1 + if (arity > 0) { + KotlinTypeFactory.simpleType(annotations, functionTypeConstructor.builtIns.getSuspendFunction(arity).typeConstructor, arguments, nullable) + } + else { + null + } + } + else -> null + } + return result ?: ErrorUtils.createErrorTypeWithArguments("Bad suspend function in metadata with constructor: $functionTypeConstructor", arguments) } private fun typeParameterTypeConstructor(typeParameterId: Int): TypeConstructor? =