diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractListCommonizer.kt index d8d96e4bc32..c9e88924dbf 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractListCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractListCommonizer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType +import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap /** * Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using @@ -22,7 +23,7 @@ abstract class AbstractListCommonizer( private var error = false final override val result: List - get() = checkState(commonizers, error).map { it.result } + get() = checkState(commonizers, error).compactMap { it.result } final override fun commonizeWith(next: List): Boolean { if (error) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt index e17566f0886..5b49a0cac4b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory +import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.name.Name @@ -47,7 +48,7 @@ private class TypeAliasShortCircuitingCommonizer( ) : AbstractStandardCommonizer() { private lateinit var name: Name private val typeParameters = TypeParameterListCommonizer(classifiers) - private lateinit var underlyingType: CirClassOrTypeAliasType + private var underlyingType: CirClassOrTypeAliasType? = null // null means not computed yet private val expandedType = TypeCommonizer(classifiers) private val visibility = VisibilityCommonizer.lowering() @@ -56,7 +57,7 @@ private class TypeAliasShortCircuitingCommonizer( name = name, typeParameters = typeParameters.result, visibility = visibility.result, - underlyingType = computeCommonizedUnderlyingType(underlyingType), + underlyingType = underlyingType!!, expandedType = expandedType.result as CirClassType ) @@ -65,23 +66,74 @@ private class TypeAliasShortCircuitingCommonizer( override fun initialize(first: CirTypeAlias) { name = first.name - underlyingType = first.underlyingType } - override fun doCommonizeWith(next: CirTypeAlias) = - typeParameters.commonizeWith(next.typeParameters) + override fun doCommonizeWith(next: CirTypeAlias): Boolean { + if (underlyingType == null) { + underlyingType = computeUnderlyingType(next.underlyingType) ?: return false + } + + return typeParameters.commonizeWith(next.typeParameters) && expandedType.commonizeWith(next.expandedType) && visibility.commonizeWith(next) + } - private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType { + private tailrec fun computeUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType? { return when (underlyingType) { - is CirClassType -> underlyingType + is CirClassType -> underlyingType.withCommonizedArguments() is CirTypeAliasType -> if (classifiers.commonDependeeLibraries.hasClassifier(underlyingType.classifierId)) - underlyingType + underlyingType.withCommonizedArguments() else - computeCommonizedUnderlyingType(underlyingType.underlyingType) + computeUnderlyingType(underlyingType.underlyingType) } } + + private fun CirClassType.withCommonizedArguments(): CirClassType? { + val existingArguments = arguments + val newArguments = existingArguments.toCommonizedArguments() ?: return null + + val existingOuterType = outerType + val newOuterType = existingOuterType?.let { it.withCommonizedArguments() ?: return null } + + return if (newArguments !== existingArguments || newOuterType !== existingOuterType) + CirTypeFactory.createClassType( + classId = classifierId, + outerType = newOuterType, + visibility = visibility, + arguments = newArguments, + isMarkedNullable = isMarkedNullable + ) + else + this + } + + private fun CirTypeAliasType.withCommonizedArguments(): CirTypeAliasType? { + val existingArguments = arguments + val newArguments = existingArguments.toCommonizedArguments() ?: return null + + val existingUnderlyingType = underlyingType + val newUnderlyingType = when (existingUnderlyingType) { + is CirClassType -> existingUnderlyingType.withCommonizedArguments() + is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments() + } ?: return null + + return if (newArguments !== existingArguments || newUnderlyingType !== existingUnderlyingType) + CirTypeFactory.createTypeAliasType( + typeAliasId = classifierId, + underlyingType = newUnderlyingType, + arguments = newArguments, + isMarkedNullable = isMarkedNullable + ) + else + this + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun List.toCommonizedArguments(): List? = + if (isEmpty()) + this + else + TypeArgumentListCommonizer(classifiers).let { if (it.commonizeWith(this)) it.result else null } } private class TypeAliasLiftingUpCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer() { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentCommonizer.kt new file mode 100644 index 00000000000..cae7c349382 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentCommonizer.kt @@ -0,0 +1,37 @@ +/* + * 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.descriptors.commonizer.core + +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirStarTypeProjection +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjectionImpl +import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers +import org.jetbrains.kotlin.types.Variance + +class TypeArgumentCommonizer( + classifiers: CirKnownClassifiers +) : AbstractStandardCommonizer() { + private var isStar = false + private lateinit var projectionKind: Variance + private val type = TypeCommonizer(classifiers) + + override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl( + projectionKind = projectionKind, + type = type.result + ) + + override fun initialize(first: CirTypeProjection) { + when (first) { + is CirStarTypeProjection -> isStar = true + is CirTypeProjectionImpl -> projectionKind = first.projectionKind + } + } + + override fun doCommonizeWith(next: CirTypeProjection) = when (next) { + is CirStarTypeProjection -> isStar + is CirTypeProjectionImpl -> !isStar && projectionKind == next.projectionKind && type.commonizeWith(next.type) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentListCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentListCommonizer.kt new file mode 100644 index 00000000000..83af0b22cdc --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeArgumentListCommonizer.kt @@ -0,0 +1,13 @@ +/* + * 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.descriptors.commonizer.core + +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection +import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers + +class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( + singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) } +) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt index 9c3d1a70c48..1cdc893683c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswe import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.types.Variance class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer() { private lateinit var wrapped: Commonizer<*, CirType> @@ -190,35 +189,6 @@ private class FlexibleTypeCommonizer(classifiers: CirKnownClassifiers) : Abstrac lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound) } -private class TypeArgumentCommonizer( - classifiers: CirKnownClassifiers -) : AbstractStandardCommonizer() { - private var isStar = false - private lateinit var projectionKind: Variance - private val type = TypeCommonizer(classifiers) - - override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl( - projectionKind = projectionKind, - type = type.result - ) - - override fun initialize(first: CirTypeProjection) { - when (first) { - is CirStarTypeProjection -> isStar = true - is CirTypeProjectionImpl -> projectionKind = first.projectionKind - } - } - - override fun doCommonizeWith(next: CirTypeProjection) = when (next) { - is CirStarTypeProjection -> isStar - is CirTypeProjectionImpl -> !isStar && projectionKind == next.projectionKind && type.commonizeWith(next.type) - } -} - -private class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer( - singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) } -) - private fun commonizeClass(classId: ClassId, classifiers: CirKnownClassifiers): Boolean { if (classifiers.commonDependeeLibraries.hasClassifier(classId)) { // The class is from common fragment of dependee library (ex: stdlib). Already commonized. diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt index c97431cb6af..7716e7af808 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt @@ -41,6 +41,13 @@ internal inline fun Collection.compactMap(transform: (T) -> R): List mapTo(ArrayList(size), transform) } +internal inline fun Array.compactMap(transform: (T) -> R): List = + when (size) { + 0 -> emptyList() + 1 -> singletonList(transform(this[0])) + else -> mapTo(ArrayList(size), transform) + } + internal inline fun Collection.compactMapNotNull(transform: (T) -> R?): List = if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact() diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/common/package_root.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/common/package_root.kt new file mode 100644 index 00000000000..a386b944de9 --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/common/package_root.kt @@ -0,0 +1,3 @@ +typealias my_long_t = common.stuff.MyLong +typealias MyTypeAlias = common.stuff.Wrapper +expect val property: MyTypeAlias diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/linux/package_root.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/linux/package_root.kt new file mode 100644 index 00000000000..9f537a20f78 --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/linux/package_root.kt @@ -0,0 +1,2 @@ +typealias my_linux_long_t = common.stuff.MyLong +actual val property: MyTypeAlias = TODO() diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/macos/package_root.kt new file mode 100644 index 00000000000..cbd6b7778a3 --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/commonized/macos/package_root.kt @@ -0,0 +1,2 @@ +typealias my_macos_long_t = common.stuff.MyLong +actual val property: MyTypeAlias = TODO() diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/dependee/common/package_common_stuff.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/dependee/common/package_common_stuff.kt new file mode 100644 index 00000000000..e346c621a85 --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/dependee/common/package_common_stuff.kt @@ -0,0 +1,4 @@ +package common.stuff + +class Wrapper +class MyLong diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/linux/package_root.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/linux/package_root.kt new file mode 100644 index 00000000000..2814fef234d --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/linux/package_root.kt @@ -0,0 +1,4 @@ +typealias my_long_t = my_linux_long_t +typealias my_linux_long_t = common.stuff.MyLong +typealias MyTypeAlias = common.stuff.Wrapper +val property: MyTypeAlias = TODO() diff --git a/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/macos/package_root.kt new file mode 100644 index 00000000000..014269e7431 --- /dev/null +++ b/native/commonizer/testData/classifierCommonization/differentTypeAliasesInArguments/original/macos/package_root.kt @@ -0,0 +1,4 @@ +typealias my_long_t = my_macos_long_t +typealias my_macos_long_t = common.stuff.MyLong +typealias MyTypeAlias = common.stuff.Wrapper +val property: MyTypeAlias = TODO() diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/ClassifierCommonizationFromSourcesTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/ClassifierCommonizationFromSourcesTest.kt index eaf9745d2b7..783438265dc 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/ClassifierCommonizationFromSourcesTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/ClassifierCommonizationFromSourcesTest.kt @@ -23,4 +23,6 @@ class ClassifierCommonizationFromSourcesTest : AbstractCommonizationFromSourcesT fun testSupertypes() = doTestSuccessfulCommonization() fun testTypeAliases() = doTestSuccessfulCommonization() + + fun testDifferentTypeAliasesInArguments() = doTestSuccessfulCommonization() }