From 4b0da0688ae6bff708cccc7ec624c30d3358bd41 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Wed, 15 Apr 2020 20:59:05 +0300 Subject: [PATCH] Fix expect discrimination with actual typealias in deserialization * For types encountered during deserialization, search for a classifier, not necessarily a class, across module dependencies (i.e. accept type aliases, returned when actual type alias discriminates an expect class). * When the referenced type is a type alias, expand it, so that when the descriptor is compared to the expansion in other places, they match. * Also, when resolving an abbreviation, don't expand the type aliases, as there are assumptions in the code base that an abbreviation is a type alias. --- .../deserialization/MemberDeserializer.kt | 4 +-- .../deserialization/TypeDeserializer.kt | 36 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt index bdd9d46f87d..54dfae91e25 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt @@ -318,8 +318,8 @@ class MemberDeserializer(private val c: DeserializationContext) { val local = c.childContext(typeAlias, proto.typeParameterList) typeAlias.initialize( local.typeDeserializer.ownTypeParameters, - local.typeDeserializer.simpleType(proto.underlyingType(c.typeTable)), - local.typeDeserializer.simpleType(proto.expandedType(c.typeTable)), + local.typeDeserializer.simpleType(proto.underlyingType(c.typeTable), expandTypeAliases = false), + local.typeDeserializer.simpleType(proto.expandedType(c.typeTable), expandTypeAliases = false), typeAlias.checkExperimentalCoroutine(local.typeDeserializer) ) 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 5d65ffa7d88..a94b2acc996 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt @@ -11,8 +11,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedAnnotations @@ -30,9 +28,10 @@ class TypeDeserializer( private val containerPresentableName: String, var experimentalSuspendFunctionTypeEncountered: Boolean = false ) { - private val classDescriptors: (Int) -> ClassDescriptor? = c.storageManager.createMemoizedFunctionWithNullableValues { fqNameIndex -> - computeClassDescriptor(fqNameIndex) - } + private val classifierDescriptors: (Int) -> ClassifierDescriptor? = + c.storageManager.createMemoizedFunctionWithNullableValues { fqNameIndex -> + computeClassifierDescriptor(fqNameIndex) + } private val typeAliasDescriptors: (Int) -> ClassifierDescriptor? = c.storageManager.createMemoizedFunctionWithNullableValues { fqNameIndex -> @@ -62,10 +61,10 @@ class TypeDeserializer( return c.components.flexibleTypeDeserializer.create(proto, id, lowerBound, upperBound) } - return simpleType(proto) + return simpleType(proto, expandTypeAliases = true) } - fun simpleType(proto: ProtoBuf.Type): SimpleType { + fun simpleType(proto: ProtoBuf.Type, expandTypeAliases: Boolean = true): SimpleType { val localClassifierType = when { proto.hasClassName() -> computeLocalClassifierReplacementType(proto.className) proto.hasTypeAliasName() -> computeLocalClassifierReplacementType(proto.typeAliasName) @@ -90,17 +89,22 @@ class TypeDeserializer( typeArgument(constructor.parameters.getOrNull(index), argumentProto) }.toList() - val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) { - createSuspendFunctionType(annotations, constructor, arguments, proto.nullable) - } else { - KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) + val declarationDescriptor = constructor.declarationDescriptor + + val simpleType = when { + expandTypeAliases && declarationDescriptor is TypeAliasDescriptor -> + with(KotlinTypeFactory) { declarationDescriptor.computeExpandedType(arguments) } + Flags.SUSPEND_TYPE.get(proto.flags) -> + createSuspendFunctionType(annotations, constructor, arguments, proto.nullable) + else -> + KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) } val computedType = proto.abbreviatedType(c.typeTable)?.let { - simpleType.withAbbreviation(simpleType(it)) + // The abbreviation type is expected to be a typealias, and it should not get expanded, we need to keep it + simpleType.withAbbreviation(simpleType(it, expandTypeAliases = false)) } ?: simpleType - if (proto.hasClassName()) { val classId = c.nameResolver.getClassId(proto.className) return c.components.platformDependentTypeTransformer.transformPlatformType(classId, computedType) @@ -121,7 +125,7 @@ class TypeDeserializer( } return when { - proto.hasClassName() -> (classDescriptors(proto.className) ?: notFoundClass(proto.className)).typeConstructor + proto.hasClassName() -> (classifierDescriptors(proto.className) ?: notFoundClass(proto.className)).typeConstructor proto.hasTypeParameter() -> typeParameterTypeConstructor(proto.typeParameter) ?: ErrorUtils.createErrorTypeConstructor( @@ -223,13 +227,13 @@ class TypeDeserializer( private fun typeParameterTypeConstructor(typeParameterId: Int): TypeConstructor? = typeParameterDescriptors[typeParameterId]?.typeConstructor ?: parent?.typeParameterTypeConstructor(typeParameterId) - private fun computeClassDescriptor(fqNameIndex: Int): ClassDescriptor? { + private fun computeClassifierDescriptor(fqNameIndex: Int): ClassifierDescriptor? { val id = c.nameResolver.getClassId(fqNameIndex) if (id.isLocal) { // Local classes can't be found in scopes return c.components.deserializeClass(id) } - return c.components.moduleDescriptor.findClassAcrossModuleDependencies(id) + return c.components.moduleDescriptor.findClassifierAcrossModuleDependencies(id) } private fun computeLocalClassifierReplacementType(className: Int): SimpleType? {