Deserialize experimental coroutines as suspend functions/types
but deprecate them for now. Promote stub version. #KT-25623: Fixed
This commit is contained in:
+33
-48
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.serialization.deserialization
|
||||
@@ -26,13 +15,9 @@ import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class MemberDeserializer(private val c: DeserializationContext) {
|
||||
private val annotationDeserializer = AnnotationDeserializer(c.components.moduleDescriptor, c.components.notFoundClasses)
|
||||
@@ -75,6 +60,12 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
proto.receiverType(c.typeTable)?.let { local.typeDeserializer.type(it, receiverAnnotations) }
|
||||
)
|
||||
|
||||
// Calculate isExperimentalCoroutineInReleaseEnvironment for type parameters
|
||||
property.typeParameters.forEach { it.upperBounds }
|
||||
|
||||
property.isExperimentalCoroutineInReleaseEnvironment = local.typeDeserializer.experimentalSuspendFunctionTypeEncountered &&
|
||||
c.components.configuration.releaseCoroutines && property.versionRequirement?.version != VersionRequirement.Version(1, 3)
|
||||
|
||||
val getter = if (hasGetter) {
|
||||
val getterFlags = proto.getterFlags
|
||||
val isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags)
|
||||
@@ -164,15 +155,13 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
)
|
||||
val local = c.childContext(function, proto.typeParameterList)
|
||||
|
||||
val returnType = local.typeDeserializer.type(proto.returnType(c.typeTable))
|
||||
val valueParameters = local.memberDeserializer.valueParameters(proto.valueParameterList, proto, AnnotatedCallableKind.FUNCTION)
|
||||
val continuationParameter = createContinuationParameterIfNeeded(function, returnType, valueParameters, flags)
|
||||
val receiverType = proto.receiverType(c.typeTable)?.let { local.typeDeserializer.type(it, receiverAnnotations) }
|
||||
function.initialize(
|
||||
proto.receiverType(c.typeTable)?.let { local.typeDeserializer.type(it, receiverAnnotations) },
|
||||
receiverType,
|
||||
getDispatchReceiverParameter(),
|
||||
local.typeDeserializer.ownTypeParameters,
|
||||
valueParameters + listOfNotNull(continuationParameter),
|
||||
if (continuationParameter == null) returnType else function.builtIns.nullableAnyType,
|
||||
local.memberDeserializer.valueParameters(proto.valueParameterList, proto, AnnotatedCallableKind.FUNCTION),
|
||||
local.typeDeserializer.type(proto.returnType(c.typeTable)),
|
||||
ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
|
||||
ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
|
||||
emptyMap<FunctionDescriptor.UserDataKey<*>, Any?>()
|
||||
@@ -182,9 +171,16 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
function.isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags)
|
||||
function.isInline = Flags.IS_INLINE.get(flags)
|
||||
function.isTailrec = Flags.IS_TAILREC.get(flags)
|
||||
function.isSuspend = Flags.IS_SUSPEND.get(flags) && loadAsSuspend(function.versionRequirement)
|
||||
function.isSuspend = Flags.IS_SUSPEND.get(flags)
|
||||
function.isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
||||
|
||||
// Calculate isExperimentalCoroutineInReleaseEnvironment for type parameters
|
||||
function.typeParameters.forEach { it.upperBounds }
|
||||
|
||||
function.isExperimentalCoroutineInReleaseEnvironment = local.typeDeserializer.experimentalSuspendFunctionTypeEncountered ||
|
||||
(c.components.configuration.releaseCoroutines && Flags.IS_SUSPEND.get(flags) &&
|
||||
function.versionRequirement?.version != VersionRequirement.Version(1, 3))
|
||||
|
||||
val mapValueForContract =
|
||||
c.components.contractDeserializer.deserializeContractFromFunction(proto, function, c.typeTable, c.typeDeserializer)
|
||||
if (mapValueForContract != null) {
|
||||
@@ -194,30 +190,6 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
return function
|
||||
}
|
||||
|
||||
private fun loadAsSuspend(versionRequirement: VersionRequirement?): Boolean =
|
||||
if (c.components.configuration.releaseCoroutines) {
|
||||
versionRequirement?.version == VersionRequirement.Version(1, 3)
|
||||
} else true
|
||||
|
||||
private fun createContinuationParameterIfNeeded(
|
||||
functionDescriptor: DeserializedSimpleFunctionDescriptor,
|
||||
returnType: KotlinType,
|
||||
valueParameters: List<ValueParameterDescriptor>,
|
||||
flags: Int
|
||||
): ValueParameterDescriptor? =
|
||||
if (!Flags.IS_SUSPEND.get(flags) || loadAsSuspend(functionDescriptor.versionRequirement)) null
|
||||
else ValueParameterDescriptorImpl(
|
||||
containingDeclaration = functionDescriptor,
|
||||
original = null,
|
||||
index = valueParameters.size,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = Name.identifier("continuation"),
|
||||
outType = functionDescriptor.module.getContinuationOfTypeOrAny(returnType, isReleaseCoroutines = false),
|
||||
declaresDefaultValue = false, isCrossinline = false,
|
||||
isNoinline = false, varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
fun loadTypeAlias(proto: ProtoBuf.TypeAlias): TypeAliasDescriptor {
|
||||
val annotations = AnnotationsImpl(proto.annotationList.map { annotationDeserializer.deserializeAnnotation(it, c.nameResolver) })
|
||||
|
||||
@@ -234,6 +206,11 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
local.typeDeserializer.simpleType(proto.expandedType(c.typeTable))
|
||||
)
|
||||
|
||||
// Calculate isExperimentalCoroutineInReleaseEnvironment for type parameters
|
||||
local.typeDeserializer.ownTypeParameters.forEach { it.upperBounds }
|
||||
|
||||
typeAlias.isExperimentalCoroutineInReleaseEnvironment = local.typeDeserializer.experimentalSuspendFunctionTypeEncountered
|
||||
|
||||
return typeAlias
|
||||
}
|
||||
|
||||
@@ -254,6 +231,14 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
ProtoEnumFlags.visibility(Flags.VISIBILITY.get(proto.flags))
|
||||
)
|
||||
descriptor.returnType = classDescriptor.defaultType
|
||||
|
||||
// Calculate isExperimentalCoroutineInReleaseEnvironment for type parameters
|
||||
descriptor.typeParameters.forEach { it.upperBounds }
|
||||
descriptor.isExperimentalCoroutineInReleaseEnvironment = local.typeDeserializer.experimentalSuspendFunctionTypeEncountered ||
|
||||
((c.containingDeclaration as? DeserializedClassDescriptor)?.c?.typeDeserializer?.experimentalSuspendFunctionTypeEncountered == true &&
|
||||
c.components.configuration.releaseCoroutines &&
|
||||
descriptor.versionRequirement?.version != VersionRequirement.Version(1, 3))
|
||||
|
||||
return descriptor
|
||||
}
|
||||
|
||||
|
||||
+16
-17
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.serialization.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -25,7 +23,8 @@ class TypeDeserializer(
|
||||
private val c: DeserializationContext,
|
||||
private val parent: TypeDeserializer?,
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
private val debugName: String
|
||||
private val debugName: String,
|
||||
var experimentalSuspendFunctionTypeEncountered: Boolean = false
|
||||
) {
|
||||
private val classDescriptors: (Int) -> ClassDescriptor? = c.storageManager.createMemoizedFunctionWithNullableValues { fqNameIndex ->
|
||||
computeClassDescriptor(fqNameIndex)
|
||||
@@ -91,7 +90,7 @@ class TypeDeserializer(
|
||||
}.toList()
|
||||
|
||||
val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
|
||||
createSuspendFunctionType(annotations, constructor, arguments, proto.nullable, c.components.configuration.releaseCoroutines)
|
||||
createSuspendFunctionType(annotations, constructor, arguments, proto.nullable)
|
||||
} else {
|
||||
KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable)
|
||||
}
|
||||
@@ -131,11 +130,10 @@ class TypeDeserializer(
|
||||
annotations: Annotations,
|
||||
functionTypeConstructor: TypeConstructor,
|
||||
arguments: List<TypeProjection>,
|
||||
nullable: Boolean,
|
||||
isReleaseCoroutines: Boolean
|
||||
nullable: Boolean
|
||||
): SimpleType {
|
||||
val result = when (functionTypeConstructor.parameters.size - arguments.size) {
|
||||
0 -> createSuspendFunctionTypeForBasicCase(annotations, functionTypeConstructor, arguments, nullable, isReleaseCoroutines)
|
||||
0 -> createSuspendFunctionTypeForBasicCase(annotations, functionTypeConstructor, arguments, nullable)
|
||||
// This case for types written by eap compiler 1.1
|
||||
1 -> {
|
||||
val arity = arguments.size - 1
|
||||
@@ -162,8 +160,7 @@ class TypeDeserializer(
|
||||
annotations: Annotations,
|
||||
functionTypeConstructor: TypeConstructor,
|
||||
arguments: List<TypeProjection>,
|
||||
nullable: Boolean,
|
||||
isReleaseCoroutines: Boolean
|
||||
nullable: Boolean
|
||||
): SimpleType? {
|
||||
val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable)
|
||||
if (!functionType.isFunctionType) return null
|
||||
@@ -171,16 +168,18 @@ class TypeDeserializer(
|
||||
// kotlin.suspend is still built with LV=1.2, thus it references old Continuation
|
||||
// And otherwise, once stdlib is compiled with 1.3 one may want to stay at LV=1.2
|
||||
if (c.containingDeclaration.safeAs<CallableDescriptor>()?.fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) {
|
||||
transformRuntimeFunctionTypeToSuspendFunction(functionType, false)?.let { oldSuspend ->
|
||||
if (oldSuspend.isSuspendFunctionType) return oldSuspend
|
||||
|
||||
transformRuntimeFunctionTypeToSuspendFunction(functionType, true)?.let { newSuspend -> return newSuspend }
|
||||
}
|
||||
val (suspendFun, experimental) = transformRuntimeFunctionTypeToSuspendFunction(functionType, true)
|
||||
if (experimental)
|
||||
transformRuntimeFunctionTypeToSuspendFunction(functionType, false).first?.let { return it }
|
||||
else
|
||||
return suspendFun
|
||||
}
|
||||
|
||||
transformRuntimeFunctionTypeToSuspendFunction(functionType, isReleaseCoroutines)?.let { return it }
|
||||
val (type, experimental) = transformRuntimeFunctionTypeToSuspendFunction(functionType, c.components.configuration.releaseCoroutines)
|
||||
|
||||
return null
|
||||
experimentalSuspendFunctionTypeEncountered = experimental || experimentalSuspendFunctionTypeEncountered
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
private fun typeParameterTypeConstructor(typeParameterId: Int): TypeConstructor? =
|
||||
|
||||
+15
-7
@@ -34,6 +34,8 @@ interface DeserializedMemberDescriptor : MemberDescriptor {
|
||||
|
||||
val typeTable: TypeTable
|
||||
|
||||
var isExperimentalCoroutineInReleaseEnvironment: Boolean
|
||||
|
||||
val versionRequirementTable: VersionRequirementTable
|
||||
|
||||
val versionRequirement: VersionRequirement?
|
||||
@@ -68,7 +70,8 @@ class DeserializedSimpleFunctionDescriptor(
|
||||
override val typeTable: TypeTable,
|
||||
override val versionRequirementTable: VersionRequirementTable,
|
||||
override val containerSource: DeserializedContainerSource?,
|
||||
source: SourceElement? = null
|
||||
source: SourceElement? = null,
|
||||
override var isExperimentalCoroutineInReleaseEnvironment: Boolean = false
|
||||
) : DeserializedCallableMemberDescriptor,
|
||||
SimpleFunctionDescriptorImpl(
|
||||
containingDeclaration, original, annotations, name, kind,
|
||||
@@ -85,7 +88,7 @@ class DeserializedSimpleFunctionDescriptor(
|
||||
): FunctionDescriptorImpl {
|
||||
return DeserializedSimpleFunctionDescriptor(
|
||||
newOwner, original as SimpleFunctionDescriptor?, annotations, newName ?: name, kind,
|
||||
proto, nameResolver, typeTable, versionRequirementTable, containerSource, source
|
||||
proto, nameResolver, typeTable, versionRequirementTable, containerSource, source, isExperimentalCoroutineInReleaseEnvironment
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -108,7 +111,8 @@ class DeserializedPropertyDescriptor(
|
||||
override val nameResolver: NameResolver,
|
||||
override val typeTable: TypeTable,
|
||||
override val versionRequirementTable: VersionRequirementTable,
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
override val containerSource: DeserializedContainerSource?,
|
||||
override var isExperimentalCoroutineInReleaseEnvironment: Boolean = false
|
||||
) : DeserializedCallableMemberDescriptor, PropertyDescriptorImpl(
|
||||
containingDeclaration, original, annotations, modality, visibility, isVar, name, kind, SourceElement.NO_SOURCE,
|
||||
isLateInit, isConst, isExpect, false, isExternal, isDelegated
|
||||
@@ -123,7 +127,8 @@ class DeserializedPropertyDescriptor(
|
||||
): PropertyDescriptorImpl {
|
||||
return DeserializedPropertyDescriptor(
|
||||
newOwner, original, annotations, newModality, newVisibility, isVar, newName, kind, isLateInit, isConst, isExternal,
|
||||
@Suppress("DEPRECATION") isDelegated, isExpect, proto, nameResolver, typeTable, versionRequirementTable, containerSource
|
||||
@Suppress("DEPRECATION") isDelegated, isExpect, proto, nameResolver, typeTable, versionRequirementTable, containerSource,
|
||||
isExperimentalCoroutineInReleaseEnvironment
|
||||
)
|
||||
}
|
||||
|
||||
@@ -141,7 +146,8 @@ class DeserializedClassConstructorDescriptor(
|
||||
override val typeTable: TypeTable,
|
||||
override val versionRequirementTable: VersionRequirementTable,
|
||||
override val containerSource: DeserializedContainerSource?,
|
||||
source: SourceElement? = null
|
||||
source: SourceElement? = null,
|
||||
override var isExperimentalCoroutineInReleaseEnvironment: Boolean = false
|
||||
) : DeserializedCallableMemberDescriptor,
|
||||
ClassConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, source ?: SourceElement.NO_SOURCE) {
|
||||
|
||||
@@ -178,7 +184,8 @@ class DeserializedTypeAliasDescriptor(
|
||||
override val nameResolver: NameResolver,
|
||||
override val typeTable: TypeTable,
|
||||
override val versionRequirementTable: VersionRequirementTable,
|
||||
override val containerSource: DeserializedContainerSource?
|
||||
override val containerSource: DeserializedContainerSource?,
|
||||
override var isExperimentalCoroutineInReleaseEnvironment: Boolean = false
|
||||
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility),
|
||||
DeserializedMemberDescriptor {
|
||||
override lateinit var constructors: Collection<TypeAliasConstructorDescriptor> private set
|
||||
@@ -210,7 +217,8 @@ class DeserializedTypeAliasDescriptor(
|
||||
if (substitutor.isEmpty) return this
|
||||
val substituted = DeserializedTypeAliasDescriptor(
|
||||
storageManager, containingDeclaration, annotations, name, visibility,
|
||||
proto, nameResolver, typeTable, versionRequirementTable, containerSource
|
||||
proto, nameResolver, typeTable, versionRequirementTable, containerSource,
|
||||
isExperimentalCoroutineInReleaseEnvironment
|
||||
)
|
||||
substituted.initialize(
|
||||
declaredTypeParameters,
|
||||
|
||||
Reference in New Issue
Block a user