From 91d64d992fb73f9af3ad68d1d85627c8d7aae42b Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Mon, 8 Aug 2022 17:34:01 +0200 Subject: [PATCH] [MPP] Refine enum entries and Enum-type Enum-type inherits java.io.Serializable on JVM, so it needs to be refinement ot avoid TYPE_MISMATCH errors. Note that for the refinement of Enum-type itself it's necessary to force refinement of enum-entries, otherwise their supertypes (and Enum-type specifically) won't be touched Tests are added on IJ side ^KT-53514 --- .../kotlin/types/KotlinTypeRefinerImpl.kt | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt index eeb543bfb0c..d408f415010 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.types +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.descriptorUtil.classId @@ -78,6 +79,7 @@ class KotlinTypeRefinerImpl( require(type is KotlinType) return when { !type.needsRefinement() -> type + type.canBeCached() -> { val cached = refinedTypeCache.computeIfAbsent(type.constructor) { type.constructor.declarationDescriptor!!.defaultType.refineWithRespectToAbbreviatedTypes(this) @@ -85,6 +87,7 @@ class KotlinTypeRefinerImpl( cached.restoreAdditionalTypeInformation(type) } + else -> type.refineWithRespectToAbbreviatedTypes(this) } } @@ -131,8 +134,11 @@ class KotlinTypeRefinerImpl( @TypeRefinement override fun isRefinementNeededForTypeConstructor(typeConstructor: TypeConstructor): Boolean { - val owner = typeConstructor.declarationDescriptor ?: return typeConstructor.areThereExpectSupertypes() - return isRefinementNeededForTypeConstructorCache.computeIfAbsent(owner) { typeConstructor.areThereExpectSupertypes() } + val owner = typeConstructor.declarationDescriptor + ?: return typeConstructor.isRefinementNeededForTypeConstructorNoCache() + return isRefinementNeededForTypeConstructorCache.computeIfAbsent(owner) { + typeConstructor.isRefinementNeededForTypeConstructorNoCache() + } } @TypeRefinement @@ -141,6 +147,20 @@ class KotlinTypeRefinerImpl( return scopes.computeIfAbsent(classDescriptor, compute) as S } + private fun TypeConstructor.isRefinementNeededForTypeConstructorNoCache(): Boolean { + return declarationDescriptor.isEnumEntryOrEnum() || areThereExpectSupertypes() + } + + // Enum-type itself should be refined because on JVM it has Serializable + // supertype, but it's not marked as expect. + // Enum entries need refinement only to force refinement of the Enum-type + // in their supertypes. + private fun DeclarationDescriptor?.isEnumEntryOrEnum(): Boolean = + if (this is ClassDescriptor) + kind == ClassKind.ENUM_CLASS || KotlinBuiltIns.isEnum(this) + else + false + private fun TypeConstructor.areThereExpectSupertypes(): Boolean { var result = false DFS.dfs( @@ -178,6 +198,7 @@ private val TypeConstructor.allDependentTypeConstructors: Collection { supertypes.map { it.constructor } + projection.type.constructor } + else -> supertypes.map { it.constructor } }