[Commonizer] Move type commonization to single invocation commonizer

^KT-48288
This commit is contained in:
sebastian.sellmair
2021-09-09 11:23:49 +02:00
committed by Space
parent 3ee87f1635
commit 97e37243c6
36 changed files with 320 additions and 296 deletions
@@ -5,51 +5,53 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirFunctionOrProperty import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.core.TypeCommonizer.Options.Companion.default
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>( class FunctionOrPropertyBaseCommonizer(
classifiers: CirKnownClassifiers private val typeCommonizer: TypeCommonizer,
) : AbstractStandardCommonizer<T, T?>() { private val extensionReceiverCommonizer: ExtensionReceiverCommonizer = ExtensionReceiverCommonizer(typeCommonizer),
protected lateinit var name: CirName private val returnTypeCommonizer: ReturnTypeCommonizer = ReturnTypeCommonizer(typeCommonizer),
protected val modality = ModalityCommonizer() ) : NullableContextualSingleInvocationCommonizer<CirFunctionOrProperty, FunctionOrPropertyBaseCommonizer.FunctionOrProperty> {
protected val visibility = VisibilityCommonizer.lowering()
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
protected val returnType = ReturnTypeCommonizer(classifiers).asCommonizer()
protected lateinit var kind: CallableMemberDescriptor.Kind
protected val typeParameters = TypeParameterListCommonizer(classifiers)
override fun initialize(first: T) { data class FunctionOrProperty(
name = first.name val name: CirName,
kind = first.kind val kind: CallableMemberDescriptor.Kind,
} val modality: Modality,
val visibility: Visibility,
val extensionReceiver: CirExtensionReceiver?,
val returnType: CirType,
val typeParameters: List<CirTypeParameter>
)
override fun doCommonizeWith(next: T): Boolean = override fun invoke(values: List<CirFunctionOrProperty>): FunctionOrProperty? {
next.kind != DELEGATION // delegated members should not be commonized /* Preconditions */
&& (next.kind != SYNTHESIZED || next.containingClass?.isData != true) // synthesized members of data classes should not be commonized
&& kind == next.kind
&& modality.commonizeWith(next.modality)
&& visibility.commonizeWith(next)
&& extensionReceiver.commonizeWith(next.extensionReceiver)
&& returnType.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters)
}
private class ReturnTypeCommonizer(
private val classifiers: CirKnownClassifiers,
) : NullableContextualSingleInvocationCommonizer<CirFunctionOrProperty, CirType> {
override fun invoke(values: List<CirFunctionOrProperty>): CirType? {
if (values.isEmpty()) return null if (values.isEmpty()) return null
val isTopLevel = values.all { it.containingClass == null }
val isCovariant = values.none { it is CirProperty && it.isVar } // delegated members should not be commonized
return TypeCommonizer(classifiers, default.withCovariantNullabilityCommonizationEnabled(isTopLevel && isCovariant)) if (values.any { value -> value.kind == DELEGATION }) {
.asCommonizer().commonize(values.map { it.returnType }) return null
}
// synthesized members of data classes should not be commonized
if (values.any { value -> value.kind == SYNTHESIZED && value.containingClass?.isData == true }) {
return null
}
return FunctionOrProperty(
name = values.first().name,
kind = values.singleDistinctValueOrNull { it.kind } ?: return null,
modality = ModalityCommonizer().commonize(values.map { it.modality }) ?: return null,
visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null,
extensionReceiver = extensionReceiverCommonizer(values.map { it.extensionReceiver })?.receiver ?: return null,
returnType = returnTypeCommonizer(values) ?: return null,
typeParameters = TypeParameterListCommonizer(typeCommonizer).commonize(values.map { it.typeParameters }) ?: return null
)
} }
} }
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirType import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.utils.compactMap
/** /**
* Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using * Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using
@@ -16,14 +15,14 @@ import org.jetbrains.kotlin.commonizer.utils.compactMap
* Input: N lists of [CirType] * Input: N lists of [CirType]
* Output: list of [CirType] * Output: list of [CirType]
*/ */
abstract class AbstractListCommonizer<T, R>( abstract class AbstractListCommonizer<T, R: Any>(
private val singleElementCommonizerFactory: (Int) -> Commonizer<T, R> private val singleElementCommonizerFactory: (Int) -> Commonizer<T, R?>
) : Commonizer<List<T>, List<R>> { ) : Commonizer<List<T>, List<R>> {
private var commonizers: Array<Commonizer<T, R>>? = null private var commonizers: Array<Commonizer<T, R?>>? = null
private var error = false private var error = false
final override val result: List<R> final override val result: List<R>
get() = checkState(commonizers, error).compactMap { it.result } get() = checkState(commonizers, error).mapNotNull { it.result }
final override fun commonizeWith(next: List<T>): Boolean { final override fun commonizeWith(next: List<T>): Boolean {
if (error) if (error)
@@ -53,7 +52,7 @@ abstract class AbstractListCommonizer<T, R>(
return !error return !error
} }
protected fun forEachSingleElementCommonizer(action: (index: Int, Commonizer<T, R>) -> Unit) { protected fun forEachSingleElementCommonizer(action: (index: Int, Commonizer<T, R?>) -> Unit) {
val commonizers = commonizers ?: failInEmptyState() val commonizers = commonizers ?: failInEmptyState()
commonizers.forEachIndexed(action) commonizers.forEachIndexed(action)
} }
@@ -9,6 +9,12 @@ interface AssociativeCommonizer<T> {
fun commonize(first: T, second: T): T? fun commonize(first: T, second: T): T?
} }
fun <T> AssociativeCommonizer<T>.commonize(values: List<T>): T? {
if (values.isEmpty()) return null
if (values.size == 1) return values.first()
return values.reduce { acc, next -> commonize(acc, next) ?: return null }
}
fun <T : Any> AssociativeCommonizer<T>.asCommonizer(): AssociativeCommonizerAdapter<T> = AssociativeCommonizerAdapter(this) fun <T : Any> AssociativeCommonizer<T>.asCommonizer(): AssociativeCommonizerAdapter<T> = AssociativeCommonizerAdapter(this)
open class AssociativeCommonizerAdapter<T : Any>( open class AssociativeCommonizerAdapter<T : Any>(
@@ -12,12 +12,11 @@ import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.doNothing import org.jetbrains.kotlin.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.doNothing
import org.jetbrains.kotlin.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.patchCallables import org.jetbrains.kotlin.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.patchCallables
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.compactMapIndexed import org.jetbrains.kotlin.commonizer.utils.compactMapIndexed
import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation
class CallableValueParametersCommonizer( class CallableValueParametersCommonizer(
classifiers: CirKnownClassifiers typeCommonizer: TypeCommonizer,
) : Commonizer<CirCallableMemberWithParameters, CallableValueParametersCommonizer.Result> { ) : Commonizer<CirCallableMemberWithParameters, CallableValueParametersCommonizer.Result> {
class Result( class Result(
val hasStableParameterNames: Boolean, val hasStableParameterNames: Boolean,
@@ -116,7 +115,7 @@ class CallableValueParametersCommonizer(
} }
} }
private val valueParameters = ValueParameterListCommonizer(classifiers) private val valueParameters = ValueParameterListCommonizer(typeCommonizer)
private val callables: MutableList<CallableToPatch> = mutableListOf() private val callables: MutableList<CallableToPatch> = mutableListOf()
private var hasStableParameterNames = true private var hasStableParameterNames = true
private var valueParameterNames: ValueParameterNames? = null private var valueParameterNames: ValueParameterNames? = null
@@ -7,27 +7,29 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClass import org.jetbrains.kotlin.commonizer.cir.CirClass
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirClass, CirClass>() { class ClassCommonizer internal constructor(
typeCommonizer: TypeCommonizer,
supertypesCommonizer: ClassSuperTypeCommonizer
) : AbstractStandardCommonizer<CirClass, CirClass>() {
private lateinit var name: CirName private lateinit var name: CirName
private lateinit var kind: ClassKind private lateinit var kind: ClassKind
private val typeParameters = TypeParameterListCommonizer(classifiers)
private val modality = ModalityCommonizer()
private val visibility = VisibilityCommonizer.equalizing()
private var isInner = false private var isInner = false
private var isValue = false private var isValue = false
private var isCompanion = false private var isCompanion = false
private val supertypes = ClassSuperTypeCommonizer(classifiers).asCommonizer() private val supertypesCommonizer = supertypesCommonizer.asCommonizer()
private val typeParameterListCommonizer: TypeParameterListCommonizer = TypeParameterListCommonizer(typeCommonizer)
private val modalityCommonizer: ModalityCommonizer = ModalityCommonizer()
private val visibilityCommonizer: VisibilityCommonizer = VisibilityCommonizer.equalizing()
override fun commonizationResult() = CirClass.create( override fun commonizationResult() = CirClass.create(
annotations = emptyList(), annotations = emptyList(),
name = name, name = name,
typeParameters = typeParameters.result, typeParameters = typeParameterListCommonizer.result,
supertypes = supertypes.result, supertypes = supertypesCommonizer.result,
visibility = visibility.result, visibility = visibilityCommonizer.result,
modality = modality.result, modality = modalityCommonizer.result,
kind = kind, kind = kind,
companion = null, companion = null,
isCompanion = isCompanion, isCompanion = isCompanion,
@@ -50,8 +52,8 @@ class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommon
&& isInner == next.isInner && isInner == next.isInner
&& isValue == next.isValue && isValue == next.isValue
&& isCompanion == next.isCompanion && isCompanion == next.isCompanion
&& modality.commonizeWith(next.modality) && modalityCommonizer.commonizeWith(next.modality)
&& visibility.commonizeWith(next) && visibilityCommonizer.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters) && typeParameterListCommonizer.commonizeWith(next.typeParameters)
&& supertypes.commonizeWith(next.supertypes) && supertypesCommonizer.commonizeWith(next.supertypes)
} }
@@ -7,26 +7,25 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClassConstructor import org.jetbrains.kotlin.commonizer.cir.CirClassConstructor
import org.jetbrains.kotlin.commonizer.cir.CirContainingClass import org.jetbrains.kotlin.commonizer.cir.CirContainingClass
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
class ClassConstructorCommonizer( class ClassConstructorCommonizer(
classifiers: CirKnownClassifiers typeCommonizer: TypeCommonizer,
) : AbstractStandardCommonizer<CirClassConstructor, CirClassConstructor>() { ) : AbstractStandardCommonizer<CirClassConstructor, CirClassConstructor>() {
private var isPrimary = false private var isPrimary = false
private val visibility = VisibilityCommonizer.equalizing() private val visibility = VisibilityCommonizer.equalizing()
private val typeParameters = TypeParameterListCommonizer(classifiers) private val typeParameterListCommonizer = TypeParameterListCommonizer(typeCommonizer)
private val valueParameters = CallableValueParametersCommonizer(classifiers) private val valueParametersCommonizer = CallableValueParametersCommonizer(typeCommonizer)
private val annotationsCommonizer = AnnotationsCommonizer() private val annotationsCommonizer: AnnotationsCommonizer = AnnotationsCommonizer()
override fun commonizationResult(): CirClassConstructor { override fun commonizationResult(): CirClassConstructor {
val valueParameters = valueParameters.result val valueParameters = valueParametersCommonizer.result
valueParameters.patchCallables() valueParameters.patchCallables()
return CirClassConstructor.create( return CirClassConstructor.create(
annotations = annotationsCommonizer.result, annotations = annotationsCommonizer.result,
typeParameters = typeParameters.result, typeParameters = typeParameterListCommonizer.result,
visibility = visibility.result, visibility = visibility.result,
containingClass = CONTAINING_CLASS_DOES_NOT_MATTER, // does not matter containingClass = CONTAINING_CLASS_DOES_NOT_MATTER, // does not matter
valueParameters = valueParameters.valueParameters, valueParameters = valueParameters.valueParameters,
@@ -44,8 +43,8 @@ class ClassConstructorCommonizer(
&& next.containingClass.modality != Modality.SEALED // don't commonize constructors for sealed classes (not not their subclasses) && next.containingClass.modality != Modality.SEALED // don't commonize constructors for sealed classes (not not their subclasses)
&& isPrimary == next.isPrimary && isPrimary == next.isPrimary
&& visibility.commonizeWith(next) && visibility.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters) && typeParameterListCommonizer.commonizeWith(next.typeParameters)
&& valueParameters.commonizeWith(next) && valueParametersCommonizer.commonizeWith(next)
&& annotationsCommonizer.commonizeWith(next.annotations) && annotationsCommonizer.commonizeWith(next.annotations)
} }
@@ -8,13 +8,16 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClassOrTypeAliasType import org.jetbrains.kotlin.commonizer.cir.CirClassOrTypeAliasType
import org.jetbrains.kotlin.commonizer.cir.CirClassType import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasType import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasType
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
internal class ClassOrTypeAliasTypeCommonizer( internal class ClassOrTypeAliasTypeCommonizer(
private val classifiers: CirKnownClassifiers, private val typeCommonizer: TypeCommonizer
private val options: TypeCommonizer.Options ) : NullableSingleInvocationCommonizer<CirClassOrTypeAliasType> {
) : AssociativeCommonizer<CirClassOrTypeAliasType> {
override fun invoke(values: List<CirClassOrTypeAliasType>): CirClassOrTypeAliasType? {
TODO()
}
/*
override fun commonize(first: CirClassOrTypeAliasType, second: CirClassOrTypeAliasType): CirClassOrTypeAliasType? { override fun commonize(first: CirClassOrTypeAliasType, second: CirClassOrTypeAliasType): CirClassOrTypeAliasType? {
if (first is CirClassType && second is CirClassType) { if (first is CirClassType && second is CirClassType) {
return ClassTypeCommonizer(classifiers, options).commonize(listOf(first, second)) return ClassTypeCommonizer(classifiers, options).commonize(listOf(first, second))
@@ -53,6 +56,9 @@ internal class ClassOrTypeAliasTypeCommonizer(
return commonize(classType, typeAliasClassType) return commonize(classType, typeAliasClassType)
} }
*/
} }
internal tailrec fun CirClassOrTypeAliasType.expandedType(): CirClassType = when (this) { internal tailrec fun CirClassOrTypeAliasType.expandedType(): CirClassType = when (this) {
@@ -41,11 +41,10 @@ private typealias Supertypes = List<CirType>
* ``` * ```
*/ */
internal class ClassSuperTypeCommonizer( internal class ClassSuperTypeCommonizer(
private val classifiers: CirKnownClassifiers private val classifiers: CirKnownClassifiers,
private val typeCommonizer: TypeCommonizer
) : SingleInvocationCommonizer<Supertypes> { ) : SingleInvocationCommonizer<Supertypes> {
private val typeCommonizer = TypeCommonizer(classifiers)
override fun invoke(values: List<Supertypes>): Supertypes { override fun invoke(values: List<Supertypes>): Supertypes {
if (values.isEmpty()) return emptyList() if (values.isEmpty()) return emptyList()
if (values.all { it.isEmpty() }) return emptyList() if (values.all { it.isEmpty() }) return emptyList()
@@ -54,7 +53,7 @@ internal class ClassSuperTypeCommonizer(
val supertypesGroups = buildSupertypesGroups(supertypesTrees) val supertypesGroups = buildSupertypesGroups(supertypesTrees)
return supertypesGroups.mapNotNull { supertypesGroup -> return supertypesGroups.mapNotNull { supertypesGroup ->
typeCommonizer.asCommonizer().commonize(supertypesGroup.types) typeCommonizer(supertypesGroup.types)
} }
} }
@@ -9,42 +9,42 @@ import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull
internal class ClassTypeCommonizer( class ClassTypeCommonizer internal constructor(
private val classifiers: CirKnownClassifiers, private val classifiers: CirKnownClassifiers,
options: TypeCommonizer.Options = TypeCommonizer.Options.default private val typeCommonizer: TypeCommonizer,
) : private val isMarkedNullableCommonizer: TypeNullabilityCommonizer
AbstractStandardCommonizer<CirClassType, CirClassType>() { ) : NullableSingleInvocationCommonizer<CirClassType> {
private lateinit var classId: CirEntityId override fun invoke(values: List<CirClassType>): CirClassType? {
private val outerType = OuterClassTypeCommonizer(classifiers) if (values.isEmpty()) return null
private lateinit var anyVisibility: Visibility val classId = values.singleDistinctValueOrNull { it.classifierId } ?: return null
private val arguments = TypeArgumentListCommonizer(classifiers) val isMarkedNullable = isMarkedNullableCommonizer.commonize(values.map { it.isMarkedNullable }) ?: return null
private val isMarkedNullable = TypeNullabilityCommonizer(options).asCommonizer()
override fun commonizationResult() = CirClassType.createInterned( if (values.any { !isClassifierAvailableInCommon(classifiers, it.classifierId) }) {
classId = classId, return null
outerType = outerType.result, }
// N.B. The 'visibility' field in class types is needed ONLY for TA commonization. The class type constructed here is
// intended to be used in "common" target. It could not participate in TA commonization. So, it does not matter which
// exactly visibility will be recorded for commonized class type. Passing the visibility of the first class type
// to reach better interning rate.
visibility = anyVisibility,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable.result
)
override fun initialize(first: CirClassType) { val outerType = if (values.all { it.outerType == null }) null
classId = first.classifierId else if (values.any { it.outerType == null }) return null
anyVisibility = first.visibility else invoke(values.map { checkNotNull(it.outerType) }) ?: return null
// Commonizer is stateful: Needs to be created per invocation!
val arguments = TypeArgumentListCommonizer(typeCommonizer).commonize(values.map { it.arguments }) ?: return null
return CirClassType.createInterned(
classId = classId,
outerType = outerType,
// N.B. The 'visibility' field in class types is needed ONLY for TA commonization. The class type constructed here is
// intended to be used in "common" target. It could not participate in TA commonization. So, it does not matter which
// exactly visibility will be recorded for commonized class type. Passing the visibility of the first class type
// to reach better interning rate.
visibility = values.first().visibility,
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
} }
override fun doCommonizeWith(next: CirClassType) =
isMarkedNullable.commonizeWith(next.isMarkedNullable)
&& classId == next.classifierId
&& outerType.commonizeWith(next.outerType)
&& isClassifierAvailableInCommon(classifiers, classId)
&& arguments.commonizeWith(next.arguments)
} }
private fun isClassifierAvailableInCommon(classifiers: CirKnownClassifiers, classId: CirEntityId): Boolean { private fun isClassifierAvailableInCommon(classifiers: CirKnownClassifiers, classId: CirEntityId): Boolean {
@@ -64,10 +64,3 @@ private fun isClassifierAvailableInCommon(classifiers: CirKnownClassifiers, clas
return (classifiers.commonizedNodes.classNode(classId)?.commonDeclaration?.invoke() return (classifiers.commonizedNodes.classNode(classId)?.commonDeclaration?.invoke()
?: classifiers.commonizedNodes.typeAliasNode(classId)?.commonDeclaration?.invoke()) != null ?: classifiers.commonizedNodes.typeAliasNode(classId)?.commonDeclaration?.invoke()) != null
} }
private class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) },
extractor = { it },
builder = { it }
)
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.mergedtree.*
internal class CommonizationVisitor( internal class CommonizationVisitor(
private val classifiers: CirKnownClassifiers,
private val root: CirRootNode private val root: CirRootNode
) : CirNodeVisitor<Unit, Unit> { ) : CirNodeVisitor<Unit, Unit> {
override fun visitRootNode(node: CirRootNode, data: Unit) { override fun visitRootNode(node: CirRootNode, data: Unit) {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
interface Commonizer<T, out R> { interface Commonizer<in T, out R> {
val result: R val result: R
fun commonizeWith(next: T): Boolean fun commonizeWith(next: T): Boolean
} }
@@ -6,17 +6,26 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirExtensionReceiver import org.jetbrains.kotlin.commonizer.cir.CirExtensionReceiver
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class ExtensionReceiverCommonizer(classifiers: CirKnownClassifiers) : class ExtensionReceiverCommonizer(
AbstractNullableCommonizer<CirExtensionReceiver, CirExtensionReceiver, CirType, CirType>( private val typeCommonizer: TypeCommonizer
wrappedCommonizerFactory = { TypeCommonizer(classifiers).asCommonizer() }, ) : NullableContextualSingleInvocationCommonizer<CirExtensionReceiver?, ExtensionReceiverCommonizer.Commonized> {
extractor = { it.type },
builder = { receiverType -> class Commonized(val receiver: CirExtensionReceiver?) {
companion object {
val NULL = Commonized(null)
}
}
override fun invoke(values: List<CirExtensionReceiver?>): Commonized? {
if (values.all { it == null }) return Commonized.NULL
if (values.any { it == null }) return null
return Commonized(
CirExtensionReceiver( CirExtensionReceiver(
annotations = emptyList(), annotations = emptyList(),
type = receiverType type = typeCommonizer(values.map { checkNotNull(it).type }) ?: return null
) )
} )
) }
}
@@ -6,37 +6,28 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirFunction import org.jetbrains.kotlin.commonizer.cir.CirFunction
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer<CirFunction>(classifiers) {
private val annotations = AnnotationsCommonizer()
private val modifiers = FunctionModifiersCommonizer()
private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirFunction? {
val valueParameters = valueParameters.result
valueParameters.patchCallables()
class FunctionCommonizer(
private val typeCommonizer: TypeCommonizer,
private val functionOrPropertyBaseCommonizer: FunctionOrPropertyBaseCommonizer,
) : NullableSingleInvocationCommonizer<CirFunction> {
override fun invoke(values: List<CirFunction>): CirFunction? {
if (values.isEmpty()) return null
val functionOrProperty = functionOrPropertyBaseCommonizer(values) ?: return null
val valueParametersResult = CallableValueParametersCommonizer(typeCommonizer).commonize(values) ?: return null
return CirFunction( return CirFunction(
annotations = annotations.result, annotations = AnnotationsCommonizer().commonize(values.map { it.annotations }) ?: return null,
name = name, name = values.first().name,
typeParameters = typeParameters.result, typeParameters = functionOrProperty.typeParameters,
visibility = visibility.result, visibility = functionOrProperty.visibility,
modality = modality.result, modality = functionOrProperty.modality,
containingClass = null, // does not matter containingClass = null, // does not matter
valueParameters = valueParameters.valueParameters, valueParameters = valueParametersResult.valueParameters,
hasStableParameterNames = valueParameters.hasStableParameterNames, hasStableParameterNames = valueParametersResult.hasStableParameterNames,
extensionReceiver = extensionReceiver.result, extensionReceiver = functionOrProperty.extensionReceiver,
returnType = returnType.result ?: return null, returnType = functionOrProperty.returnType,
kind = kind, kind = functionOrProperty.kind,
modifiers = modifiers.result modifiers = FunctionModifiersCommonizer().commonize(values.map { it.modifiers }) ?: return null
) )
} }
}
override fun doCommonizeWith(next: CirFunction): Boolean {
return super.doCommonizeWith(next)
&& annotations.commonizeWith(next.annotations)
&& modifiers.commonizeWith(next.modifiers)
&& valueParameters.commonizeWith(next)
}
}
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
interface NullableContextualSingleInvocationCommonizer<T : Any, R : Any> { interface NullableContextualSingleInvocationCommonizer<T, R : Any> {
operator fun invoke(values: List<T>): R? operator fun invoke(values: List<T>): R?
} }
fun <T : Any, R : Any> NullableContextualSingleInvocationCommonizer<T, R>.asCommonizer(): Commonizer<T, R?> = fun <T, R : Any> NullableContextualSingleInvocationCommonizer<T, R>.asCommonizer(): Commonizer<T, R?> =
object : Commonizer<T, R?> { object : Commonizer<T, R?> {
private val collectedValues = mutableListOf<T>() private val collectedValues = mutableListOf<T>()
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
interface NullableSingleInvocationCommonizer<T : Any> { interface NullableSingleInvocationCommonizer<T> {
operator fun invoke(values: List<T>): T? operator fun invoke(values: List<T>): T?
} }
@@ -9,19 +9,21 @@ import org.jetbrains.kotlin.commonizer.cir.CirConstantValue
import org.jetbrains.kotlin.commonizer.cir.CirProperty import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.cir.CirPropertyGetter import org.jetbrains.kotlin.commonizer.cir.CirPropertyGetter
import org.jetbrains.kotlin.commonizer.core.PropertyCommonizer.ConstCommonizationState.* import org.jetbrains.kotlin.commonizer.core.PropertyCommonizer.ConstCommonizationState.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer<CirProperty>(classifiers) { class PropertyCommonizer(
functionOrPropertyBaseCommonizer: FunctionOrPropertyBaseCommonizer
) : AbstractStandardCommonizer<CirProperty, CirProperty?>() {
private val setter = PropertySetterCommonizer.asNullableCommonizer() private val setter = PropertySetterCommonizer.asNullableCommonizer()
private var isExternal = true private var isExternal = true
private lateinit var constCommonizationState: ConstCommonizationState private lateinit var constCommonizationState: ConstCommonizationState
private val functionOrPropertyBaseCommonizer = functionOrPropertyBaseCommonizer.asCommonizer()
override fun commonizationResult(): CirProperty? { override fun commonizationResult(): CirProperty? {
val modality = modality.result val functionOrPropertyBase = functionOrPropertyBaseCommonizer.result ?: return null
val setter = setter.result?.takeIf { setter -> val setter = setter.result?.takeIf { setter ->
setter !== PropertySetterCommonizer.privateFallbackSetter || modality == Modality.FINAL setter !== PropertySetterCommonizer.privateFallbackSetter || functionOrPropertyBase.modality == Modality.FINAL
} }
val constCommonizationState = constCommonizationState val constCommonizationState = constCommonizationState
@@ -29,15 +31,15 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
return CirProperty( return CirProperty(
annotations = emptyList(), annotations = emptyList(),
name = name, name = functionOrPropertyBase.name,
typeParameters = typeParameters.result, typeParameters = functionOrPropertyBase.typeParameters,
visibility = visibility.result, visibility = functionOrPropertyBase.visibility,
modality = modality, modality = functionOrPropertyBase.modality,
containingClass = null, // does not matter containingClass = null, // does not matter
isExternal = isExternal, isExternal = isExternal,
extensionReceiver = extensionReceiver.result, extensionReceiver = functionOrPropertyBase.extensionReceiver,
returnType = returnType.result ?: return null, returnType = functionOrPropertyBase.returnType,
kind = kind, kind = functionOrPropertyBase.kind,
isVar = setter != null, isVar = setter != null,
isLateInit = false, isLateInit = false,
isConst = constCompileTimeInitializer != null, isConst = constCompileTimeInitializer != null,
@@ -51,8 +53,6 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
} }
override fun initialize(first: CirProperty) { override fun initialize(first: CirProperty) {
super.initialize(first)
constCommonizationState = if (first.isConst) { constCommonizationState = if (first.isConst) {
first.compileTimeInitializer.takeIf { it != CirConstantValue.NullValue }?.let(::ConstSameValue) ?: NonConst first.compileTimeInitializer.takeIf { it != CirConstantValue.NullValue }?.let(::ConstSameValue) ?: NonConst
} else { } else {
@@ -89,7 +89,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
this.constCommonizationState = NonConst this.constCommonizationState = NonConst
} }
val result = super.doCommonizeWith(next) val result = functionOrPropertyBaseCommonizer.commonizeWith(next)
&& setter.commonizeWith(next.setter) && setter.commonizeWith(next.setter)
if (result) { if (result) {
@@ -0,0 +1,23 @@
/*
* 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.CirFunctionOrProperty
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.cir.CirType
class ReturnTypeCommonizer(
private val typeCommonizer: TypeCommonizer,
) : NullableContextualSingleInvocationCommonizer<CirFunctionOrProperty, CirType> {
override fun invoke(values: List<CirFunctionOrProperty>): CirType? {
if (values.isEmpty()) return null
val isTopLevel = values.all { it.containingClass == null }
val isCovariant = values.none { it is CirProperty && it.isVar }
return typeCommonizer
.withOptions { withCovariantNullabilityCommonizationEnabled(isTopLevel && isCovariant) }
.invoke(values.map { it.returnType })
}
}
@@ -13,17 +13,18 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class TypeAliasCommonizer( class TypeAliasCommonizer(
private val classifiers: CirKnownClassifiers private val typeCommonizer: TypeCommonizer,
private val classifiers: CirKnownClassifiers,
) : NullableSingleInvocationCommonizer<CirTypeAlias> { ) : NullableSingleInvocationCommonizer<CirTypeAlias> {
override fun invoke(values: List<CirTypeAlias>): CirTypeAlias? { override fun invoke(values: List<CirTypeAlias>): CirTypeAlias? {
if (values.isEmpty()) return null if (values.isEmpty()) return null
val name = values.map { it.name }.distinct().singleOrNull() ?: return null val name = values.map { it.name }.distinct().singleOrNull() ?: return null
val typeParameters = TypeParameterListCommonizer(classifiers).commonize(values.map { it.typeParameters }) ?: return null val typeParameters = TypeParameterListCommonizer(typeCommonizer).commonize(values.map { it.typeParameters }) ?: return null
val underlyingType = TypeCommonizer(classifiers, TypeCommonizer.Options.default.withOptimisticNumberTypeCommonizationEnabled()) val underlyingType = typeCommonizer.withOptions { withOptimisticNumberTypeCommonizationEnabled() }
.asCommonizer().commonize(values.map { it.underlyingType }) as? CirClassOrTypeAliasType ?: return null .invoke(values.map { it.underlyingType }) as? CirClassOrTypeAliasType ?: return null
val visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null val visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null
@@ -11,15 +11,14 @@ import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion.
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
internal class TypeAliasTypeCommonizer( internal class TypeAliasTypeCommonizer(
private val typeCommonizer: TypeCommonizer,
private val classifiers: CirKnownClassifiers, private val classifiers: CirKnownClassifiers,
options: TypeCommonizer.Options ) : AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: CirEntityId private lateinit var typeAliasId: CirEntityId
private val arguments = TypeArgumentListCommonizer(classifiers) private val arguments = TypeArgumentListCommonizer(typeCommonizer)
private val underlyingTypeArguments = TypeArgumentListCommonizer(classifiers) private val underlyingTypeArguments = TypeArgumentListCommonizer(typeCommonizer)
private val isMarkedNullable = TypeNullabilityCommonizer(options).asCommonizer() private val isMarkedNullable = TypeNullabilityCommonizer(typeCommonizer.options).asCommonizer()
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
override fun commonizationResult() = override fun commonizationResult() =
@@ -47,7 +46,7 @@ internal class TypeAliasTypeCommonizer(
is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier) is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier)
is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier) is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier)
null -> { null -> {
val underlyingType = computeSuitableUnderlyingType(classifiers, next.underlyingType) ?: return false val underlyingType = computeSuitableUnderlyingType(classifiers, typeCommonizer, next.underlyingType) ?: return false
CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(underlyingType) CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(underlyingType)
} }
else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier") else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier")
@@ -8,30 +8,22 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirRegularTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirRegularTypeProjection
import org.jetbrains.kotlin.commonizer.cir.CirStarTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirStarTypeProjection
import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.utils.safeCastValues
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull
class TypeArgumentCommonizer( class TypeArgumentCommonizer(
classifiers: CirKnownClassifiers private val typeCommonizer: TypeCommonizer
) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() { ) : NullableSingleInvocationCommonizer<CirTypeProjection> {
private var isStar = false override fun invoke(values: List<CirTypeProjection>): CirTypeProjection? {
private lateinit var projectionKind: Variance /* All values are star projections */
private val type = TypeCommonizer(classifiers).asCommonizer() values.safeCastValues<CirTypeProjection, CirStarTypeProjection>()?.let { return CirStarTypeProjection }
override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirRegularTypeProjection( /* All values are regular type projections */
projectionKind = projectionKind, val projections = values.safeCastValues<CirTypeProjection, CirRegularTypeProjection>() ?: return null
type = type.result
)
override fun initialize(first: CirTypeProjection) { return CirRegularTypeProjection(
when (first) { projectionKind = projections.singleDistinctValueOrNull { it.projectionKind } ?: return null,
is CirStarTypeProjection -> isStar = true type = typeCommonizer(projections.map { it.type }) ?: return null
is CirRegularTypeProjection -> projectionKind = first.projectionKind )
}
}
override fun doCommonizeWith(next: CirTypeProjection) = when (next) {
is CirStarTypeProjection -> isStar
is CirRegularTypeProjection -> !isStar && projectionKind == next.projectionKind && type.commonizeWith(next.type)
} }
} }
@@ -6,8 +6,7 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>( class TypeArgumentListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) } singleElementCommonizerFactory = { TypeArgumentCommonizer(typeCommonizer).asCommonizer() }
) )
@@ -7,23 +7,27 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.safeCastValues
class TypeCommonizer( class TypeCommonizer(
private val classifiers: CirKnownClassifiers, private val classifiers: CirKnownClassifiers,
private val options: Options = Options.default val options: Options = Options.default
) : AssociativeCommonizer<CirType> { ) : NullableSingleInvocationCommonizer<CirType> {
override fun commonize(first: CirType, second: CirType): CirType? {
if (first is CirClassOrTypeAliasType && second is CirClassOrTypeAliasType) { private val classOrTypeAliasTypeCommonizer = ClassOrTypeAliasTypeCommonizer(this)
return ClassOrTypeAliasTypeCommonizer(classifiers, options).commonize(first, second) private val flexibleTypeCommonizer = FlexibleTypeAssociativeCommonizer(this)
override fun invoke(values: List<CirType>): CirType? {
values.safeCastValues<CirType, CirClassOrTypeAliasType>()?.let { types ->
return classOrTypeAliasTypeCommonizer(types)
} }
if (first is CirTypeParameterType && second is CirTypeParameterType) { values.safeCastValues<CirType, CirTypeParameterType>()?.let { types ->
return TypeParameterTypeCommonizer.commonize(first, second) return TypeParameterTypeCommonizer.commonize(types)
} }
if (first is CirFlexibleType && second is CirFlexibleType) { values.safeCastValues<CirType, CirFlexibleType>()?.let { types ->
return FlexibleTypeAssociativeCommonizer(classifiers, options).commonize(first, second) return flexibleTypeCommonizer(types)
} }
return null return null
@@ -48,6 +52,15 @@ class TypeCommonizer(
val default = Options() val default = Options()
} }
} }
fun withOptions(options: Options): TypeCommonizer {
return if (this.options == options) this
else TypeCommonizer(classifiers, options)
}
inline fun withOptions(createNewOptions: Options.() -> Options): TypeCommonizer {
return withOptions(options.createNewOptions())
}
} }
private object TypeParameterTypeCommonizer : AssociativeCommonizer<CirTypeParameterType> { private object TypeParameterTypeCommonizer : AssociativeCommonizer<CirTypeParameterType> {
@@ -60,14 +73,11 @@ private object TypeParameterTypeCommonizer : AssociativeCommonizer<CirTypeParame
} }
private class FlexibleTypeAssociativeCommonizer( private class FlexibleTypeAssociativeCommonizer(
private val classifiers: CirKnownClassifiers, private val typeCommonizer: TypeCommonizer
private val options: TypeCommonizer.Options ) : NullableSingleInvocationCommonizer<CirFlexibleType> {
) : AssociativeCommonizer<CirFlexibleType> { override fun invoke(values: List<CirFlexibleType>): CirFlexibleType? {
override fun commonize(first: CirFlexibleType, second: CirFlexibleType): CirFlexibleType? { val lowerBound = typeCommonizer(values.map { it.lowerBound }) ?: return null
val upperBound = typeCommonizer(values.map { it.upperBound }) ?: return null
val lowerBound = TypeCommonizer(classifiers, options).commonize(first.lowerBound, second.lowerBound) ?: return null
val upperBound = TypeCommonizer(classifiers, options).commonize(first.upperBound, second.upperBound) ?: return null
return CirFlexibleType( return CirFlexibleType(
lowerBound = lowerBound as CirSimpleType, lowerBound = lowerBound as CirSimpleType,
upperBound = upperBound as CirSimpleType upperBound = upperBound as CirSimpleType
@@ -8,14 +8,13 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirType import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() { class TypeParameterCommonizer(typeCommonizer: TypeCommonizer) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() {
private lateinit var name: CirName private lateinit var name: CirName
private var isReified = false private var isReified = false
private lateinit var variance: Variance private lateinit var variance: Variance
private val upperBounds = TypeParameterUpperBoundsCommonizer(classifiers) private val upperBounds = TypeParameterUpperBoundsCommonizer(typeCommonizer)
override fun commonizationResult() = CirTypeParameter( override fun commonizationResult() = CirTypeParameter(
annotations = emptyList(), annotations = emptyList(),
@@ -38,6 +37,6 @@ class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStanda
&& upperBounds.commonizeWith(next.upperBounds) && upperBounds.commonizeWith(next.upperBounds)
} }
private class TypeParameterUpperBoundsCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirType, CirType>( private class TypeParameterUpperBoundsCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer<CirType, CirType>(
singleElementCommonizerFactory = { TypeCommonizer(classifiers).asCommonizer() } singleElementCommonizerFactory = { typeCommonizer.asCommonizer() }
) )
@@ -6,8 +6,7 @@
package org.jetbrains.kotlin.commonizer.core package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class TypeParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeParameter, CirTypeParameter>( class TypeParameterListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer<CirTypeParameter, CirTypeParameter>(
singleElementCommonizerFactory = { TypeParameterCommonizer(classifiers) } singleElementCommonizerFactory = { TypeParameterCommonizer(typeCommonizer) }
) )
@@ -8,25 +8,27 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirType import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.isNull import org.jetbrains.kotlin.commonizer.utils.isNull
class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirValueParameter, CirValueParameter>() { class ValueParameterCommonizer(returnTypeCommonizer: TypeCommonizer) :
AbstractStandardCommonizer<CirValueParameter, CirValueParameter?>() {
private lateinit var name: CirName private lateinit var name: CirName
private val returnType = TypeCommonizer(classifiers).asCommonizer() private val returnTypeCommonizer = returnTypeCommonizer.asCommonizer()
private var varargElementType: CirType? = null private var varargElementType: CirType? = null
private var isCrossinline = true private var isCrossinline = true
private var isNoinline = true private var isNoinline = true
override fun commonizationResult() = CirValueParameter.createInterned( override fun commonizationResult(): CirValueParameter? {
annotations = emptyList(), return CirValueParameter.createInterned(
name = name, annotations = emptyList(),
returnType = returnType.result, name = name,
varargElementType = varargElementType, returnType = returnTypeCommonizer.result ?: return null,
declaresDefaultValue = false, varargElementType = varargElementType,
isCrossinline = isCrossinline, declaresDefaultValue = false,
isNoinline = isNoinline isCrossinline = isCrossinline,
) isNoinline = isNoinline
)
}
override fun initialize(first: CirValueParameter) { override fun initialize(first: CirValueParameter) {
name = first.name name = first.name
@@ -38,7 +40,7 @@ class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStand
override fun doCommonizeWith(next: CirValueParameter): Boolean { override fun doCommonizeWith(next: CirValueParameter): Boolean {
val result = !next.declaresDefaultValue val result = !next.declaresDefaultValue
&& varargElementType.isNull() == next.varargElementType.isNull() && varargElementType.isNull() == next.varargElementType.isNull()
&& returnType.commonizeWith(next.returnType) && returnTypeCommonizer.commonizeWith(next.returnType)
if (result) { if (result) {
isCrossinline = isCrossinline && next.isCrossinline isCrossinline = isCrossinline && next.isCrossinline
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
class ValueParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirValueParameter, CirValueParameter>( class ValueParameterListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer<CirValueParameter, CirValueParameter>(
singleElementCommonizerFactory = { ValueParameterCommonizer(classifiers) } singleElementCommonizerFactory = { ValueParameterCommonizer(typeCommonizer) }
) { ) {
fun overwriteNames(names: List<CirName>) { fun overwriteNames(names: List<CirName>) {
forEachSingleElementCommonizer { index, singleElementCommonizer -> forEachSingleElementCommonizer { index, singleElementCommonizer ->
@@ -13,24 +13,25 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
internal tailrec fun computeSuitableUnderlyingType( internal tailrec fun computeSuitableUnderlyingType(
classifiers: CirKnownClassifiers, classifiers: CirKnownClassifiers,
typeCommonizer: TypeCommonizer,
underlyingType: CirClassOrTypeAliasType underlyingType: CirClassOrTypeAliasType
): CirClassOrTypeAliasType? { ): CirClassOrTypeAliasType? {
return when (underlyingType) { return when (underlyingType) {
is CirClassType -> underlyingType.withCommonizedArguments(classifiers) is CirClassType -> underlyingType.withCommonizedArguments(typeCommonizer)
is CirTypeAliasType -> is CirTypeAliasType ->
if (classifiers.commonDependencies.hasClassifier(underlyingType.classifierId) || if (classifiers.commonDependencies.hasClassifier(underlyingType.classifierId) ||
classifiers.commonizedNodes.typeAliasNode(underlyingType.classifierId)?.commonDeclaration?.invoke() != null classifiers.commonizedNodes.typeAliasNode(underlyingType.classifierId)?.commonDeclaration?.invoke() != null
) underlyingType.withCommonizedArguments(classifiers) ) underlyingType.withCommonizedArguments(typeCommonizer)
else computeSuitableUnderlyingType(classifiers, underlyingType.underlyingType) else computeSuitableUnderlyingType(classifiers, typeCommonizer, underlyingType.underlyingType)
} }
} }
private fun CirClassType.withCommonizedArguments(classifiers: CirKnownClassifiers): CirClassType? { private fun CirClassType.withCommonizedArguments(typeCommonizer: TypeCommonizer): CirClassType? {
val existingArguments = arguments val existingArguments = arguments
val newArguments = existingArguments.toCommonizedArguments(classifiers) ?: return null val newArguments = existingArguments.toCommonizedArguments(typeCommonizer) ?: return null
val existingOuterType = outerType val existingOuterType = outerType
val newOuterType = existingOuterType?.let { it.withCommonizedArguments(classifiers) ?: return null } val newOuterType = existingOuterType?.let { it.withCommonizedArguments(typeCommonizer) ?: return null }
return if (newArguments !== existingArguments || newOuterType !== existingOuterType) return if (newArguments !== existingArguments || newOuterType !== existingOuterType)
CirClassType.createInterned( CirClassType.createInterned(
@@ -44,14 +45,14 @@ private fun CirClassType.withCommonizedArguments(classifiers: CirKnownClassifier
this this
} }
private fun CirTypeAliasType.withCommonizedArguments(classifiers: CirKnownClassifiers): CirTypeAliasType? { private fun CirTypeAliasType.withCommonizedArguments(typeCommonizer: TypeCommonizer): CirTypeAliasType? {
val existingArguments = arguments val existingArguments = arguments
val newArguments = existingArguments.toCommonizedArguments(classifiers) ?: return null val newArguments = existingArguments.toCommonizedArguments(typeCommonizer) ?: return null
val existingUnderlyingType = underlyingType val existingUnderlyingType = underlyingType
val newUnderlyingType = when (existingUnderlyingType) { val newUnderlyingType = when (existingUnderlyingType) {
is CirClassType -> existingUnderlyingType.withCommonizedArguments(classifiers) is CirClassType -> existingUnderlyingType.withCommonizedArguments(typeCommonizer)
is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments(classifiers) is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments(typeCommonizer)
} ?: return null } ?: return null
return if (newArguments !== existingArguments || newUnderlyingType !== existingUnderlyingType) return if (newArguments !== existingArguments || newUnderlyingType !== existingUnderlyingType)
@@ -66,8 +67,6 @@ private fun CirTypeAliasType.withCommonizedArguments(classifiers: CirKnownClassi
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
private inline fun List<CirTypeProjection>.toCommonizedArguments(classifiers: CirKnownClassifiers): List<CirTypeProjection>? = private inline fun List<CirTypeProjection>.toCommonizedArguments(typeCommonizer: TypeCommonizer): List<CirTypeProjection>? =
if (isEmpty()) if (isEmpty()) this
this else TypeArgumentListCommonizer(typeCommonizer).let { if (it.commonizeWith(this)) it.result else null }
else
TypeArgumentListCommonizer(classifiers).let { if (it.commonizeWith(this)) it.result else null }
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
import org.jetbrains.kotlin.commonizer.transformer.AliasedTypeSubstitutor
import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.TypeSubstitutionCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.UnderscoredTypeAliasTypeSubstitutor
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer
import org.jetbrains.kotlin.commonizer.tree.mergeCirTree import org.jetbrains.kotlin.commonizer.tree.mergeCirTree
@@ -65,17 +62,7 @@ internal fun commonizeTarget(
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree) InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
TypeSubstitutionCirNodeTransformer( mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
parameters.storageManager, classifiers,
AliasedTypeSubstitutor(classifiers.commonDependencies, classifiers.classifierIndices)
).invoke(mergedTree)
TypeSubstitutionCirNodeTransformer(
parameters.storageManager, classifiers,
UnderscoredTypeAliasTypeSubstitutor(classifiers.classifierIndices)
).invoke(mergedTree)
mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit)
return mergedTree return mergedTree
} }
@@ -57,7 +57,7 @@ internal fun buildPropertyNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
nodeRelationship = nodeRelationship, nodeRelationship = nodeRelationship,
commonizerProducer = { PropertyCommonizer(classifiers) }, commonizerProducer = { PropertyCommonizer(FunctionOrPropertyBaseCommonizer(TypeCommonizer(classifiers))) },
nodeProducer = ::CirPropertyNode nodeProducer = ::CirPropertyNode
) )
@@ -70,7 +70,10 @@ internal fun buildFunctionNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
nodeRelationship = nodeRelationship, nodeRelationship = nodeRelationship,
commonizerProducer = { FunctionCommonizer(classifiers) }, commonizerProducer = {
val typeCommonizer = TypeCommonizer(classifiers)
FunctionCommonizer(typeCommonizer, FunctionOrPropertyBaseCommonizer(typeCommonizer)).asCommonizer()
},
nodeProducer = ::CirFunctionNode nodeProducer = ::CirFunctionNode
) )
@@ -84,7 +87,10 @@ internal fun buildClassNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
nodeRelationship = nodeRelationship, nodeRelationship = nodeRelationship,
commonizerProducer = { ClassCommonizer(classifiers) }, commonizerProducer = {
val typeCommonizer = TypeCommonizer(classifiers)
ClassCommonizer(typeCommonizer, ClassSuperTypeCommonizer(classifiers, typeCommonizer))
},
recursionMarker = CirClassRecursionMarker, recursionMarker = CirClassRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration -> nodeProducer = { targetDeclarations, commonDeclaration ->
CirClassNode(classId, targetDeclarations, commonDeclaration).also { CirClassNode(classId, targetDeclarations, commonDeclaration).also {
@@ -103,7 +109,7 @@ internal fun buildClassConstructorNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
nodeRelationship = nodeRelationship, nodeRelationship = nodeRelationship,
commonizerProducer = { ClassConstructorCommonizer(classifiers) }, commonizerProducer = { ClassConstructorCommonizer(TypeCommonizer(classifiers)) },
nodeProducer = ::CirClassConstructorNode nodeProducer = ::CirClassConstructorNode
) )
@@ -116,7 +122,7 @@ internal fun buildTypeAliasNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
nodeRelationship = null, nodeRelationship = null,
commonizerProducer = { TypeAliasCommonizer(classifiers).asCommonizer() }, commonizerProducer = { TypeAliasCommonizer(TypeCommonizer(classifiers), classifiers).asCommonizer() },
recursionMarker = CirTypeAliasRecursionMarker, recursionMarker = CirTypeAliasRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration -> nodeProducer = { targetDeclarations, commonDeclaration ->
CirTypeAliasNode(typeAliasId, targetDeclarations, commonDeclaration).also { CirTypeAliasNode(typeAliasId, targetDeclarations, commonDeclaration).also {
@@ -145,12 +151,13 @@ private fun <T : CirDeclaration, R : CirDeclaration, N : CirNode<T, R>> buildNod
return nodeProducer(targetDeclarations, commonLazyValue) return nodeProducer(targetDeclarations, commonLazyValue)
} }
@Suppress("UNCHECKED_CAST")
internal fun <T : Any, R> commonize( internal fun <T : Any, R> commonize(
targetDeclarations: CommonizedGroup<T>, targetDeclarations: CommonizedGroup<T>,
commonizer: Commonizer<T, R> commonizer: Commonizer<T, R>
): R? { ): R? {
if (targetDeclarations.any { it == null }) return null if (targetDeclarations.any { it == null }) return null
return commonizer.commonize(targetDeclarations.filterNotNull()) return commonizer.commonize(targetDeclarations as List<T>)
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@@ -34,6 +34,10 @@ internal inline fun <T, R> Array<T>.compactMap(transform: (T) -> R): List<R> =
else -> mapTo(ArrayList(size), transform) else -> mapTo(ArrayList(size), transform)
} }
internal inline fun <T, R : Any> Array<T>.compactMapNotNull(transform: (T) -> R): List<R> {
return mapNotNullTo(ArrayList<R>(size), transform).also { it.trimToSize() }
}
internal inline fun <T, reified R : Any> Collection<T>.compactMapNotNull(transform: (T) -> R?): List<R> = internal inline fun <T, reified R : Any> Collection<T>.compactMapNotNull(transform: (T) -> R?): List<R> =
if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact() if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact()
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.commonizer.utils.mockClassType import org.jetbrains.kotlin.commonizer.utils.mockClassType
import org.junit.Test import org.junit.Test
class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionReceiver?, CirExtensionReceiver?>() { class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionReceiver?, ExtensionReceiverCommonizer.Commonized?>() {
@Test @Test
fun nullReceiver() = doTestSuccess( fun nullReceiver() = doTestSuccess(
@@ -20,7 +20,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionRecei
@Test @Test
fun sameReceiver() = doTestSuccess( fun sameReceiver() = doTestSuccess(
expected = mockExtensionReceiver("kotlin/String"), expected = ExtensionReceiverCommonizer.Commonized(mockExtensionReceiver("kotlin/String")),
mockExtensionReceiver("kotlin/String"), mockExtensionReceiver("kotlin/String"),
mockExtensionReceiver("kotlin/String"), mockExtensionReceiver("kotlin/String"),
mockExtensionReceiver("kotlin/String") mockExtensionReceiver("kotlin/String")
@@ -47,7 +47,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionRecei
mockExtensionReceiver("kotlin/String") mockExtensionReceiver("kotlin/String")
) )
override fun createCommonizer() = ExtensionReceiverCommonizer(MOCK_CLASSIFIERS) override fun createCommonizer() = ExtensionReceiverCommonizer(TypeCommonizer(MOCK_CLASSIFIERS)).asCommonizer()
} }
private fun mockExtensionReceiver(receiverClassId: String) = CirExtensionReceiver( private fun mockExtensionReceiver(receiverClassId: String) = CirExtensionReceiver(
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() { class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType?>() {
private lateinit var classifiers: CirKnownClassifiers private lateinit var classifiers: CirKnownClassifiers
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.types.Variance
import org.junit.Test import org.junit.Test
class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter>() { class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter>() {
override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS) override fun createCommonizer() = TypeParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
@Test @Test
fun allAreReified() = doTestSuccess( fun allAreReified() = doTestSuccess(
@@ -108,7 +108,7 @@ class TypeParameterListCommonizerTest : AbstractCommonizerTest<List<CirTypeParam
) )
) )
override fun createCommonizer() = TypeParameterListCommonizer(MOCK_CLASSIFIERS) override fun createCommonizer() = TypeParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
private companion object { private companion object {
fun mockTypeParams(vararg params: Pair<String, String>): List<CirTypeParameter> { fun mockTypeParams(vararg params: Pair<String, String>): List<CirTypeParameter> {
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.commonizer.utils.mockClassType import org.jetbrains.kotlin.commonizer.utils.mockClassType
import org.junit.Test import org.junit.Test
class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, CirValueParameter>() { class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, CirValueParameter?>() {
@Test @Test
fun sameReturnType1() = doTestSuccess( fun sameReturnType1() = doTestSuccess(
@@ -137,7 +137,7 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, C
mockValueParam("kotlin/String", declaresDefaultValue = true) mockValueParam("kotlin/String", declaresDefaultValue = true)
) )
override fun createCommonizer() = ValueParameterCommonizer(MOCK_CLASSIFIERS) override fun createCommonizer() = ValueParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun areEqual(a: CirValueParameter?, b: CirValueParameter?) = override fun areEqual(a: CirValueParameter?, b: CirValueParameter?) =
(a === b) || (a != null && b != null && areEqual(MOCK_CLASSIFIERS, a, b)) (a === b) || (a != null && b != null && areEqual(MOCK_CLASSIFIERS, a, b))
@@ -149,7 +149,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValuePar
) )
) )
override fun createCommonizer() = ValueParameterListCommonizer(MOCK_CLASSIFIERS) override fun createCommonizer() = ValueParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun areEqual(a: List<CirValueParameter>?, b: List<CirValueParameter>?): Boolean { override fun areEqual(a: List<CirValueParameter>?, b: List<CirValueParameter>?): Boolean {
if (a === b) if (a === b)