[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:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.types
|
package org.jetbrains.kotlin.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
@@ -78,6 +79,7 @@ class KotlinTypeRefinerImpl(
|
|||||||
require(type is KotlinType)
|
require(type is KotlinType)
|
||||||
return when {
|
return when {
|
||||||
!type.needsRefinement() -> type
|
!type.needsRefinement() -> type
|
||||||
|
|
||||||
type.canBeCached() -> {
|
type.canBeCached() -> {
|
||||||
val cached = refinedTypeCache.computeIfAbsent(type.constructor) {
|
val cached = refinedTypeCache.computeIfAbsent(type.constructor) {
|
||||||
type.constructor.declarationDescriptor!!.defaultType.refineWithRespectToAbbreviatedTypes(this)
|
type.constructor.declarationDescriptor!!.defaultType.refineWithRespectToAbbreviatedTypes(this)
|
||||||
@@ -85,6 +87,7 @@ class KotlinTypeRefinerImpl(
|
|||||||
|
|
||||||
cached.restoreAdditionalTypeInformation(type)
|
cached.restoreAdditionalTypeInformation(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> type.refineWithRespectToAbbreviatedTypes(this)
|
else -> type.refineWithRespectToAbbreviatedTypes(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,8 +134,11 @@ class KotlinTypeRefinerImpl(
|
|||||||
|
|
||||||
@TypeRefinement
|
@TypeRefinement
|
||||||
override fun isRefinementNeededForTypeConstructor(typeConstructor: TypeConstructor): Boolean {
|
override fun isRefinementNeededForTypeConstructor(typeConstructor: TypeConstructor): Boolean {
|
||||||
val owner = typeConstructor.declarationDescriptor ?: return typeConstructor.areThereExpectSupertypes()
|
val owner = typeConstructor.declarationDescriptor
|
||||||
return isRefinementNeededForTypeConstructorCache.computeIfAbsent(owner) { typeConstructor.areThereExpectSupertypes() }
|
?: return typeConstructor.isRefinementNeededForTypeConstructorNoCache()
|
||||||
|
return isRefinementNeededForTypeConstructorCache.computeIfAbsent(owner) {
|
||||||
|
typeConstructor.isRefinementNeededForTypeConstructorNoCache()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeRefinement
|
@TypeRefinement
|
||||||
@@ -141,6 +147,20 @@ class KotlinTypeRefinerImpl(
|
|||||||
return scopes.computeIfAbsent(classDescriptor, compute) as S
|
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 {
|
private fun TypeConstructor.areThereExpectSupertypes(): Boolean {
|
||||||
var result = false
|
var result = false
|
||||||
DFS.dfs(
|
DFS.dfs(
|
||||||
@@ -178,6 +198,7 @@ private val TypeConstructor.allDependentTypeConstructors: Collection<TypeConstru
|
|||||||
is NewCapturedTypeConstructor -> {
|
is NewCapturedTypeConstructor -> {
|
||||||
supertypes.map { it.constructor } + projection.type.constructor
|
supertypes.map { it.constructor } + projection.type.constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> supertypes.map { it.constructor }
|
else -> supertypes.map { it.constructor }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user