[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
diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeRefinerImpl.kt index eeb543b..d408f41 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 @@ 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 @@ cached.restoreAdditionalTypeInformation(type) } + else -> type.refineWithRespectToAbbreviatedTypes(this) } } @@ -131,8 +134,11 @@ @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 @@ 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 @@ is NewCapturedTypeConstructor -> { supertypes.map { it.constructor } + projection.type.constructor } + else -> supertypes.map { it.constructor } }