From d3c6dc362e489351dbf0662c1337cb2b2caeb79f Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Mon, 1 Jun 2020 15:59:36 +0700 Subject: [PATCH] [Commonizer] Lift up identical type aliases ^KMM-55 --- .../builder/DeclarationsBuilderVisitor1.kt | 2 +- .../descriptors/commonizer/builder/context.kt | 24 +++++- .../builder/typeAliasDescriptors.kt | 21 ++++-- .../descriptors/commonizer/cir/CirClass.kt | 8 +- .../commonizer/cir/CirClassifier.kt | 12 +++ .../commonizer/cir/CirDeclaration.kt | 5 +- .../descriptors/commonizer/cir/CirType.kt | 9 +-- .../commonizer/cir/CirTypeAlias.kt | 7 +- .../cir/factory/CirTypeAliasFactory.kt | 36 +++++++-- .../commonizer/cir/factory/CirTypeFactory.kt | 14 +--- .../commonizer/cir/impl/CirSimpleTypeImpl.kt | 6 +- .../commonizer/cir/impl/CirTypeAliasImpl.kt | 5 +- .../commonizer/cir/impl/RecursionMarkers.kt | 8 ++ .../descriptors/commonizer/core/Commonizer.kt | 9 ++- .../core/PropertySetterCommonizer.kt | 4 +- .../commonizer/core/TypeAliasCommonizer.kt | 74 ++++++++++++++++--- .../commonizer/core/TypeCommonizer.kt | 7 +- .../commonizer/core/VisibilityCommonizer.kt | 12 +-- .../commonizer/mergedtree/nodeBuilders.kt | 3 +- .../commonizer/mergedtree/nodes.kt | 4 +- .../EqualizingVisibilityCommonizerTest.kt | 6 +- .../core/LoweringVisibilityCommonizerTest.kt | 4 +- 22 files changed, 195 insertions(+), 85 deletions(-) create mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifier.kt diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor1.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor1.kt index 0baae510f23..0291631cbb0 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor1.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor1.kt @@ -129,7 +129,7 @@ internal class DeclarationsBuilderVisitor1( node.buildDescriptors(components, typeAliasesGroup, data) val typeAliases = typeAliasesGroup.toList() - val commonClass = typeAliases[node.indexOfCommon] as CommonizedClassDescriptor? + val commonClass = typeAliases[node.indexOfCommon] as? CommonizedClassDescriptor? commonClass?.unsubstitutedMemberScope = CommonizedMemberScope() // empty member scope commonClass?.initialize(emptyList()) // no constructors diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt index cee2ff4b995..560ae09d780 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.storage.StorageManager /** * Temporary caches for constructed descriptors. */ -class DeclarationsBuilderCache(dimension: Int) { +class DeclarationsBuilderCache(private val dimension: Int) { init { check(dimension > 0) } @@ -43,8 +43,26 @@ class DeclarationsBuilderCache(dimension: Int) { fun getCachedClasses(fqName: FqName): List = classes.getOrFail(fqName) - fun getCachedClassifier(fqName: FqName, index: Int): ClassifierDescriptorWithTypeParameters? = - classes.getOrNull(fqName)?.get(index) ?: typeAliases.getOrNull(fqName)?.get(index) + fun getCachedClassifier(fqName: FqName, index: Int): ClassifierDescriptorWithTypeParameters? { + // first, look up for class + val classes: CommonizedGroup? = classes.getOrNull(fqName) + classes?.get(index)?.let { return it } + + // then, for type alias + val typeAliases: CommonizedGroup? = typeAliases.getOrNull(fqName) + typeAliases?.get(index)?.let { return it } + + val indexOfCommon = dimension - 1 + if (indexOfCommon != index) { + // then, for class from the common fragment + classes?.get(indexOfCommon)?.let { return it } + + // then, for type alias from the common fragment + typeAliases?.get(indexOfCommon)?.let { return it } + } + + return null + } fun cache(index: Int, modules: List) { this.modules[index] = modules diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt index d721c13b148..4df8fdb7e50 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.indexOfCommon @@ -19,14 +20,24 @@ internal fun CirTypeAliasNode.buildDescriptors( output: CommonizedGroup, containingDeclarations: List ) { - val commonClass: CirClass? = common() - val markAsActual = commonClass != null + val commonClassifier: CirClassifier? = common() + // Note: 'expect class' and lifted up 'typealias' both can't be non-null + val commonTypeAlias: CirTypeAlias? = commonClassifier as? CirTypeAlias? - target.forEachIndexed { index, typeAlias -> - typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) + val isLiftedUp = commonTypeAlias?.isLiftedUp == true + val markAsActual = commonClassifier != null + + if (!isLiftedUp) { + target.forEachIndexed { index, typeAlias -> + typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) + } } - commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true) + if (commonTypeAlias != null) { + commonTypeAlias.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName) + } else if (commonClassifier != null && commonClassifier is CirClass) { + commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true) + } // log stats components.statsCollector?.logStats(output.toList()) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt index 276d7687c02..e8d5384157c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt @@ -8,13 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.name.FqName -interface CirClass : - CirAnnotatedDeclaration, - CirNamedDeclaration, - CirDeclarationWithTypeParameters, - CirDeclarationWithVisibility, - CirDeclarationWithModality { - +interface CirClass : CirClassifier, CirDeclarationWithModality { val kind: ClassKind var companion: FqName? // null means no companion object val isCompanion: Boolean diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifier.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifier.kt new file mode 100644 index 00000000000..624daabb3a6 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifier.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 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.cir + +interface CirClassifier : + CirAnnotatedDeclaration, + CirNamedDeclaration, + CirDeclarationWithTypeParameters, + CirDeclarationWithVisibility diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt index 88ba4b2f550..c491a12db25 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt @@ -31,10 +31,13 @@ interface CirNamedDeclaration : CirDeclaration { val name: Name } -interface CirDeclarationWithVisibility : CirDeclaration { +// TODO: merge with [CirDeclarationWithVisibility] +interface CirHasVisibility { val visibility: Visibility } +interface CirDeclarationWithVisibility : CirDeclaration, CirHasVisibility + interface CirDeclarationWithModality : CirDeclaration { val modality: Modality } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt index 116c20ee4fc..e4133295453 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.CLASS import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.TYPE_ALIAS import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory @@ -17,8 +18,7 @@ sealed class CirType { } /** - * All attributes except for [expandedTypeConstructorId] are read from the abbreviation type: [AbbreviatedType.abbreviation]. - * And [expandedTypeConstructorId] is read from the expanded type: [AbbreviatedType.expandedType]. + * All attributes are read from the abbreviation type: [AbbreviatedType.abbreviation]. * * This is necessary to properly compare types for type aliases, where abbreviation type represents the type alias itself while * expanded type represents right-hand side declaration that should be processed separately. @@ -28,13 +28,12 @@ sealed class CirType { * * Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost. */ -abstract class CirSimpleType : CirType() { +abstract class CirSimpleType : CirType(), CirHasVisibility { abstract val kind: CirSimpleTypeKind abstract val fqName: FqName abstract val arguments: List abstract val isMarkedNullable: Boolean abstract val isDefinitelyNotNullType: Boolean - abstract val expandedTypeConstructorId: CirTypeConstructorId inline val isClassOrTypeAlias: Boolean get() = (kind == CLASS || kind == TYPE_ALIAS) } @@ -50,8 +49,6 @@ enum class CirSimpleTypeKind { } } -data class CirTypeConstructorId(val fqName: FqName, val numberOfTypeParameters: Int) - data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType) data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSimpleType) : CirType() { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirTypeAlias.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirTypeAlias.kt index 84c7700f753..e9592c4fb71 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirTypeAlias.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirTypeAlias.kt @@ -5,12 +5,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir -interface CirTypeAlias : - CirAnnotatedDeclaration, - CirNamedDeclaration, - CirDeclarationWithTypeParameters, - CirDeclarationWithVisibility { - +interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration { val underlyingType: CirSimpleType val expandedType: CirSimpleType } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeAliasFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeAliasFactory.kt index 2fb851486fc..4d27fe7a125 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeAliasFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeAliasFactory.kt @@ -6,19 +6,41 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.intern +import org.jetbrains.kotlin.name.Name object CirTypeAliasFactory { - fun create(source: TypeAliasDescriptor): CirTypeAlias { + fun create(source: TypeAliasDescriptor): CirTypeAlias = create( + annotations = source.annotations.map(CirAnnotationFactory::create), + name = source.name.intern(), + typeParameters = source.declaredTypeParameters.map(CirTypeParameterFactory::create), + visibility = source.visibility, + underlyingType = CirTypeFactory.create(source.underlyingType), + expandedType = CirTypeFactory.create(source.expandedType) + ) + + @Suppress("NOTHING_TO_INLINE") + inline fun create( + annotations: List, + name: Name, + typeParameters: List, + visibility: Visibility, + underlyingType: CirSimpleType, + expandedType: CirSimpleType + ): CirTypeAlias { return CirTypeAliasImpl( - annotations = source.annotations.map(CirAnnotationFactory::create), - name = source.name.intern(), - typeParameters = source.declaredTypeParameters.map(CirTypeParameterFactory::create), - visibility = source.visibility, - underlyingType = CirTypeFactory.create(source.underlyingType), - expandedType = CirTypeFactory.create(source.expandedType) + annotations = annotations, + name = name, + typeParameters = typeParameters, + visibility = visibility, + underlyingType = underlyingType, + expandedType = expandedType ) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt index 8b38a65f46c..aa2e41a1566 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.* import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirSimpleTypeImpl @@ -30,10 +27,11 @@ object CirTypeFactory { fun create(source: SimpleType): CirSimpleType { val abbreviation: SimpleType = (source as? AbbreviatedType)?.abbreviation ?: source - val expanded: SimpleType = (source as? AbbreviatedType)?.expandedType ?: source + val classifierDescriptor: ClassifierDescriptor = abbreviation.declarationDescriptor val simpleType = CirSimpleTypeImpl( - kind = abbreviation.declarationDescriptor.cirSimpleTypeKind, + kind = classifierDescriptor.cirSimpleTypeKind, + visibility = (classifierDescriptor as? ClassifierDescriptorWithTypeParameters)?.visibility ?: Visibilities.UNKNOWN, fqName = abbreviation.fqNameInterned, arguments = abbreviation.arguments.map { projection -> CirTypeProjection( @@ -44,10 +42,6 @@ object CirTypeFactory { }, isMarkedNullable = abbreviation.isMarkedNullable, isDefinitelyNotNullType = abbreviation.isDefinitelyNotNullType, - expandedTypeConstructorId = CirTypeConstructorId( - fqName = expanded.fqNameInterned, - numberOfTypeParameters = expanded.constructor.parameters.size - ), fqNameWithTypeParameters = source.fqNameWithTypeParameters ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt index b7946fee69d..faf4dd78da0 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeConstructorId import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode @@ -15,17 +15,18 @@ import org.jetbrains.kotlin.name.FqName data class CirSimpleTypeImpl( override val kind: CirSimpleTypeKind, + override val visibility: Visibility, // visibility of the classifier descriptor override val fqName: FqName, override val arguments: List, override val isMarkedNullable: Boolean, override val isDefinitelyNotNullType: Boolean, - override val expandedTypeConstructorId: CirTypeConstructorId, override val fqNameWithTypeParameters: String ) : CirSimpleType() { // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode private var cachedHashCode = 0 private fun computeHashCode() = hashCode(kind) + .appendHashCode(visibility) .appendHashCode(fqName) .appendHashCode(arguments) .appendHashCode(isMarkedNullable) @@ -47,6 +48,7 @@ data class CirSimpleTypeImpl( isMarkedNullable == other.isMarkedNullable && fqName == other.fqName && kind == other.kind + && visibility == other.visibility && arguments == other.arguments && fqNameWithTypeParameters == other.fqNameWithTypeParameters && isDefinitelyNotNullType == other.isDefinitelyNotNullType diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasImpl.kt index 7a3fb2e4aeb..ce6a4faa5ce 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasImpl.kt @@ -19,4 +19,7 @@ data class CirTypeAliasImpl( override val visibility: Visibility, override val underlyingType: CirSimpleType, override val expandedType: CirSimpleType -) : CirTypeAlias +) : CirTypeAlias { + // any TA in "common" fragment is already lifted up + override val isLiftedUp get() = true +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt index d847810da16..a5c1c3395eb 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRecursionMarker import org.jetbrains.kotlin.name.FqName @@ -26,3 +27,10 @@ object CirClassRecursionMarker : CirClass, CirRecursionMarker { override val isExternal get() = unsupported() override val supertypes get() = unsupported() } + +object CirClassifierRecursionMarker : CirClassifier, CirRecursionMarker { + override val annotations get() = unsupported() + override val name get() = unsupported() + override val typeParameters get() = unsupported() + override val visibility get() = unsupported() +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/Commonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/Commonizer.kt index cebc6b038f3..025f3be9a81 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/Commonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/Commonizer.kt @@ -19,12 +19,15 @@ abstract class AbstractStandardCommonizer : Commonizer { private var state = State.EMPTY - final override val result: R + protected val hasResult: Boolean get() = when (state) { - State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException() - State.IN_PROGRESS -> commonizationResult() + State.EMPTY, State.ERROR -> false + State.IN_PROGRESS -> true } + final override val result: R + get() = if (hasResult) commonizationResult() else throw IllegalCommonizerStateException() + final override fun commonizeWith(next: T): Boolean { val result = when (state) { State.ERROR -> return false diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertySetterCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertySetterCommonizer.kt index 73394f1da3d..f620f772512 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertySetterCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertySetterCommonizer.kt @@ -6,11 +6,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclarationWithVisibility +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirHasVisibility import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPropertySetter import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertySetterFactory -class PropertySetterCommonizer : AbstractNullableCommonizer( +class PropertySetterCommonizer : AbstractNullableCommonizer( wrappedCommonizerFactory = { VisibilityCommonizer.equalizing() }, extractor = { it }, builder = CirPropertySetterFactory::createDefaultNoAnnotations 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 7f94ac98ee1..83563e857a5 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 @@ -7,23 +7,76 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias +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.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.name.Name -class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { - private lateinit var name: Name - private val underlyingType = TypeCommonizer(cache) - private val visibility = VisibilityCommonizer.lowering(allowPrivate = true) +/** + * Main (optimistic) branch: + * - Make sure that all TAs are identical, so the resulting TA can be lifted up into "common" fragment. + * + * Secondary (backup) branch: + * - Produce an "expect class" for "common" fragment and the corresponding "actual typealias" declarations for each platform fragment. + */ +class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private val main = TypeAliasLiftingUpCommonizer(cache) + private val secondary = TypeAliasExpectClassCommonizer() - override fun commonizationResult() = CirClassFactory.create( + override fun commonizationResult(): CirClassifier = main.resultOrNull ?: secondary.result + + override fun initialize(first: CirTypeAlias) = Unit + + @Suppress("ReplaceNegatedIsEmptyWithIsNotEmpty") + override fun doCommonizeWith(next: CirTypeAlias): Boolean { + val mainResult = main.commonizeWith(next) + val secondaryResult = secondary.commonizeWith(next) + + // Note: don't call commonizeWith() functions in return statement to avoid short-circuiting! + return mainResult || secondaryResult + } +} + +private class TypeAliasLiftingUpCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private lateinit var name: Name + private val typeParameters = TypeParameterListCommonizer(cache) + private val underlyingType = TypeCommonizer(cache) + private lateinit var expandedType: CirSimpleType + private val visibility = VisibilityCommonizer.lowering(allowPrivate = false) + + override fun commonizationResult(): CirTypeAlias = CirTypeAliasFactory.create( + annotations = emptyList(), + name = name, + typeParameters = typeParameters.result, + visibility = visibility.result, + underlyingType = underlyingType.result as CirSimpleType, + expandedType = expandedType + ) + + val resultOrNull: CirTypeAlias? + get() = if (hasResult) commonizationResult() else null + + override fun initialize(first: CirTypeAlias) { + name = first.name + expandedType = first.expandedType + } + + override fun doCommonizeWith(next: CirTypeAlias) = + typeParameters.commonizeWith(next.typeParameters) + && underlyingType.commonizeWith(next.underlyingType) + && visibility.commonizeWith(next) +} + +private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer() { + private lateinit var name: Name + private val classVisibility = VisibilityCommonizer.equalizing() + + override fun commonizationResult(): CirClass = CirClassFactory.create( annotations = emptyList(), name = name, typeParameters = emptyList(), - visibility = visibility.result, + visibility = classVisibility.result, modality = Modality.FINAL, kind = ClassKind.CLASS, companion = null, @@ -43,6 +96,5 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz next.typeParameters.isEmpty() // TAs with declared type parameters can't be commonized && next.underlyingType.arguments.isEmpty() // TAs with functional types or types with parameters at the right-hand side can't be commonized && next.underlyingType.kind == CirSimpleTypeKind.CLASS // right-hand side could have only class - && underlyingType.commonizeWith(next.underlyingType) - && visibility.commonizeWith(next) + && classVisibility.commonizeWith(next.underlyingType) // the visibilities of the right-hand classes should be equal } 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 1378ce7f581..a4274b78870 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 @@ -50,12 +50,7 @@ private fun areSimpleTypesEqual(cache: CirClassifiersCache, a: CirSimpleType, b: fun isClassOrTypeAliasUnderStandardKotlinPackages() = // N.B. only for descriptors that represent classes or type aliases, but not type parameters! - a.isClassOrTypeAlias && b.isClassOrTypeAlias - && a.fqName.isUnderStandardKotlinPackages - // If classes are from the standard Kotlin packages, compare them only by type constructors. - // Effectively, this includes comparison of 1) FQ names of underlying descriptors and 2) number of type constructor parameters. - // See org.jetbrains.kotlin.types.AbstractClassTypeConstructor.equals() for details. - && (a === b || a.expandedTypeConstructorId == b.expandedTypeConstructorId) + a.isClassOrTypeAlias && b.isClassOrTypeAlias && a.fqName.isUnderStandardKotlinPackages fun descriptorsCanBeCommonizedThemselves() = a.kind == b.kind && when (a.kind) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/VisibilityCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/VisibilityCommonizer.kt index 294c591224d..1fe77bff2b2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/VisibilityCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/VisibilityCommonizer.kt @@ -7,10 +7,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclarationWithVisibility import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunctionOrProperty +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirHasVisibility -abstract class VisibilityCommonizer(private val allowPrivate: Boolean) : Commonizer { +abstract class VisibilityCommonizer(private val allowPrivate: Boolean) : Commonizer { companion object { fun lowering(allowPrivate: Boolean = false): VisibilityCommonizer = LoweringVisibilityCommonizer(allowPrivate) @@ -22,7 +22,7 @@ abstract class VisibilityCommonizer(private val allowPrivate: Boolean) : Commoni override val result: Visibility get() = temp?.takeIf { it != Visibilities.UNKNOWN } ?: throw IllegalCommonizerStateException() - override fun commonizeWith(next: CirDeclarationWithVisibility): Boolean { + override fun commonizeWith(next: CirHasVisibility): Boolean { if (temp == Visibilities.UNKNOWN) return false @@ -37,7 +37,7 @@ abstract class VisibilityCommonizer(private val allowPrivate: Boolean) : Commoni return temp != Visibilities.UNKNOWN } - protected abstract fun canBeCommonized(next: CirDeclarationWithVisibility): Boolean + protected abstract fun canBeCommonized(next: CirHasVisibility): Boolean protected abstract fun getNext(current: Visibility, next: Visibility): Visibility } @@ -49,7 +49,7 @@ private class LoweringVisibilityCommonizer(allowPrivate: Boolean) : VisibilityCo private var atLeastOneVirtualCallableMet = false private var atLeastTwoVisibilitiesMet = false - override fun canBeCommonized(next: CirDeclarationWithVisibility): Boolean { + override fun canBeCommonized(next: CirHasVisibility): Boolean { if (!atLeastOneVirtualCallableMet) atLeastOneVirtualCallableMet = (next as? CirFunctionOrProperty)?.isVirtual() == true @@ -74,7 +74,7 @@ private class LoweringVisibilityCommonizer(allowPrivate: Boolean) : VisibilityCo * Make sure that visibilities of all member descriptors are equal and are not private according to [Visibilities.isPrivate]. */ private class EqualizingVisibilityCommonizer : VisibilityCommonizer(false) { - override fun canBeCommonized(next: CirDeclarationWithVisibility) = true + override fun canBeCommonized(next: CirHasVisibility) = true override fun getNext(current: Visibility, next: Visibility) = if (Visibilities.compare(current, next) == 0) current else Visibilities.UNKNOWN diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt index dacb89521f5..fa4655117ff 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.TargetProvider import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclaration import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.* import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassRecursionMarker +import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassifierRecursionMarker import org.jetbrains.kotlin.descriptors.commonizer.core.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.ClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup @@ -133,7 +134,7 @@ internal fun buildTypeAliasNode( descriptors = typeAliases, targetDeclarationProducer = CirTypeAliasFactory::create, commonValueProducer = { commonize(it, TypeAliasCommonizer(cacheRW)) }, - recursionMarker = CirClassRecursionMarker, + recursionMarker = CirClassifierRecursionMarker, nodeProducer = ::CirTypeAliasNode ).also { node -> typeAliases.firstNonNull().fqNameSafe.intern().let { fqName -> diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodes.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodes.kt index 843ba5d2c9c..cd6cd5bb858 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodes.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodes.kt @@ -118,8 +118,8 @@ class CirClassConstructorNode( class CirTypeAliasNode( override val target: List, - override val common: NullableLazyValue -) : CirNodeWithFqName { + override val common: NullableLazyValue +) : CirNodeWithFqName { override lateinit var fqName: FqName override fun accept(visitor: CirNodeVisitor, data: T): R = diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/EqualizingVisibilityCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/EqualizingVisibilityCommonizerTest.kt index 555edcf37f9..366d221d3d1 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/EqualizingVisibilityCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/EqualizingVisibilityCommonizerTest.kt @@ -7,10 +7,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.Visibilities.* import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclarationWithVisibility +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirHasVisibility import org.junit.Test -class EqualizingVisibilityCommonizerTest : AbstractCommonizerTest() { +class EqualizingVisibilityCommonizerTest : AbstractCommonizerTest() { @Test fun publicOnly() = doTestSuccess( @@ -63,6 +63,6 @@ class EqualizingVisibilityCommonizerTest : AbstractCommonizerTest() { +) : AbstractCommonizerTest() { @Test fun publicOnly() = doTestSuccess(