[Commonizer] Implement ClassSuperTypeCommonizer

This implementation runs as regular part of the commonization.
Previous implementation inside the CommonizationVisitor was fully
replaced by it.

As a side effect: CirClass.supertypes was now marked immutable.

^KT-47430 In Progress
This commit is contained in:
sebastian.sellmair
2021-08-11 09:52:14 +02:00
committed by Space
parent 50a343f91e
commit 1857096071
10 changed files with 60 additions and 81 deletions

View File

@@ -15,7 +15,7 @@ interface CirClass : CirClassifier, CirContainingClass {
val isValue: Boolean
val isInner: Boolean
val isExternal: Boolean
var supertypes: List<CirType>
val supertypes: List<CirType>
companion object {
@Suppress("NOTHING_TO_INLINE")
@@ -23,6 +23,7 @@ interface CirClass : CirClassifier, CirContainingClass {
annotations: List<CirAnnotation>,
name: CirName,
typeParameters: List<CirTypeParameter>,
supertypes: List<CirType>,
visibility: Visibility,
modality: Modality,
kind: ClassKind,
@@ -31,11 +32,12 @@ interface CirClass : CirClassifier, CirContainingClass {
isData: Boolean,
isValue: Boolean,
isInner: Boolean,
isExternal: Boolean
isExternal: Boolean,
): CirClass = CirClassImpl(
annotations = annotations,
name = name,
typeParameters = typeParameters,
supertypes = supertypes,
visibility = visibility,
modality = modality,
kind = kind,
@@ -53,6 +55,7 @@ data class CirClassImpl(
override val annotations: List<CirAnnotation>,
override val name: CirName,
override val typeParameters: List<CirTypeParameter>,
override val supertypes: List<CirType>,
override val visibility: Visibility,
override val modality: Modality,
override val kind: ClassKind,
@@ -62,13 +65,4 @@ data class CirClassImpl(
override val isValue: Boolean,
override val isInner: Boolean,
override val isExternal: Boolean,
) : CirClass {
private var _supertypes: List<CirType>? = null
override var supertypes: List<CirType>
get() = _supertypes ?: error("${::supertypes.name} has not been initialized yet")
set(value) {
check(_supertypes == null) { "Re-initialization of ${::supertypes.name}" }
_supertypes = value
}
}
) : CirClass

View File

@@ -19,11 +19,13 @@ class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommon
private var isInner = false
private var isValue = false
private var isCompanion = false
private val supertypes = ClassSuperTypeCommonizer(classifiers).asCommonizer()
override fun commonizationResult() = CirClass.create(
annotations = emptyList(),
name = name,
typeParameters = typeParameters.result,
supertypes = supertypes.result,
visibility = visibility.result,
modality = modality.result,
kind = kind,
@@ -51,4 +53,5 @@ class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommon
&& modality.commonizeWith(next.modality)
&& visibility.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters)
&& supertypes.commonizeWith(next.supertypes)
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClassOrTypeAliasType
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class ClassSuperTypeCommonizer(
private val classifiers: CirKnownClassifiers
) : AssociativeCommonizer<List<CirType>> {
private val typeCommonizer = TypeCommonizer(classifiers)
override fun commonize(first: List<CirType>, second: List<CirType>): List<CirType> {
if (first.isEmpty() || second.isEmpty()) return emptyList()
val firstGroup = first.filterIsInstance<CirClassOrTypeAliasType>().associateBy { it.classifierId }
val secondGroup = second.filterIsInstance<CirClassOrTypeAliasType>().associateBy { it.classifierId }
val commonClassifiers = firstGroup.keys intersect secondGroup.keys
return commonClassifiers.mapNotNull { classifier ->
typeCommonizer.commonize(firstGroup.getValue(classifier), secondGroup.getValue(classifier))
}
}
}

View File

@@ -5,11 +5,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClass
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.commonizer.utils.compactMapNotNull
internal class CommonizationVisitor(
private val classifiers: CirKnownClassifiers,
@@ -93,9 +89,6 @@ internal class CommonizationVisitor(
commonClass.companion = companionObjectName
}
}
// find out common (and commonized) supertypes
commonClass.commonizeSupertypes(node.collectCommonSupertypes())
}
override fun visitClassConstructorNode(node: CirClassConstructorNode, data: Unit) {
@@ -103,49 +96,6 @@ internal class CommonizationVisitor(
}
override fun visitTypeAliasNode(node: CirTypeAliasNode, data: Unit) {
val commonClassifier = node.commonDeclaration() // commonize type alias
if (commonClassifier is CirClass) {
// find out common (and commonized) supertypes
commonClassifier.commonizeSupertypes(node.collectCommonSupertypes())
}
}
private fun CirClassNode.collectCommonSupertypes(): Map<CirType, CommonizedGroup<CirType>> {
val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order
for ((index, clazz) in targetDeclarations.withIndex()) {
for (supertype in clazz!!.supertypes) {
supertypesMap.getOrPut(supertype) { CommonizedGroup(targetDeclarations.size) }[index] = supertype
}
}
return supertypesMap
}
private fun CirTypeAliasNode.collectCommonSupertypes(): Map<CirType, CommonizedGroup<CirType>>? {
val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order
for ((index, typeAlias) in targetDeclarations.withIndex()) {
val expandedClassId = typeAlias!!.expandedType.classifierId
if (classifiers.commonDependencies.hasClassifier(expandedClassId))
return null // this case is not supported yet
val expandedClassNode = classifiers.commonizedNodes.classNode(expandedClassId) ?: return null
val expandedClass = expandedClassNode.targetDeclarations[index]
?: error("Can't find expanded class with class ID $expandedClassId and index $index for type alias $classifierName")
for (supertype in expandedClass.supertypes) {
supertypesMap.getOrPut(supertype) { CommonizedGroup(targetDeclarations.size) }[index] = supertype
}
}
return supertypesMap
}
private fun CirClass.commonizeSupertypes(
supertypesMap: Map<CirType, CommonizedGroup<CirType>>?
) {
val commonSupertypes = supertypesMap?.values?.compactMapNotNull { supertypesGroup ->
commonize(supertypesGroup, TypeCommonizer(classifiers).asCommonizer())
}.orEmpty()
supertypes = commonSupertypes
node.commonDeclaration() // commonize type alias
}
}

View File

@@ -39,7 +39,7 @@ object CirFictitiousFunctionClassifiers : CirProvidedClassifiers {
}
val classId = CirEntityId.create(PACKAGE_NAME, CirName.create("$prefix$arity"))
val clazz = CirProvided.RegularClass(typeParameters, Visibilities.Public)
val clazz = CirProvided.RegularClass(typeParameters, emptyList(), Visibilities.Public)
consumer(classId, clazz)
}

View File

@@ -258,6 +258,7 @@ object CirDeserializers {
annotations = annotations(source.flags, typeResolver, source::annotations),
name = name,
typeParameters = source.typeParameters.compactMap { typeParameter(it, typeResolver) },
supertypes = source.filteredSupertypes.compactMap { type(it, typeResolver) },
visibility = visibility(source.flags),
modality = modality(source.flags),
kind = classKind(source.flags),
@@ -267,9 +268,7 @@ object CirDeserializers {
isValue = Flag.Class.IS_VALUE(source.flags),
isInner = Flag.Class.IS_INNER(source.flags),
isExternal = Flag.Class.IS_EXTERNAL(source.flags)
).apply {
supertypes = source.filteredSupertypes.compactMap { type(it, typeResolver) }
}
)
fun defaultEnumEntry(
name: CirName,
@@ -281,6 +280,15 @@ object CirDeserializers {
annotations = annotations.compactMap { annotation(it, typeResolver) },
name = name,
typeParameters = emptyList(),
supertypes = listOf(
CirClassType.createInterned(
classId = enumClassId,
outerType = null,
visibility = visibility(enumClass.flags),
arguments = emptyList(),
isMarkedNullable = false
)
),
visibility = Visibilities.Public,
modality = Modality.FINAL,
kind = ClassKind.ENUM_ENTRY,
@@ -290,16 +298,7 @@ object CirDeserializers {
isValue = false,
isInner = false,
isExternal = false
).apply {
val enumClassType = CirClassType.createInterned(
classId = enumClassId,
outerType = null,
visibility = visibility(enumClass.flags),
arguments = emptyList(),
isMarkedNullable = false
)
supertypes = listOf(enumClassType)
}
)
@Suppress("NOTHING_TO_INLINE")
private inline fun classKind(flags: Flags): ClassKind =

View File

@@ -144,11 +144,10 @@ private data class ArtificialAliasedCirClass(
}
private fun CirTypeAlias.toArtificialCirClass(): CirClass = CirClass.create(
annotations = emptyList(), name = name, typeParameters = typeParameters,
annotations = emptyList(), name = name, typeParameters = typeParameters, supertypes = artificialSupertypes(),
visibility = this.visibility, modality = Modality.FINAL, kind = ClassKind.CLASS,
companion = null, isCompanion = false, isData = false, isValue = false, isInner = false, isExternal = false
).also { it.supertypes = artificialSupertypes() }
)
/**
* Analog to "KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule" which also

View File

@@ -431,6 +431,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
annotations = emptyList(),
name = type.classifierId.relativeNameSegments.last(),
typeParameters = emptyList(),
supertypes = emptyList(),
visibility = Visibilities.Public,
modality = Modality.FINAL,
kind = ClassKind.CLASS,

View File

@@ -96,7 +96,8 @@ class InlineTypeAliasCirNodeTransformerTest {
storageManager, 2, classifiers, null, CirEntityId.create("under/test/X")
).apply {
targetDeclarations[1] = CirClass.create(
name = CirName.create("X"), typeParameters = emptyList(), visibility = Visibilities.Public,
name = CirName.create("X"), typeParameters = emptyList(),
supertypes = emptyList(), visibility = Visibilities.Public,
companion = null, isCompanion = false, isData = false, isExternal = false,
isInner = false, isValue = false, kind = ClassKind.CLASS,
modality = Modality.FINAL, annotations = emptyList(),

View File

@@ -61,6 +61,7 @@ internal val MOCK_CLASSIFIERS = CirKnownClassifiers(
annotations = emptyList(),
name = CirName.create("Any"),
typeParameters = emptyList(),
supertypes = emptyList(),
visibility = Visibilities.Public,
modality = Modality.OPEN,
kind = ClassKind.CLASS,