From 97e37243c69cee58cae961a841ba1f7a944dce04 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Thu, 9 Sep 2021 11:23:49 +0200 Subject: [PATCH] [Commonizer] Move type commonization to single invocation commonizer ^KT-48288 --- .../AbstractFunctionOrPropertyCommonizer.kt | 80 ++++++++++--------- .../commonizer/core/AbstractListCommonizer.kt | 11 ++- .../commonizer/core/AssociativeCommonizer.kt | 6 ++ .../core/CallableValueParametersCommonizer.kt | 5 +- .../kotlin/commonizer/core/ClassCommonizer.kt | 30 +++---- .../core/ClassConstructorCommonizer.kt | 17 ++-- .../core/ClassOrTypeAliasTypeCommonizer.kt | 14 +++- .../core/ClassSuperTypeCommonizer.kt | 7 +- .../commonizer/core/ClassTypeCommonizer.kt | 69 +++++++--------- .../commonizer/core/CommonizationVisitor.kt | 1 - .../kotlin/commonizer/core/Commonizer.kt | 2 +- .../core/ExtensionReceiverCommonizer.kt | 29 ++++--- .../commonizer/core/FunctionCommonizer.kt | 49 +++++------- ...bleContextualSingleInvocationCommonizer.kt | 4 +- .../NullableSingleInvocationCommonizer.kt | 2 +- .../commonizer/core/PropertyCommonizer.kt | 28 +++---- .../commonizer/core/ReturnTypeCommonizer.kt | 23 ++++++ .../commonizer/core/TypeAliasCommonizer.kt | 9 ++- .../core/TypeAliasTypeCommonizer.kt | 13 ++- .../commonizer/core/TypeArgumentCommonizer.kt | 34 +++----- .../core/TypeArgumentListCommonizer.kt | 5 +- .../kotlin/commonizer/core/TypeCommonizer.kt | 46 ++++++----- .../core/TypeParameterCommonizer.kt | 9 +-- .../core/TypeParameterListCommonizer.kt | 5 +- .../core/ValueParameterCommonizer.kt | 28 ++++--- .../core/ValueParameterListCommonizer.kt | 5 +- .../kotlin/commonizer/core/typeAliasUtils.kt | 29 ++++--- .../org/jetbrains/kotlin/commonizer/facade.kt | 15 +--- .../commonizer/mergedtree/nodeBuilders.kt | 19 +++-- .../jetbrains/kotlin/commonizer/utils/misc.kt | 4 + .../core/ExtensionReceiverCommonizerTest.kt | 6 +- .../commonizer/core/TypeCommonizerTest.kt | 2 +- .../core/TypeParameterCommonizerTest.kt | 2 +- .../core/TypeParameterListCommonizerTest.kt | 2 +- .../core/ValueParameterCommonizerTest.kt | 4 +- .../core/ValueParameterListCommonizerTest.kt | 2 +- 36 files changed, 320 insertions(+), 296 deletions(-) create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ReturnTypeCommonizer.kt diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractFunctionOrPropertyCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractFunctionOrPropertyCommonizer.kt index ef5744fd2d7..cbf00090894 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractFunctionOrPropertyCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractFunctionOrPropertyCommonizer.kt @@ -5,51 +5,53 @@ package org.jetbrains.kotlin.commonizer.core -import org.jetbrains.kotlin.commonizer.cir.CirFunctionOrProperty -import org.jetbrains.kotlin.commonizer.cir.CirName -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.commonizer.cir.* +import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility -abstract class AbstractFunctionOrPropertyCommonizer( - classifiers: CirKnownClassifiers -) : AbstractStandardCommonizer() { - protected lateinit var name: CirName - protected val modality = ModalityCommonizer() - 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) +class FunctionOrPropertyBaseCommonizer( + private val typeCommonizer: TypeCommonizer, + private val extensionReceiverCommonizer: ExtensionReceiverCommonizer = ExtensionReceiverCommonizer(typeCommonizer), + private val returnTypeCommonizer: ReturnTypeCommonizer = ReturnTypeCommonizer(typeCommonizer), +) : NullableContextualSingleInvocationCommonizer { - override fun initialize(first: T) { - name = first.name - kind = first.kind - } + data class FunctionOrProperty( + val name: CirName, + val kind: CallableMemberDescriptor.Kind, + val modality: Modality, + val visibility: Visibility, + val extensionReceiver: CirExtensionReceiver?, + val returnType: CirType, + val typeParameters: List + ) - override fun doCommonizeWith(next: T): Boolean = - next.kind != DELEGATION // delegated members should not be commonized - && (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 { - override fun invoke(values: List): CirType? { + override fun invoke(values: List): FunctionOrProperty? { + /* Preconditions */ if (values.isEmpty()) return null - val isTopLevel = values.all { it.containingClass == null } - val isCovariant = values.none { it is CirProperty && it.isVar } - return TypeCommonizer(classifiers, default.withCovariantNullabilityCommonizationEnabled(isTopLevel && isCovariant)) - .asCommonizer().commonize(values.map { it.returnType }) + + // delegated members should not be commonized + if (values.any { value -> value.kind == DELEGATION }) { + 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 + ) } } + diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractListCommonizer.kt index 8c80ed4a0b9..9b00be5be08 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractListCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AbstractListCommonizer.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.commonizer.core 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 @@ -16,14 +15,14 @@ import org.jetbrains.kotlin.commonizer.utils.compactMap * Input: N lists of [CirType] * Output: list of [CirType] */ -abstract class AbstractListCommonizer( - private val singleElementCommonizerFactory: (Int) -> Commonizer +abstract class AbstractListCommonizer( + private val singleElementCommonizerFactory: (Int) -> Commonizer ) : Commonizer, List> { - private var commonizers: Array>? = null + private var commonizers: Array>? = null private var error = false final override val result: List - get() = checkState(commonizers, error).compactMap { it.result } + get() = checkState(commonizers, error).mapNotNull { it.result } final override fun commonizeWith(next: List): Boolean { if (error) @@ -53,7 +52,7 @@ abstract class AbstractListCommonizer( return !error } - protected fun forEachSingleElementCommonizer(action: (index: Int, Commonizer) -> Unit) { + protected fun forEachSingleElementCommonizer(action: (index: Int, Commonizer) -> Unit) { val commonizers = commonizers ?: failInEmptyState() commonizers.forEachIndexed(action) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AssociativeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AssociativeCommonizer.kt index ab42fbca591..305b81c152b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AssociativeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/AssociativeCommonizer.kt @@ -9,6 +9,12 @@ interface AssociativeCommonizer { fun commonize(first: T, second: T): T? } +fun AssociativeCommonizer.commonize(values: List): T? { + if (values.isEmpty()) return null + if (values.size == 1) return values.first() + return values.reduce { acc, next -> commonize(acc, next) ?: return null } +} + fun AssociativeCommonizer.asCommonizer(): AssociativeCommonizerAdapter = AssociativeCommonizerAdapter(this) open class AssociativeCommonizerAdapter( diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CallableValueParametersCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CallableValueParametersCommonizer.kt index 3ac4142f5fc..da9a4280e93 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CallableValueParametersCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CallableValueParametersCommonizer.kt @@ -12,12 +12,11 @@ import org.jetbrains.kotlin.commonizer.cir.CirName 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.patchCallables -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.utils.compactMapIndexed import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation class CallableValueParametersCommonizer( - classifiers: CirKnownClassifiers + typeCommonizer: TypeCommonizer, ) : Commonizer { class Result( val hasStableParameterNames: Boolean, @@ -116,7 +115,7 @@ class CallableValueParametersCommonizer( } } - private val valueParameters = ValueParameterListCommonizer(classifiers) + private val valueParameters = ValueParameterListCommonizer(typeCommonizer) private val callables: MutableList = mutableListOf() private var hasStableParameterNames = true private var valueParameterNames: ValueParameterNames? = null diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassCommonizer.kt index 6ffe68bd64f..72110a84b11 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassCommonizer.kt @@ -7,27 +7,29 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirClass import org.jetbrains.kotlin.commonizer.cir.CirName -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.descriptors.ClassKind -class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer() { +class ClassCommonizer internal constructor( + typeCommonizer: TypeCommonizer, + supertypesCommonizer: ClassSuperTypeCommonizer +) : AbstractStandardCommonizer() { private lateinit var name: CirName 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 isValue = 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( annotations = emptyList(), name = name, - typeParameters = typeParameters.result, - supertypes = supertypes.result, - visibility = visibility.result, - modality = modality.result, + typeParameters = typeParameterListCommonizer.result, + supertypes = supertypesCommonizer.result, + visibility = visibilityCommonizer.result, + modality = modalityCommonizer.result, kind = kind, companion = null, isCompanion = isCompanion, @@ -50,8 +52,8 @@ class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommon && isInner == next.isInner && isValue == next.isValue && isCompanion == next.isCompanion - && modality.commonizeWith(next.modality) - && visibility.commonizeWith(next) - && typeParameters.commonizeWith(next.typeParameters) - && supertypes.commonizeWith(next.supertypes) + && modalityCommonizer.commonizeWith(next.modality) + && visibilityCommonizer.commonizeWith(next) + && typeParameterListCommonizer.commonizeWith(next.typeParameters) + && supertypesCommonizer.commonizeWith(next.supertypes) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassConstructorCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassConstructorCommonizer.kt index 564f31e5992..468af68f8fd 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassConstructorCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassConstructorCommonizer.kt @@ -7,26 +7,25 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirClassConstructor 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.Modality class ClassConstructorCommonizer( - classifiers: CirKnownClassifiers + typeCommonizer: TypeCommonizer, ) : AbstractStandardCommonizer() { private var isPrimary = false private val visibility = VisibilityCommonizer.equalizing() - private val typeParameters = TypeParameterListCommonizer(classifiers) - private val valueParameters = CallableValueParametersCommonizer(classifiers) - private val annotationsCommonizer = AnnotationsCommonizer() + private val typeParameterListCommonizer = TypeParameterListCommonizer(typeCommonizer) + private val valueParametersCommonizer = CallableValueParametersCommonizer(typeCommonizer) + private val annotationsCommonizer: AnnotationsCommonizer = AnnotationsCommonizer() override fun commonizationResult(): CirClassConstructor { - val valueParameters = valueParameters.result + val valueParameters = valueParametersCommonizer.result valueParameters.patchCallables() return CirClassConstructor.create( annotations = annotationsCommonizer.result, - typeParameters = typeParameters.result, + typeParameters = typeParameterListCommonizer.result, visibility = visibility.result, containingClass = CONTAINING_CLASS_DOES_NOT_MATTER, // does not matter 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) && isPrimary == next.isPrimary && visibility.commonizeWith(next) - && typeParameters.commonizeWith(next.typeParameters) - && valueParameters.commonizeWith(next) + && typeParameterListCommonizer.commonizeWith(next.typeParameters) + && valueParametersCommonizer.commonizeWith(next) && annotationsCommonizer.commonizeWith(next.annotations) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt index f8546af6d80..f880d2eae87 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt @@ -8,13 +8,16 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirClassOrTypeAliasType import org.jetbrains.kotlin.commonizer.cir.CirClassType import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasType -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers internal class ClassOrTypeAliasTypeCommonizer( - private val classifiers: CirKnownClassifiers, - private val options: TypeCommonizer.Options -) : AssociativeCommonizer { + private val typeCommonizer: TypeCommonizer +) : NullableSingleInvocationCommonizer { + override fun invoke(values: List): CirClassOrTypeAliasType? { + TODO() + } + + /* override fun commonize(first: CirClassOrTypeAliasType, second: CirClassOrTypeAliasType): CirClassOrTypeAliasType? { if (first is CirClassType && second is CirClassType) { return ClassTypeCommonizer(classifiers, options).commonize(listOf(first, second)) @@ -53,6 +56,9 @@ internal class ClassOrTypeAliasTypeCommonizer( return commonize(classType, typeAliasClassType) } + + */ + } internal tailrec fun CirClassOrTypeAliasType.expandedType(): CirClassType = when (this) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassSuperTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassSuperTypeCommonizer.kt index 37b0a4bb0f4..bc5932341f4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassSuperTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassSuperTypeCommonizer.kt @@ -41,11 +41,10 @@ private typealias Supertypes = List * ``` */ internal class ClassSuperTypeCommonizer( - private val classifiers: CirKnownClassifiers + private val classifiers: CirKnownClassifiers, + private val typeCommonizer: TypeCommonizer ) : SingleInvocationCommonizer { - private val typeCommonizer = TypeCommonizer(classifiers) - override fun invoke(values: List): Supertypes { if (values.isEmpty()) return emptyList() if (values.all { it.isEmpty() }) return emptyList() @@ -54,7 +53,7 @@ internal class ClassSuperTypeCommonizer( val supertypesGroups = buildSupertypesGroups(supertypesTrees) return supertypesGroups.mapNotNull { supertypesGroup -> - typeCommonizer.asCommonizer().commonize(supertypesGroup.types) + typeCommonizer(supertypesGroup.types) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassTypeCommonizer.kt index f0a705fc5d5..de470c85973 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassTypeCommonizer.kt @@ -9,42 +9,42 @@ import org.jetbrains.kotlin.commonizer.cir.CirClassType import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers 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, - options: TypeCommonizer.Options = TypeCommonizer.Options.default -) : - AbstractStandardCommonizer() { - private lateinit var classId: CirEntityId - private val outerType = OuterClassTypeCommonizer(classifiers) - private lateinit var anyVisibility: Visibility - private val arguments = TypeArgumentListCommonizer(classifiers) - private val isMarkedNullable = TypeNullabilityCommonizer(options).asCommonizer() + private val typeCommonizer: TypeCommonizer, + private val isMarkedNullableCommonizer: TypeNullabilityCommonizer +) : NullableSingleInvocationCommonizer { + override fun invoke(values: List): CirClassType? { + if (values.isEmpty()) return null + val classId = values.singleDistinctValueOrNull { it.classifierId } ?: return null + val isMarkedNullable = isMarkedNullableCommonizer.commonize(values.map { it.isMarkedNullable }) ?: return null - override fun commonizationResult() = CirClassType.createInterned( - classId = classId, - 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 - ) + if (values.any { !isClassifierAvailableInCommon(classifiers, it.classifierId) }) { + return null + } - override fun initialize(first: CirClassType) { - classId = first.classifierId - anyVisibility = first.visibility + val outerType = if (values.all { it.outerType == null }) null + else if (values.any { it.outerType == null }) return null + 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 { @@ -64,10 +64,3 @@ private fun isClassifierAvailableInCommon(classifiers: CirKnownClassifiers, clas return (classifiers.commonizedNodes.classNode(classId)?.commonDeclaration?.invoke() ?: classifiers.commonizedNodes.typeAliasNode(classId)?.commonDeclaration?.invoke()) != null } - -private class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) : - AbstractNullableCommonizer( - wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) }, - extractor = { it }, - builder = { it } - ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CommonizationVisitor.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CommonizationVisitor.kt index affa215f207..657578df2de 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CommonizationVisitor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/CommonizationVisitor.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.mergedtree.* internal class CommonizationVisitor( - private val classifiers: CirKnownClassifiers, private val root: CirRootNode ) : CirNodeVisitor { override fun visitRootNode(node: CirRootNode, data: Unit) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/Commonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/Commonizer.kt index b19d2930702..47410adf561 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/Commonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/Commonizer.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.commonizer.core -interface Commonizer { +interface Commonizer { val result: R fun commonizeWith(next: T): Boolean } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizer.kt index f18ca678744..418da158d59 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizer.kt @@ -6,17 +6,26 @@ package org.jetbrains.kotlin.commonizer.core 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) : - AbstractNullableCommonizer( - wrappedCommonizerFactory = { TypeCommonizer(classifiers).asCommonizer() }, - extractor = { it.type }, - builder = { receiverType -> +class ExtensionReceiverCommonizer( + private val typeCommonizer: TypeCommonizer +) : NullableContextualSingleInvocationCommonizer { + + class Commonized(val receiver: CirExtensionReceiver?) { + companion object { + val NULL = Commonized(null) + } + } + + override fun invoke(values: List): Commonized? { + if (values.all { it == null }) return Commonized.NULL + if (values.any { it == null }) return null + + return Commonized( CirExtensionReceiver( annotations = emptyList(), - type = receiverType + type = typeCommonizer(values.map { checkNotNull(it).type }) ?: return null ) - } - ) + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/FunctionCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/FunctionCommonizer.kt index 7db855ae070..4af1c575508 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/FunctionCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/FunctionCommonizer.kt @@ -6,37 +6,28 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirFunction -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers - -class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer(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 { + override fun invoke(values: List): CirFunction? { + if (values.isEmpty()) return null + val functionOrProperty = functionOrPropertyBaseCommonizer(values) ?: return null + val valueParametersResult = CallableValueParametersCommonizer(typeCommonizer).commonize(values) ?: return null return CirFunction( - annotations = annotations.result, - name = name, - typeParameters = typeParameters.result, - visibility = visibility.result, - modality = modality.result, + annotations = AnnotationsCommonizer().commonize(values.map { it.annotations }) ?: return null, + name = values.first().name, + typeParameters = functionOrProperty.typeParameters, + visibility = functionOrProperty.visibility, + modality = functionOrProperty.modality, containingClass = null, // does not matter - valueParameters = valueParameters.valueParameters, - hasStableParameterNames = valueParameters.hasStableParameterNames, - extensionReceiver = extensionReceiver.result, - returnType = returnType.result ?: return null, - kind = kind, - modifiers = modifiers.result + valueParameters = valueParametersResult.valueParameters, + hasStableParameterNames = valueParametersResult.hasStableParameterNames, + extensionReceiver = functionOrProperty.extensionReceiver, + returnType = functionOrProperty.returnType, + kind = functionOrProperty.kind, + 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) - } -} +} \ No newline at end of file diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableContextualSingleInvocationCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableContextualSingleInvocationCommonizer.kt index ae693a42016..9fe92ae2049 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableContextualSingleInvocationCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableContextualSingleInvocationCommonizer.kt @@ -5,11 +5,11 @@ package org.jetbrains.kotlin.commonizer.core -interface NullableContextualSingleInvocationCommonizer { +interface NullableContextualSingleInvocationCommonizer { operator fun invoke(values: List): R? } -fun NullableContextualSingleInvocationCommonizer.asCommonizer(): Commonizer = +fun NullableContextualSingleInvocationCommonizer.asCommonizer(): Commonizer = object : Commonizer { private val collectedValues = mutableListOf() diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableSingleInvocationCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableSingleInvocationCommonizer.kt index 7eacfabb371..23d56cc9225 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableSingleInvocationCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/NullableSingleInvocationCommonizer.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.commonizer.core -interface NullableSingleInvocationCommonizer { +interface NullableSingleInvocationCommonizer { operator fun invoke(values: List): T? } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PropertyCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PropertyCommonizer.kt index 0d21100a6a3..ccf57176c4a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PropertyCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PropertyCommonizer.kt @@ -9,19 +9,21 @@ import org.jetbrains.kotlin.commonizer.cir.CirConstantValue import org.jetbrains.kotlin.commonizer.cir.CirProperty import org.jetbrains.kotlin.commonizer.cir.CirPropertyGetter import org.jetbrains.kotlin.commonizer.core.PropertyCommonizer.ConstCommonizationState.* -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.descriptors.Modality -class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer(classifiers) { +class PropertyCommonizer( + functionOrPropertyBaseCommonizer: FunctionOrPropertyBaseCommonizer +) : AbstractStandardCommonizer() { private val setter = PropertySetterCommonizer.asNullableCommonizer() private var isExternal = true private lateinit var constCommonizationState: ConstCommonizationState + private val functionOrPropertyBaseCommonizer = functionOrPropertyBaseCommonizer.asCommonizer() override fun commonizationResult(): CirProperty? { - val modality = modality.result + val functionOrPropertyBase = functionOrPropertyBaseCommonizer.result ?: return null val setter = setter.result?.takeIf { setter -> - setter !== PropertySetterCommonizer.privateFallbackSetter || modality == Modality.FINAL + setter !== PropertySetterCommonizer.privateFallbackSetter || functionOrPropertyBase.modality == Modality.FINAL } val constCommonizationState = constCommonizationState @@ -29,15 +31,15 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP return CirProperty( annotations = emptyList(), - name = name, - typeParameters = typeParameters.result, - visibility = visibility.result, - modality = modality, + name = functionOrPropertyBase.name, + typeParameters = functionOrPropertyBase.typeParameters, + visibility = functionOrPropertyBase.visibility, + modality = functionOrPropertyBase.modality, containingClass = null, // does not matter isExternal = isExternal, - extensionReceiver = extensionReceiver.result, - returnType = returnType.result ?: return null, - kind = kind, + extensionReceiver = functionOrPropertyBase.extensionReceiver, + returnType = functionOrPropertyBase.returnType, + kind = functionOrPropertyBase.kind, isVar = setter != null, isLateInit = false, isConst = constCompileTimeInitializer != null, @@ -51,8 +53,6 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP } override fun initialize(first: CirProperty) { - super.initialize(first) - constCommonizationState = if (first.isConst) { first.compileTimeInitializer.takeIf { it != CirConstantValue.NullValue }?.let(::ConstSameValue) ?: NonConst } else { @@ -89,7 +89,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP this.constCommonizationState = NonConst } - val result = super.doCommonizeWith(next) + val result = functionOrPropertyBaseCommonizer.commonizeWith(next) && setter.commonizeWith(next.setter) if (result) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ReturnTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ReturnTypeCommonizer.kt new file mode 100644 index 00000000000..d7c617db362 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ReturnTypeCommonizer.kt @@ -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 { + override fun invoke(values: List): 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 }) + } +} \ No newline at end of file diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasCommonizer.kt index d4bda4d14e4..b5828e9c589 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasCommonizer.kt @@ -13,17 +13,18 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull class TypeAliasCommonizer( - private val classifiers: CirKnownClassifiers + private val typeCommonizer: TypeCommonizer, + private val classifiers: CirKnownClassifiers, ) : NullableSingleInvocationCommonizer { override fun invoke(values: List): CirTypeAlias? { if (values.isEmpty()) 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()) - .asCommonizer().commonize(values.map { it.underlyingType }) as? CirClassOrTypeAliasType ?: return null + val underlyingType = typeCommonizer.withOptions { withOptimisticNumberTypeCommonizationEnabled() } + .invoke(values.map { it.underlyingType }) as? CirClassOrTypeAliasType ?: return null val visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasTypeCommonizer.kt index 1520c18fc13..a086120e55c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeAliasTypeCommonizer.kt @@ -11,15 +11,14 @@ import org.jetbrains.kotlin.commonizer.core.CommonizedTypeAliasAnswer.Companion. import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers internal class TypeAliasTypeCommonizer( + private val typeCommonizer: TypeCommonizer, private val classifiers: CirKnownClassifiers, - options: TypeCommonizer.Options -) : - AbstractStandardCommonizer() { +) : AbstractStandardCommonizer() { private lateinit var typeAliasId: CirEntityId - private val arguments = TypeArgumentListCommonizer(classifiers) - private val underlyingTypeArguments = TypeArgumentListCommonizer(classifiers) - private val isMarkedNullable = TypeNullabilityCommonizer(options).asCommonizer() + private val arguments = TypeArgumentListCommonizer(typeCommonizer) + private val underlyingTypeArguments = TypeArgumentListCommonizer(typeCommonizer) + private val isMarkedNullable = TypeNullabilityCommonizer(typeCommonizer.options).asCommonizer() private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet override fun commonizationResult() = @@ -47,7 +46,7 @@ internal class TypeAliasTypeCommonizer( is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier) is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier) null -> { - val underlyingType = computeSuitableUnderlyingType(classifiers, next.underlyingType) ?: return false + val underlyingType = computeSuitableUnderlyingType(classifiers, typeCommonizer, next.underlyingType) ?: return false CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(underlyingType) } else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier") diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentCommonizer.kt index 3dc1fc5f759..735b3523480 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentCommonizer.kt @@ -8,30 +8,22 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirRegularTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirStarTypeProjection import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.commonizer.utils.safeCastValues +import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull class TypeArgumentCommonizer( - classifiers: CirKnownClassifiers -) : AbstractStandardCommonizer() { - private var isStar = false - private lateinit var projectionKind: Variance - private val type = TypeCommonizer(classifiers).asCommonizer() + private val typeCommonizer: TypeCommonizer +) : NullableSingleInvocationCommonizer { + override fun invoke(values: List): CirTypeProjection? { + /* All values are star projections */ + values.safeCastValues()?.let { return CirStarTypeProjection } - override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirRegularTypeProjection( - projectionKind = projectionKind, - type = type.result - ) + /* All values are regular type projections */ + val projections = values.safeCastValues() ?: return null - override fun initialize(first: CirTypeProjection) { - when (first) { - is CirStarTypeProjection -> isStar = true - 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) + return CirRegularTypeProjection( + projectionKind = projections.singleDistinctValueOrNull { it.projectionKind } ?: return null, + type = typeCommonizer(projections.map { it.type }) ?: return null + ) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentListCommonizer.kt index aaa75657bb8..62c066ee4db 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentListCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeArgumentListCommonizer.kt @@ -6,8 +6,7 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirTypeProjection -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers -class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( - singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) } +class TypeArgumentListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer( + singleElementCommonizerFactory = { TypeArgumentCommonizer(typeCommonizer).asCommonizer() } ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeCommonizer.kt index af8af761ec6..0d4329df75f 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeCommonizer.kt @@ -7,23 +7,27 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers - +import org.jetbrains.kotlin.commonizer.utils.safeCastValues class TypeCommonizer( private val classifiers: CirKnownClassifiers, - private val options: Options = Options.default -) : AssociativeCommonizer { - override fun commonize(first: CirType, second: CirType): CirType? { - if (first is CirClassOrTypeAliasType && second is CirClassOrTypeAliasType) { - return ClassOrTypeAliasTypeCommonizer(classifiers, options).commonize(first, second) + val options: Options = Options.default +) : NullableSingleInvocationCommonizer { + + private val classOrTypeAliasTypeCommonizer = ClassOrTypeAliasTypeCommonizer(this) + private val flexibleTypeCommonizer = FlexibleTypeAssociativeCommonizer(this) + + override fun invoke(values: List): CirType? { + values.safeCastValues()?.let { types -> + return classOrTypeAliasTypeCommonizer(types) } - if (first is CirTypeParameterType && second is CirTypeParameterType) { - return TypeParameterTypeCommonizer.commonize(first, second) + values.safeCastValues()?.let { types -> + return TypeParameterTypeCommonizer.commonize(types) } - if (first is CirFlexibleType && second is CirFlexibleType) { - return FlexibleTypeAssociativeCommonizer(classifiers, options).commonize(first, second) + values.safeCastValues()?.let { types -> + return flexibleTypeCommonizer(types) } return null @@ -48,6 +52,15 @@ class TypeCommonizer( 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 { @@ -60,14 +73,11 @@ private object TypeParameterTypeCommonizer : AssociativeCommonizer { - override fun commonize(first: CirFlexibleType, second: CirFlexibleType): CirFlexibleType? { - - val lowerBound = TypeCommonizer(classifiers, options).commonize(first.lowerBound, second.lowerBound) ?: return null - val upperBound = TypeCommonizer(classifiers, options).commonize(first.upperBound, second.upperBound) ?: return null - + private val typeCommonizer: TypeCommonizer +) : NullableSingleInvocationCommonizer { + override fun invoke(values: List): CirFlexibleType? { + val lowerBound = typeCommonizer(values.map { it.lowerBound }) ?: return null + val upperBound = typeCommonizer(values.map { it.upperBound }) ?: return null return CirFlexibleType( lowerBound = lowerBound as CirSimpleType, upperBound = upperBound as CirSimpleType diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizer.kt index 50d554bd134..a4245ed7aae 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizer.kt @@ -8,14 +8,13 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirType import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.types.Variance -class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer() { +class TypeParameterCommonizer(typeCommonizer: TypeCommonizer) : AbstractStandardCommonizer() { private lateinit var name: CirName private var isReified = false private lateinit var variance: Variance - private val upperBounds = TypeParameterUpperBoundsCommonizer(classifiers) + private val upperBounds = TypeParameterUpperBoundsCommonizer(typeCommonizer) override fun commonizationResult() = CirTypeParameter( annotations = emptyList(), @@ -38,6 +37,6 @@ class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStanda && upperBounds.commonizeWith(next.upperBounds) } -private class TypeParameterUpperBoundsCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( - singleElementCommonizerFactory = { TypeCommonizer(classifiers).asCommonizer() } +private class TypeParameterUpperBoundsCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer( + singleElementCommonizerFactory = { typeCommonizer.asCommonizer() } ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizer.kt index 80ee14e325e..b16d5634b5c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizer.kt @@ -6,8 +6,7 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers -class TypeParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( - singleElementCommonizerFactory = { TypeParameterCommonizer(classifiers) } +class TypeParameterListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer( + singleElementCommonizerFactory = { TypeParameterCommonizer(typeCommonizer) } ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizer.kt index 5904fdfa420..4a37e66a4e2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizer.kt @@ -8,25 +8,27 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirType import org.jetbrains.kotlin.commonizer.cir.CirValueParameter -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.commonizer.utils.isNull -class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer() { +class ValueParameterCommonizer(returnTypeCommonizer: TypeCommonizer) : + AbstractStandardCommonizer() { private lateinit var name: CirName - private val returnType = TypeCommonizer(classifiers).asCommonizer() + private val returnTypeCommonizer = returnTypeCommonizer.asCommonizer() private var varargElementType: CirType? = null private var isCrossinline = true private var isNoinline = true - override fun commonizationResult() = CirValueParameter.createInterned( - annotations = emptyList(), - name = name, - returnType = returnType.result, - varargElementType = varargElementType, - declaresDefaultValue = false, - isCrossinline = isCrossinline, - isNoinline = isNoinline - ) + override fun commonizationResult(): CirValueParameter? { + return CirValueParameter.createInterned( + annotations = emptyList(), + name = name, + returnType = returnTypeCommonizer.result ?: return null, + varargElementType = varargElementType, + declaresDefaultValue = false, + isCrossinline = isCrossinline, + isNoinline = isNoinline + ) + } override fun initialize(first: CirValueParameter) { name = first.name @@ -38,7 +40,7 @@ class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStand override fun doCommonizeWith(next: CirValueParameter): Boolean { val result = !next.declaresDefaultValue && varargElementType.isNull() == next.varargElementType.isNull() - && returnType.commonizeWith(next.returnType) + && returnTypeCommonizer.commonizeWith(next.returnType) if (result) { isCrossinline = isCrossinline && next.isCrossinline diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterListCommonizer.kt index 8480bfe900c..9c1c6bc7ea4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterListCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ValueParameterListCommonizer.kt @@ -7,10 +7,9 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirValueParameter -import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers -class ValueParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( - singleElementCommonizerFactory = { ValueParameterCommonizer(classifiers) } +class ValueParameterListCommonizer(typeCommonizer: TypeCommonizer) : AbstractListCommonizer( + singleElementCommonizerFactory = { ValueParameterCommonizer(typeCommonizer) } ) { fun overwriteNames(names: List) { forEachSingleElementCommonizer { index, singleElementCommonizer -> diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/typeAliasUtils.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/typeAliasUtils.kt index eafb9813c0e..295e53525a2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/typeAliasUtils.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/typeAliasUtils.kt @@ -13,24 +13,25 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers internal tailrec fun computeSuitableUnderlyingType( classifiers: CirKnownClassifiers, + typeCommonizer: TypeCommonizer, underlyingType: CirClassOrTypeAliasType ): CirClassOrTypeAliasType? { return when (underlyingType) { - is CirClassType -> underlyingType.withCommonizedArguments(classifiers) + is CirClassType -> underlyingType.withCommonizedArguments(typeCommonizer) is CirTypeAliasType -> if (classifiers.commonDependencies.hasClassifier(underlyingType.classifierId) || classifiers.commonizedNodes.typeAliasNode(underlyingType.classifierId)?.commonDeclaration?.invoke() != null - ) underlyingType.withCommonizedArguments(classifiers) - else computeSuitableUnderlyingType(classifiers, underlyingType.underlyingType) + ) underlyingType.withCommonizedArguments(typeCommonizer) + else computeSuitableUnderlyingType(classifiers, typeCommonizer, underlyingType.underlyingType) } } -private fun CirClassType.withCommonizedArguments(classifiers: CirKnownClassifiers): CirClassType? { +private fun CirClassType.withCommonizedArguments(typeCommonizer: TypeCommonizer): CirClassType? { val existingArguments = arguments - val newArguments = existingArguments.toCommonizedArguments(classifiers) ?: return null + val newArguments = existingArguments.toCommonizedArguments(typeCommonizer) ?: return null 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) CirClassType.createInterned( @@ -44,14 +45,14 @@ private fun CirClassType.withCommonizedArguments(classifiers: CirKnownClassifier this } -private fun CirTypeAliasType.withCommonizedArguments(classifiers: CirKnownClassifiers): CirTypeAliasType? { +private fun CirTypeAliasType.withCommonizedArguments(typeCommonizer: TypeCommonizer): CirTypeAliasType? { val existingArguments = arguments - val newArguments = existingArguments.toCommonizedArguments(classifiers) ?: return null + val newArguments = existingArguments.toCommonizedArguments(typeCommonizer) ?: return null val existingUnderlyingType = underlyingType val newUnderlyingType = when (existingUnderlyingType) { - is CirClassType -> existingUnderlyingType.withCommonizedArguments(classifiers) - is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments(classifiers) + is CirClassType -> existingUnderlyingType.withCommonizedArguments(typeCommonizer) + is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments(typeCommonizer) } ?: return null return if (newArguments !== existingArguments || newUnderlyingType !== existingUnderlyingType) @@ -66,8 +67,6 @@ private fun CirTypeAliasType.withCommonizedArguments(classifiers: CirKnownClassi } @Suppress("NOTHING_TO_INLINE") -private inline fun List.toCommonizedArguments(classifiers: CirKnownClassifiers): List? = - if (isEmpty()) - this - else - TypeArgumentListCommonizer(classifiers).let { if (it.commonizeWith(this)) it.result else null } +private inline fun List.toCommonizedArguments(typeCommonizer: TypeCommonizer): List? = + if (isEmpty()) this + else TypeArgumentListCommonizer(typeCommonizer).let { if (it.commonizeWith(this)) it.result else null } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt index f84a4f98948..48ae80524a6 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt @@ -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.CirRootNode 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.TypeSubstitutionCirNodeTransformer -import org.jetbrains.kotlin.commonizer.transformer.UnderscoredTypeAliasTypeSubstitutor import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer import org.jetbrains.kotlin.commonizer.tree.mergeCirTree @@ -65,17 +62,7 @@ internal fun commonizeTarget( InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree) - TypeSubstitutionCirNodeTransformer( - 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) + mergedTree.accept(CommonizationVisitor(mergedTree), Unit) return mergedTree } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt index 2fb97974b87..d3eea94477e 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt @@ -57,7 +57,7 @@ internal fun buildPropertyNode( storageManager = storageManager, size = size, nodeRelationship = nodeRelationship, - commonizerProducer = { PropertyCommonizer(classifiers) }, + commonizerProducer = { PropertyCommonizer(FunctionOrPropertyBaseCommonizer(TypeCommonizer(classifiers))) }, nodeProducer = ::CirPropertyNode ) @@ -70,7 +70,10 @@ internal fun buildFunctionNode( storageManager = storageManager, size = size, nodeRelationship = nodeRelationship, - commonizerProducer = { FunctionCommonizer(classifiers) }, + commonizerProducer = { + val typeCommonizer = TypeCommonizer(classifiers) + FunctionCommonizer(typeCommonizer, FunctionOrPropertyBaseCommonizer(typeCommonizer)).asCommonizer() + }, nodeProducer = ::CirFunctionNode ) @@ -84,7 +87,10 @@ internal fun buildClassNode( storageManager = storageManager, size = size, nodeRelationship = nodeRelationship, - commonizerProducer = { ClassCommonizer(classifiers) }, + commonizerProducer = { + val typeCommonizer = TypeCommonizer(classifiers) + ClassCommonizer(typeCommonizer, ClassSuperTypeCommonizer(classifiers, typeCommonizer)) + }, recursionMarker = CirClassRecursionMarker, nodeProducer = { targetDeclarations, commonDeclaration -> CirClassNode(classId, targetDeclarations, commonDeclaration).also { @@ -103,7 +109,7 @@ internal fun buildClassConstructorNode( storageManager = storageManager, size = size, nodeRelationship = nodeRelationship, - commonizerProducer = { ClassConstructorCommonizer(classifiers) }, + commonizerProducer = { ClassConstructorCommonizer(TypeCommonizer(classifiers)) }, nodeProducer = ::CirClassConstructorNode ) @@ -116,7 +122,7 @@ internal fun buildTypeAliasNode( storageManager = storageManager, size = size, nodeRelationship = null, - commonizerProducer = { TypeAliasCommonizer(classifiers).asCommonizer() }, + commonizerProducer = { TypeAliasCommonizer(TypeCommonizer(classifiers), classifiers).asCommonizer() }, recursionMarker = CirTypeAliasRecursionMarker, nodeProducer = { targetDeclarations, commonDeclaration -> CirTypeAliasNode(typeAliasId, targetDeclarations, commonDeclaration).also { @@ -145,12 +151,13 @@ private fun > buildNod return nodeProducer(targetDeclarations, commonLazyValue) } +@Suppress("UNCHECKED_CAST") internal fun commonize( targetDeclarations: CommonizedGroup, commonizer: Commonizer ): R? { if (targetDeclarations.any { it == null }) return null - return commonizer.commonize(targetDeclarations.filterNotNull()) + return commonizer.commonize(targetDeclarations as List) } @Suppress("NOTHING_TO_INLINE") diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/misc.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/misc.kt index affd3481553..9643171aba3 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/misc.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/misc.kt @@ -34,6 +34,10 @@ internal inline fun Array.compactMap(transform: (T) -> R): List = else -> mapTo(ArrayList(size), transform) } +internal inline fun Array.compactMapNotNull(transform: (T) -> R): List { + return mapNotNullTo(ArrayList(size), transform).also { it.trimToSize() } +} + internal inline fun Collection.compactMapNotNull(transform: (T) -> R?): List = if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact() diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizerTest.kt index 0af81cb9569..d855e4309c1 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ExtensionReceiverCommonizerTest.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS import org.jetbrains.kotlin.commonizer.utils.mockClassType import org.junit.Test -class ExtensionReceiverCommonizerTest : AbstractCommonizerTest() { +class ExtensionReceiverCommonizerTest : AbstractCommonizerTest() { @Test fun nullReceiver() = doTestSuccess( @@ -20,7 +20,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest() { +class TypeCommonizerTest : AbstractCommonizerTest() { private lateinit var classifiers: CirKnownClassifiers diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizerTest.kt index adce6e80f70..08a23fbec53 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterCommonizerTest.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.types.Variance import org.junit.Test class TypeParameterCommonizerTest : AbstractCommonizerTest() { - override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS) + override fun createCommonizer() = TypeParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS)) @Test fun allAreReified() = doTestSuccess( diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizerTest.kt index a288f53f155..1818ebee761 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeParameterListCommonizerTest.kt @@ -108,7 +108,7 @@ class TypeParameterListCommonizerTest : AbstractCommonizerTest): List { diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizerTest.kt index 1b5a1ed59ba..08a0cfb51bd 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/ValueParameterCommonizerTest.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS import org.jetbrains.kotlin.commonizer.utils.mockClassType import org.junit.Test -class ValueParameterCommonizerTest : AbstractCommonizerTest() { +class ValueParameterCommonizerTest : AbstractCommonizerTest() { @Test fun sameReturnType1() = doTestSuccess( @@ -137,7 +137,7 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest?, b: List?): Boolean { if (a === b)