[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
This commit is contained in:
Dmitry Savvinov
2022-08-08 17:34:01 +02:00
parent 22e26d0756
commit 91d64d992f
@@ -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<TypeConstru
is NewCapturedTypeConstructor -> {
supertypes.map { it.constructor } + projection.type.constructor
}
else -> supertypes.map { it.constructor }
}