From f5bb60f7cd6d7e56c1a6321c13cd782b9df8d8b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Mon, 19 Oct 2020 20:33:23 +0300 Subject: [PATCH] [Commonizer] Refactor CIR type representation 1. Drop CirClassifierId 2. Specialized classes for each kind of types (classes, TAs, type parameters, flexible types). 3. TypeCommonizer now returns commonized type. In case of TAs this could be a completely new type describing expect class or a new TA with the different underlying type. --- .../builder/CommonizedTypeAliasDescriptor.kt | 12 +- .../commonizer/builder/builderUtils.kt | 93 ++++--- .../commonizer/cir/CirAnnotation.kt | 2 +- .../commonizer/cir/CirClassifierId.kt | 18 -- .../descriptors/commonizer/cir/CirType.kt | 102 ++++++- .../commonizer/cir/CirTypeAlias.kt | 4 +- .../cir/factory/CirAnnotationFactory.kt | 6 +- .../cir/factory/CirClassifierIdFactory.kt | 38 --- .../cir/factory/CirTypeAliasFactory.kt | 21 +- .../commonizer/cir/factory/CirTypeFactory.kt | 176 +++++++++--- .../commonizer/cir/impl/CirAnnotationImpl.kt | 4 +- ...rSimpleTypeImpl.kt => CirClassTypeImpl.kt} | 27 +- .../commonizer/cir/impl/CirTypeAliasImpl.kt | 17 +- .../cir/impl/CirTypeAliasTypeImpl.kt | 48 ++++ .../commonizer/core/AnnotationsCommonizer.kt | 11 +- .../core/CallableValueParametersCommonizer.kt | 5 +- .../commonizer/core/CommonizationVisitor.kt | 4 +- .../descriptors/commonizer/core/Commonizer.kt | 2 +- .../commonizer/core/TypeAliasCommonizer.kt | 105 ++++--- .../commonizer/core/TypeCommonizer.kt | 256 +++++++++++++----- .../descriptors/commonizer/utils/type.kt | 17 +- .../commonized/common/package_root.kt | 16 ++ .../returnTypes/commonized/js/package_root.kt | 16 ++ .../commonized/jvm/package_root.kt | 16 ++ .../returnTypes/original/js/package_root.kt | 16 ++ .../returnTypes/original/jvm/package_root.kt | 16 ++ .../common/package_kotlinx_cinterop.kt | 11 +- .../commonized/common/package_root.kt | 6 + .../linux/package_kotlinx_cinterop.kt | 11 +- .../commonized/linux/package_root.kt | 2 + .../macos/package_kotlinx_cinterop.kt | 11 +- .../commonized/macos/package_root.kt | 2 + .../linux/package_kotlinx_cinterop.kt | 11 +- .../original/linux/package_root.kt | 5 + .../macos/package_kotlinx_cinterop.kt | 11 +- .../original/macos/package_root.kt | 5 + .../core/AnnotationsCommonizerTest.kt | 4 +- .../commonizer/core/TypeCommonizerTest.kt | 14 +- .../core/ValueParameterCommonizerTest.kt | 5 +- .../utils/ComparingDeclarationsVisitor.kt | 12 - 40 files changed, 818 insertions(+), 340 deletions(-) delete mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt delete mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt rename native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/{CirSimpleTypeImpl.kt => CirClassTypeImpl.kt} (60%) create mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasTypeImpl.kt diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedTypeAliasDescriptor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedTypeAliasDescriptor.kt index f667a93faab..976c0dd2152 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedTypeAliasDescriptor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedTypeAliasDescriptor.kt @@ -17,12 +17,12 @@ import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.asSimpleType class CommonizedTypeAliasDescriptor( - override val storageManager: StorageManager, - containingDeclaration: DeclarationDescriptor, - annotations: Annotations, - name: Name, - visibility: DescriptorVisibility, - private val isActual: Boolean + override val storageManager: StorageManager, + containingDeclaration: DeclarationDescriptor, + annotations: Annotations, + name: Name, + visibility: DescriptorVisibility, + private val isActual: Boolean ) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility) { private lateinit var underlyingTypeImpl: NotNullLazyValue diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt index 65a9a910066..5038e4d54df 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -101,31 +100,32 @@ internal fun CirSimpleType.buildType( targetComponents: TargetDeclarationsBuilderComponents, typeParameterResolver: TypeParameterResolver, expandTypeAliases: Boolean -): SimpleType { - val classifier: ClassifierDescriptor = when (val classifierId = classifierId) { - is CirClassifierId.Class -> { - targetComponents.findClassOrTypeAlias(classifierId.classId).checkClassifierType() - } - is CirClassifierId.TypeAlias -> { - val classId = classifierId.classId - val classOrTypeAlias: ClassifierDescriptorWithTypeParameters = targetComponents.findClassOrTypeAlias(classId) +): SimpleType = when (this) { + is CirClassType -> buildSimpleType( + classifier = targetComponents.findClassOrTypeAlias(classifierId).checkClassifierType(), + arguments = collectArguments(targetComponents, typeParameterResolver, expandTypeAliases), + isMarkedNullable = isMarkedNullable + ) + is CirTypeAliasType -> { + val typeAliasDescriptor = targetComponents.findClassOrTypeAlias(classifierId).checkClassifierType() + val arguments = this.arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) } - if (classId.packageFqName.isUnderStandardKotlinPackages || !targetComponents.isCommon) { - // classifier type could be only type alias - classOrTypeAlias.checkClassifierType() - } else { - // classifier could be class or type alias - classOrTypeAlias - } - } - is CirClassifierId.TypeParameter -> { - typeParameterResolver.resolve(classifierId.index) - ?: error("Type parameter $classifierId not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}") - } + if (expandTypeAliases) + buildExpandedType(typeAliasDescriptor, arguments, isMarkedNullable) + else + buildSimpleType(typeAliasDescriptor, arguments, isMarkedNullable) } + is CirTypeParameterType -> buildSimpleType( + classifier = typeParameterResolver.resolve(index) + ?: error("Type parameter with index=$index not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}"), + arguments = emptyList(), + isMarkedNullable = isMarkedNullable + ) +} - val arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) } - val simpleType = simpleType( +@Suppress("NOTHING_TO_INLINE") +private inline fun buildSimpleType(classifier: ClassifierDescriptor, arguments: List, isMarkedNullable: Boolean) = + simpleType( annotations = Annotations.EMPTY, constructor = classifier.typeConstructor, arguments = arguments, @@ -133,29 +133,46 @@ internal fun CirSimpleType.buildType( kotlinTypeRefiner = null ) - return if (expandTypeAliases && classifier is TypeAliasDescriptor) { - val expandedType = TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation( - TypeAliasExpansion.create(null, classifier, arguments), - Annotations.EMPTY - ) +@Suppress("NOTHING_TO_INLINE") +private inline fun buildExpandedType(classifier: TypeAliasDescriptor, arguments: List, isMarkedNullable: Boolean) = + TypeAliasExpander.NON_REPORTING.expand( + TypeAliasExpansion.create(null, classifier, arguments), + Annotations.EMPTY + ).makeNullableAsSpecified(isMarkedNullable) - expandedType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType) - } else - simpleType -} private inline fun ClassifierDescriptorWithTypeParameters.checkClassifierType(): T { check(this is T) { "Mismatched classifier kinds.\nFound: ${this::class.java}, $this\nShould be: ${T::class.java}" } return this } +private fun CirClassType.collectArguments( + targetComponents: TargetDeclarationsBuilderComponents, + typeParameterResolver: TypeParameterResolver, + expandTypeAliases: Boolean +): List { + return if (outerType == null) { + arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) } + } else { + val allTypes = generateSequence(this) { it.outerType }.toList() + val arguments = mutableListOf() + + for (index in allTypes.size - 1 downTo 0) { + allTypes[index].arguments.mapTo(arguments) { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) } + } + + arguments.toList() + } +} + private fun CirTypeProjection.buildArgument( targetComponents: TargetDeclarationsBuilderComponents, typeParameterResolver: TypeParameterResolver, expandTypeAliases: Boolean -): TypeProjection = - if (isStarProjection) { - StarProjectionForAbsentTypeParameter(targetComponents.builtIns) - } else { - TypeProjectionImpl(projectionKind, type.buildType(targetComponents, typeParameterResolver, expandTypeAliases)) - } +): TypeProjection = when (this) { + is CirStarTypeProjection -> StarProjectionForAbsentTypeParameter(targetComponents.builtIns) + is CirTypeProjectionImpl -> TypeProjectionImpl( + projectionKind, + type.buildType(targetComponents, typeParameterResolver, expandTypeAliases) + ) +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt index 0025b1e847f..e8a042ff233 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue interface CirAnnotation { - val type: CirSimpleType + val type: CirClassType val constantValueArguments: Map> val annotationValueArguments: Map } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt deleted file mode 100644 index 4e2ca2bc0bb..00000000000 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 - -import org.jetbrains.kotlin.name.ClassId - -sealed class CirClassifierId { - interface ClassOrTypeAlias { - val classId: ClassId - } - - data class Class(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId() - data class TypeAlias(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId() - data class TypeParameter(val index: Int) : CirClassifierId() -} 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 0edb01fe947..6f2d7f958d0 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,31 +5,107 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir -import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.Variance typealias CirTypeSignature = String -sealed class CirType +/** + * The hierarchy of [CirType]: + * + * [CirType] + * / \ + * [CirFlexibleType] [CirSimpleType] + * / \ + * [CirTypeParameterType] [CirClassOrTypeAliasType] + * / \ + * [CirClassType] [CirTypeAliasType] + */ +sealed class CirType { + final override fun toString() = buildString { appendDescriptionTo(this) } + internal abstract fun appendDescriptionTo(builder: StringBuilder) +} + +data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSimpleType) : CirType() { + override fun appendDescriptionTo(builder: StringBuilder) { + builder.append("lower = ") + lowerBound.appendDescriptionTo(builder) + builder.append(", upper = ") + upperBound.appendDescriptionTo(builder) + } +} + +/** + * Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost. + */ +sealed class CirSimpleType : CirType() { + abstract val isMarkedNullable: Boolean + + override fun appendDescriptionTo(builder: StringBuilder) { + if (isMarkedNullable) builder.append('?') + } +} + +data class CirTypeParameterType( + val index: Int, + override val isMarkedNullable: Boolean +) : CirSimpleType() { + override fun appendDescriptionTo(builder: StringBuilder) { + builder.append('#').append(index) + super.appendDescriptionTo(builder) + } +} + +sealed class CirClassOrTypeAliasType : CirSimpleType() { + abstract val classifierId: ClassId + abstract val arguments: List + + override fun appendDescriptionTo(builder: StringBuilder) { + builder.append(classifierId.asString()) + if (arguments.isNotEmpty()) arguments.joinTo(builder, prefix = "<", postfix = ">") + super.appendDescriptionTo(builder) + } +} + +abstract class CirClassType : CirClassOrTypeAliasType(), CirHasVisibility { + abstract val outerType: CirClassType? + + override fun appendDescriptionTo(builder: StringBuilder) { + outerType?.let { + it.appendDescriptionTo(builder) + builder.append('.') + } + super.appendDescriptionTo(builder) + } +} /** * 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. - * - * There is no difference between "abbreviation" and "expanded" for types representing classes and type parameters. - * For details, see [CirTypeFactory]. - * - * Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost. */ -abstract class CirSimpleType : CirType(), CirHasVisibility { - abstract val classifierId: CirClassifierId - abstract val arguments: List - abstract val isMarkedNullable: Boolean +abstract class CirTypeAliasType : CirClassOrTypeAliasType() { + abstract val underlyingType: CirClassOrTypeAliasType + + override fun appendDescriptionTo(builder: StringBuilder) { + super.appendDescriptionTo(builder) + builder.append(" -> ") + underlyingType.appendDescriptionTo(builder) + } } -data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSimpleType) : CirType() +sealed class CirTypeProjection -data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType) +object CirStarTypeProjection : CirTypeProjection() { + override fun toString() = "*" +} + +data class CirTypeProjectionImpl(val projectionKind: Variance, val type: CirType) : CirTypeProjection() { + override fun toString() = buildString { + append(projectionKind) + if (isNotEmpty()) append(' ') + type.appendDescriptionTo(this) + } +} 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 e9592c4fb71..149397d8a1b 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 @@ -6,6 +6,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration { - val underlyingType: CirSimpleType - val expandedType: CirSimpleType + val underlyingType: CirClassOrTypeAliasType + val expandedType: CirClassType } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt index 226fd087fe6..560f1118b40 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory import gnu.trove.THashMap import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.checkConstantSupportedInCommonization @@ -21,7 +21,7 @@ object CirAnnotationFactory { private val interner = Interner() fun create(source: AnnotationDescriptor): CirAnnotation { - val type = CirTypeFactory.create(source.type) as CirSimpleType + val type = CirTypeFactory.create(source.type, useAbbreviation = false) as CirClassType val allValueArguments: Map> = source.allValueArguments if (allValueArguments.isEmpty()) @@ -52,7 +52,7 @@ object CirAnnotationFactory { } fun create( - type: CirSimpleType, + type: CirClassType, constantValueArguments: Map>, annotationValueArguments: Map ): CirAnnotation { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt deleted file mode 100644 index 02839ff12ea..00000000000 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt +++ /dev/null @@ -1,38 +0,0 @@ -package org.jetbrains.kotlin.descriptors.commonizer.cir.factory - -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId -import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner -import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId -import org.jetbrains.kotlin.name.ClassId - -@Suppress("MemberVisibilityCanBePrivate") -object CirClassifierIdFactory { - private val interner = Interner() - - fun create(source: ClassifierDescriptor): CirClassifierId { - return when (source) { - is ClassDescriptor -> createForClass(source.internedClassId) - is TypeAliasDescriptor -> createForTypeAlias(source.internedClassId) - is TypeParameterDescriptor -> createForTypeParameter(source.typeParameterIndex) - else -> error("Unexpected classifier descriptor type: ${source::class.java}, $this") - } - } - - fun createForClass(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.Class(classId)) - fun createForTypeAlias(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.TypeAlias(classId)) - fun createForTypeParameter(index: Int): CirClassifierId = interner.intern(CirClassifierId.TypeParameter(index)) -} - -private inline val TypeParameterDescriptor.typeParameterIndex: Int - get() { - var index = index - var parent = containingDeclaration - - while ((parent as? ClassifierDescriptorWithTypeParameters)?.isInner != false) { - parent = parent.containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: break - index += parent.declaredTypeParameters.size - } - - return index - } 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 8926083b578..01ff9904709 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 @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.descriptors.DescriptorVisibility -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.* import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.intern import org.jetbrains.kotlin.name.Name @@ -21,18 +18,18 @@ object CirTypeAliasFactory { name = source.name.intern(), typeParameters = source.declaredTypeParameters.map(CirTypeParameterFactory::create), visibility = source.visibility, - underlyingType = CirTypeFactory.create(source.underlyingType), - expandedType = CirTypeFactory.create(source.expandedType, useAbbreviation = false) + underlyingType = CirTypeFactory.create(source.underlyingType, useAbbreviation = true) as CirClassOrTypeAliasType, + expandedType = CirTypeFactory.create(source.expandedType, useAbbreviation = false) as CirClassType ) @Suppress("NOTHING_TO_INLINE") inline fun create( - annotations: List, - name: Name, - typeParameters: List, - visibility: DescriptorVisibility, - underlyingType: CirSimpleType, - expandedType: CirSimpleType + annotations: List, + name: Name, + typeParameters: List, + visibility: DescriptorVisibility, + underlyingType: CirClassOrTypeAliasType, + expandedType: CirClassType ): CirTypeAlias { return CirTypeAliasImpl( annotations = annotations, 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 685e31d1f7e..418b4991e6f 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,58 +5,168 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters -import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.descriptors.DescriptorVisibility +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirSimpleTypeImpl +import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassTypeImpl +import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasTypeImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.declarationDescriptor +import org.jetbrains.kotlin.descriptors.commonizer.utils.extractExpandedType +import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.* object CirTypeFactory { - private val interner = Interner() + private val classTypeInterner = Interner() + private val typeAliasTypeInterner = Interner() + private val typeParameterTypeInterner = Interner() - fun create(source: KotlinType): CirType = source.unwrap().run { + fun create(source: KotlinType, useAbbreviation: Boolean = true): CirType = source.unwrap().run { when (this) { - is SimpleType -> create(this) - is FlexibleType -> CirFlexibleType(create(lowerBound), create(upperBound)) + is SimpleType -> create(this, useAbbreviation) + is FlexibleType -> CirFlexibleType(create(lowerBound, useAbbreviation), create(upperBound, useAbbreviation)) } } - fun create(source: SimpleType, useAbbreviation: Boolean = true): CirSimpleType { - @Suppress("NAME_SHADOWING") - val source = if (useAbbreviation && source is AbbreviatedType) source.abbreviation else source - val classifierDescriptor: ClassifierDescriptor = source.declarationDescriptor + fun create(source: SimpleType, useAbbreviation: Boolean): CirSimpleType { + if (useAbbreviation && source is AbbreviatedType) { + val abbreviation = source.abbreviation + when (val classifierDescriptor = abbreviation.declarationDescriptor) { + is TypeAliasDescriptor -> { + return createTypeAliasType( + typeAliasId = classifierDescriptor.internedClassId, + underlyingType = create(extractExpandedType(source), useAbbreviation = true) as CirClassOrTypeAliasType, + arguments = createArguments(abbreviation.arguments, useAbbreviation = true), + isMarkedNullable = abbreviation.isMarkedNullable + ) + } + else -> error("Unexpected classifier descriptor type for abbreviation type: ${classifierDescriptor::class.java}, $classifierDescriptor, ${source.abbreviation}") + } + } - return create( - classifierId = CirClassifierIdFactory.create(classifierDescriptor), - visibility = (classifierDescriptor as? ClassifierDescriptorWithTypeParameters)?.visibility ?: DescriptorVisibilities.UNKNOWN, - arguments = source.arguments.map { projection -> - CirTypeProjection( - projectionKind = projection.projectionKind, - isStarProjection = projection.isStarProjection, - type = create(projection.type) + return when (val classifierDescriptor = source.declarationDescriptor) { + is ClassDescriptor -> createClassTypeWithAllOuterTypes( + classDescriptor = classifierDescriptor, + arguments = createArguments(source.arguments, useAbbreviation), + isMarkedNullable = source.isMarkedNullable + ) + is TypeAliasDescriptor -> { + val abbreviatedType = TypeAliasExpander.NON_REPORTING.expand( + TypeAliasExpansion.create(null, classifierDescriptor, source.arguments), + Annotations.EMPTY + ) as AbbreviatedType + + createTypeAliasType( + typeAliasId = classifierDescriptor.internedClassId, + underlyingType = create(extractExpandedType(abbreviatedType), useAbbreviation = true) as CirClassOrTypeAliasType, + arguments = createArguments(source.arguments, useAbbreviation = true), + isMarkedNullable = source.isMarkedNullable ) - }, - isMarkedNullable = source.isMarkedNullable - ) + } + is TypeParameterDescriptor -> createTypeParameterType(classifierDescriptor.typeParameterIndex, source.isMarkedNullable) + else -> error("Unexpected classifier descriptor type: ${classifierDescriptor::class.java}, $classifierDescriptor, $source") + } } - fun create( - classifierId: CirClassifierId, - visibility: DescriptorVisibility, - arguments: List, - isMarkedNullable: Boolean - ): CirSimpleType { - return interner.intern( - CirSimpleTypeImpl( - classifierId = classifierId, + fun createClassType( + classId: ClassId, + outerType: CirClassType?, + visibility: DescriptorVisibility, + arguments: List, + isMarkedNullable: Boolean + ): CirClassType { + return classTypeInterner.intern( + CirClassTypeImpl( + classifierId = classId, + outerType = outerType, visibility = visibility, arguments = arguments, isMarkedNullable = isMarkedNullable ) ) } + + fun createTypeAliasType( + typeAliasId: ClassId, + underlyingType: CirClassOrTypeAliasType, + arguments: List, + isMarkedNullable: Boolean + ): CirTypeAliasType { + return typeAliasTypeInterner.intern( + CirTypeAliasTypeImpl( + classifierId = typeAliasId, + underlyingType = underlyingType, + arguments = arguments, + isMarkedNullable = isMarkedNullable + ) + ) + } + + fun createTypeParameterType( + index: Int, + isMarkedNullable: Boolean + ): CirTypeParameterType { + return typeParameterTypeInterner.intern( + CirTypeParameterType( + index = index, + isMarkedNullable = isMarkedNullable + ) + ) + } + + private fun createClassTypeWithAllOuterTypes( + classDescriptor: ClassDescriptor, + arguments: List, + isMarkedNullable: Boolean + ): CirClassType { + val outerType: CirClassType? + val remainingArguments: List + + if (classDescriptor.isInner) { + val declaredTypeParametersCount = classDescriptor.declaredTypeParameters.size + outerType = createClassTypeWithAllOuterTypes( + classDescriptor = classDescriptor.containingDeclaration as ClassDescriptor, + arguments = arguments.subList(0, arguments.size - declaredTypeParametersCount), + isMarkedNullable = false // don't pass nullable flag to outer types + ) + remainingArguments = arguments.subList(arguments.size - declaredTypeParametersCount, arguments.size) + } else { + outerType = null + remainingArguments = arguments + } + + return createClassType( + classId = classDescriptor.internedClassId, + outerType = outerType, + visibility = classDescriptor.visibility, + arguments = remainingArguments, + isMarkedNullable = isMarkedNullable + ) + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun createArguments(arguments: List, useAbbreviation: Boolean): List = + arguments.map { projection -> + if (projection.isStarProjection) + CirStarTypeProjection + else + CirTypeProjectionImpl( + projectionKind = projection.projectionKind, + type = create(projection.type, useAbbreviation) + ) + } + + private inline val TypeParameterDescriptor.typeParameterIndex: Int + get() { + var index = index + var parent = containingDeclaration + + while ((parent as? ClassifierDescriptorWithTypeParameters)?.isInner != false) { + parent = parent.containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: break + index += parent.declaredTypeParameters.size + } + + return index + } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt index db9bc13945d..01c4ea35f9d 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt @@ -6,14 +6,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue data class CirAnnotationImpl( - override val type: CirSimpleType, + override val type: CirClassType, override val constantValueArguments: Map>, override val annotationValueArguments: Map ) : CirAnnotation { 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/CirClassTypeImpl.kt similarity index 60% rename from native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt rename to native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirClassTypeImpl.kt index 2392c002d39..7d91040dd2a 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/CirClassTypeImpl.kt @@ -6,20 +6,24 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.DescriptorVisibility -import org.jetbrains.kotlin.descriptors.commonizer.cir.* +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode +import org.jetbrains.kotlin.name.ClassId -data class CirSimpleTypeImpl( - override val classifierId: CirClassifierId, - override val visibility: DescriptorVisibility, // visibility of the classifier descriptor - override val arguments: List, - override val isMarkedNullable: Boolean -) : CirSimpleType() { +data class CirClassTypeImpl( + override val classifierId: ClassId, + override val outerType: CirClassType?, + override val visibility: DescriptorVisibility, // visibility of the class descriptor + override val arguments: List, + override val isMarkedNullable: Boolean, +) : CirClassType() { // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode private var cachedHashCode = 0 private fun computeHashCode() = hashCode(classifierId) + .appendHashCode(outerType) .appendHashCode(visibility) .appendHashCode(arguments) .appendHashCode(isMarkedNullable) @@ -33,13 +37,14 @@ data class CirSimpleTypeImpl( return currentHashCode } - override fun equals(other: Any?) = when { + override fun equals(other: Any?): Boolean = when { other === this -> true - other is CirSimpleType -> { - isMarkedNullable == other.isMarkedNullable - && classifierId == other.classifierId + other is CirClassType -> { + classifierId == other.classifierId + && isMarkedNullable == other.isMarkedNullable && visibility == other.visibility && arguments == other.arguments + && outerType == other.outerType } else -> false } 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 bc3ba945615..6cb409db0a3 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 @@ -6,19 +6,16 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.DescriptorVisibility -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.* import org.jetbrains.kotlin.name.Name data class CirTypeAliasImpl( - override val annotations: List, - override val name: Name, - override val typeParameters: List, - override val visibility: DescriptorVisibility, - override val underlyingType: CirSimpleType, - override val expandedType: CirSimpleType // only for commonization algorithm; does not participate in building resulting declarations + override val annotations: List, + override val name: Name, + override val typeParameters: List, + override val visibility: DescriptorVisibility, + override val underlyingType: CirClassOrTypeAliasType, + override val expandedType: CirClassType // only for commonization algorithm; does not participate in building resulting declarations ) : 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/CirTypeAliasTypeImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasTypeImpl.kt new file mode 100644 index 00000000000..9631f7a0ae0 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirTypeAliasTypeImpl.kt @@ -0,0 +1,48 @@ +/* + * 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.impl + +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassOrTypeAliasType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAliasType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection +import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode +import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode +import org.jetbrains.kotlin.name.ClassId + +data class CirTypeAliasTypeImpl( + override val classifierId: ClassId, + override val underlyingType: CirClassOrTypeAliasType, + override val arguments: List, + override val isMarkedNullable: Boolean +) : CirTypeAliasType() { + // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode + private var cachedHashCode = 0 + + private fun computeHashCode() = hashCode(classifierId) + .appendHashCode(underlyingType) + .appendHashCode(arguments) + .appendHashCode(isMarkedNullable) + + override fun hashCode(): Int { + var currentHashCode = cachedHashCode + if (currentHashCode != 0) return currentHashCode + + currentHashCode = computeHashCode() + cachedHashCode = currentHashCode + return currentHashCode + } + + override fun equals(other: Any?): Boolean = when { + other === this -> true + other is CirTypeAliasType -> { + classifierId == other.classifierId + && underlyingType == other.underlyingType + && isMarkedNullable == other.isMarkedNullable + && arguments == other.arguments + } + else -> false + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt index 6811e38b8cf..9c998441783 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt @@ -7,9 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory -import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassifierIdFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_CID @@ -38,9 +36,7 @@ class AnnotationsCommonizer : AbstractStandardCommonizer, Li override fun initialize(first: List) = Unit override fun doCommonizeWith(next: List): Boolean { - val nextDeprecatedAnnotation = next.firstOrNull { annotation -> - (annotation.type.classifierId as? CirClassifierId.Class)?.classId == DEPRECATED_ANNOTATION_CID - } ?: return true + val nextDeprecatedAnnotation = next.firstOrNull { it.type.classifierId == DEPRECATED_ANNOTATION_CID } ?: return true val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer ?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it } @@ -160,8 +156,9 @@ private class DeprecatedAnnotationCommonizer : Commonizer - (annotation.type.classifierId as? CirClassifierId.ClassOrTypeAlias)?.classId?.isObjCInteropCallableAnnotation == true - } + return (this as CirHasAnnotations).annotations.none { it.type.classifierId.isObjCInteropCallableAnnotation } } private fun failIllegalState(current: ValueParameterNames?, next: ValueParameterNames): Nothing = diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt index 1f6b43629a6..11fa5d110f4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt @@ -6,13 +6,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages -import org.jetbrains.kotlin.utils.addToStdlib.cast internal class CommonizationVisitor( private val root: CirRootNode @@ -128,7 +126,7 @@ internal class CommonizationVisitor( private fun CirTypeAliasNode.collectCommonSupertypes(): Map>? { val supertypesMap: MutableMap> = linkedMapOf() // preserve supertype order for ((index, typeAlias) in targetDeclarations.withIndex()) { - val expandedClassId = typeAlias!!.expandedType.classifierId.cast().classId + val expandedClassId = typeAlias!!.expandedType.classifierId if (expandedClassId.packageFqName.isUnderStandardKotlinPackages) return null // this case is not supported 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 d073f21474c..1a9333f74d4 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 @@ -56,7 +56,7 @@ fun Commonizer<*, *>.failInEmptyState(): Nothing = throw IllegalCommonizerStateE @Suppress("unused") fun Commonizer<*, *>.failInErrorState(): Nothing = throw IllegalCommonizerStateException("empty") -fun Commonizer<*, *>.checkState(value: T?, error: Boolean): T = when { +inline fun Commonizer<*, *>.checkState(value: T?, error: Boolean): T = when { value == null -> failInEmptyState() error -> failInErrorState() else -> value 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 530d989d007..59719e19ca7 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 @@ -11,6 +11,7 @@ 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.descriptors.commonizer.utils.isUnderStandardKotlinPackages import org.jetbrains.kotlin.name.Name /** @@ -32,7 +33,6 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz override fun initialize(first: CirTypeAlias) = Unit - @Suppress("ReplaceNegatedIsEmptyWithIsNotEmpty") override fun doCommonizeWith(next: CirTypeAlias): Boolean { val primaryResult = primary.commonizeWith(next) val secondaryResult = secondary.commonizeWith(next) @@ -46,19 +46,59 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { private lateinit var name: Name private val typeParameters = TypeParameterListCommonizer(cache) + private lateinit var underlyingType: CirClassOrTypeAliasType private val expandedType = TypeCommonizer(cache) private val visibility = VisibilityCommonizer.lowering() + override fun commonizationResult() = CirTypeAliasFactory.create( + annotations = emptyList(), + name = name, + typeParameters = typeParameters.result, + visibility = visibility.result, + underlyingType = computeCommonizedUnderlyingType(underlyingType), + expandedType = expandedType.result as CirClassType + ) + + val resultOrNull: CirTypeAlias? + get() = if (hasResult) commonizationResult() else null + + override fun initialize(first: CirTypeAlias) { + name = first.name + underlyingType = first.underlyingType + } + + override fun doCommonizeWith(next: CirTypeAlias) = + typeParameters.commonizeWith(next.typeParameters) + && expandedType.commonizeWith(next.expandedType) + && visibility.commonizeWith(next) + + private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType { + return when (underlyingType) { + is CirClassType -> underlyingType + is CirTypeAliasType -> if (underlyingType.classifierId.packageFqName.isUnderStandardKotlinPackages) + underlyingType + else + computeCommonizedUnderlyingType(underlyingType.underlyingType) + } + } +} + +private class TypeAliasLiftingUpCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private lateinit var name: Name + private val typeParameters = TypeParameterListCommonizer(cache) + private val underlyingType = TypeCommonizer(cache) + private val visibility = VisibilityCommonizer.lowering() + override fun commonizationResult(): CirTypeAlias { - val expandedType = expandedType.result as CirSimpleType + val underlyingType = underlyingType.result as CirClassOrTypeAliasType return CirTypeAliasFactory.create( annotations = emptyList(), name = name, typeParameters = typeParameters.result, visibility = visibility.result, - underlyingType = expandedType, // pass expanded type as underlying type - expandedType = expandedType + underlyingType = underlyingType, + expandedType = computeCommonizedExpandedType(underlyingType) ) } @@ -69,40 +109,17 @@ private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : A name = first.name } - override fun doCommonizeWith(next: CirTypeAlias) = - typeParameters.commonizeWith(next.typeParameters) - && expandedType.commonizeWith(next.expandedType) - && visibility.commonizeWith(next) -} - -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() - - 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 tailrec fun computeCommonizedExpandedType(underlyingType: CirClassOrTypeAliasType): CirClassType { + return when (underlyingType) { + is CirClassType -> underlyingType + is CirTypeAliasType -> computeCommonizedExpandedType(underlyingType.underlyingType) + } + } } private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer() { @@ -129,9 +146,19 @@ private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer true + type.arguments.isNotEmpty() -> false + else -> hasNoArguments(type.outerType) + } } 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 4ff0cf25761..5ab61fe96d0 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 @@ -5,105 +5,231 @@ package org.jetbrains.kotlin.descriptors.commonizer.core +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.commonizer.cir.* +import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages -import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.Variance class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer() { - private lateinit var temp: CirType + private lateinit var wrapped: Commonizer<*, CirType> - override fun commonizationResult() = temp + override fun commonizationResult() = wrapped.result override fun initialize(first: CirType) { - temp = first + @Suppress("UNCHECKED_CAST") + wrapped = when (first) { + is CirClassType -> ClassTypeCommonizer(cache) + is CirTypeAliasType -> TypeAliasTypeCommonizer(cache) + is CirTypeParameterType -> TypeParameterTypeCommonizer() + is CirFlexibleType -> FlexibleTypeCommonizer(cache) + } as Commonizer<*, CirType> } - override fun doCommonizeWith(next: CirType) = areTypesEqual(cache, temp, next) + override fun doCommonizeWith(next: CirType) = when (next) { + is CirClassType -> (wrapped as? ClassTypeCommonizer)?.commonizeWith(next) == true + is CirTypeAliasType -> (wrapped as? TypeAliasTypeCommonizer)?.commonizeWith(next) == true + is CirTypeParameterType -> (wrapped as? TypeParameterTypeCommonizer)?.commonizeWith(next) == true + is CirFlexibleType -> (wrapped as? FlexibleTypeCommonizer)?.commonizeWith(next) == true + } } -/** - * See also [AbstractStrictEqualityTypeChecker]. - */ -@Suppress("IntroduceWhenSubject") -internal fun areTypesEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean = when { - a is CirSimpleType -> (b is CirSimpleType) && areSimpleTypesEqual(cache, a, b) - a is CirFlexibleType -> (b is CirFlexibleType) - && areSimpleTypesEqual(cache, a.lowerBound, b.lowerBound) - && areSimpleTypesEqual(cache, a.upperBound, b.upperBound) - else -> false +private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private lateinit var classId: ClassId + private val outerType = OuterClassTypeCommonizer(cache) + private lateinit var anyVisibility: DescriptorVisibility + private val arguments = TypeArgumentListCommonizer(cache) + private var isMarkedNullable = false + + override fun commonizationResult() = CirTypeFactory.createClassType( + 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 + ) + + override fun initialize(first: CirClassType) { + classId = first.classifierId + anyVisibility = first.visibility + isMarkedNullable = first.isMarkedNullable + } + + override fun doCommonizeWith(next: CirClassType) = + isMarkedNullable == next.isMarkedNullable + && classId == next.classifierId + && outerType.commonizeWith(next.outerType) + && commonizeClassifier(classId, cache.classes).first + && arguments.commonizeWith(next.arguments) } -private fun areSimpleTypesEqual(cache: CirClassifiersCache, a: CirSimpleType, b: CirSimpleType): Boolean { - val aId = a.classifierId - val bId = b.classifierId +private class OuterClassTypeCommonizer(cache: CirClassifiersCache) : + AbstractNullableCommonizer( + wrappedCommonizerFactory = { ClassTypeCommonizer(cache) }, + extractor = { it }, + builder = { it } + ) - if (a !== b) { - if (a.arguments.size != b.arguments.size || a.isMarkedNullable != b.isMarkedNullable) { +private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) : + AbstractStandardCommonizer() { + + private lateinit var typeAliasId: ClassId + private val arguments = TypeArgumentListCommonizer(cache) + private var isMarkedNullable = false + private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet + + override fun commonizationResult() = + (commonizedTypeBuilder ?: failInEmptyState()).build( + typeAliasId = typeAliasId, + arguments = arguments.result, + isMarkedNullable = isMarkedNullable + ) + + override fun initialize(first: CirTypeAliasType) { + typeAliasId = first.classifierId + isMarkedNullable = first.isMarkedNullable + } + + override fun doCommonizeWith(next: CirTypeAliasType): Boolean { + if (isMarkedNullable != next.isMarkedNullable || typeAliasId != next.classifierId) return false + + if (commonizedTypeBuilder == null) { + val (commonized, commonClassifier) = commonizeClassifier(typeAliasId, cache.typeAliases) + if (!commonized) + return false + + commonizedTypeBuilder = when (commonClassifier) { + is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier) + is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier) + null -> CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(next.underlyingType) + else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier") + } } - if (aId is CirClassifierId.ClassOrTypeAlias) { - if (bId !is CirClassifierId.ClassOrTypeAlias || aId.classId != bId.classId) return false - } - - if (aId is CirClassifierId.TypeParameter) { - if (bId !is CirClassifierId.TypeParameter || aId.index != bId.index) return false - } + return arguments.commonizeWith(next.arguments) } - // N.B. only for descriptors that represent classes or type aliases, but not type parameters! - fun isClassOrTypeAliasUnderStandardKotlinPackages(): Boolean { - return (aId as? CirClassifierId.ClassOrTypeAlias)?.classId?.packageFqName?.isUnderStandardKotlinPackages == true - } + // builds a new type for "common" library fragment for the given combination of type alias types in "platform" fragments + private interface CommonizedTypeAliasTypeBuilder { + fun build(typeAliasId: ClassId, arguments: List, isMarkedNullable: Boolean): CirClassOrTypeAliasType - fun descriptorsCanBeCommonizedThemselves(): Boolean { - return when (aId) { - is CirClassifierId.Class -> bId is CirClassifierId.Class && cache.classes[aId.classId].canBeCommonized() - is CirClassifierId.TypeAlias -> bId is CirClassifierId.TypeAlias && cache.typeAliases[aId.classId].canBeCommonized() - is CirClassifierId.TypeParameter -> { - // Real type parameter commonization is performed in TypeParameterCommonizer. - // Here it is enough to check that FQ names are equal (which is already done above). - true + companion object { + // type alias has been commonized to expect class, need to build type for expect class + fun forClass(commonClass: CirClass) = object : CommonizedTypeAliasTypeBuilder { + override fun build(typeAliasId: ClassId, arguments: List, isMarkedNullable: Boolean) = + CirTypeFactory.createClassType( + classId = typeAliasId, + outerType = null, // there can't be outer type + visibility = commonClass.visibility, + arguments = arguments, + isMarkedNullable = isMarkedNullable + ) + } + + // type alias has been commonized to another type alias with the different underlying type, need to build type for + // new type alias + fun forTypeAlias(modifiedTypeAlias: CirTypeAlias) = forKnownUnderlyingType(modifiedTypeAlias.underlyingType) + + // type alias don't needs to be commonized because it is from the standard library + fun forKnownUnderlyingType(underlyingType: CirClassOrTypeAliasType) = object : CommonizedTypeAliasTypeBuilder { + override fun build(typeAliasId: ClassId, arguments: List, isMarkedNullable: Boolean) = + CirTypeFactory.createTypeAliasType( + typeAliasId = typeAliasId, + underlyingType = underlyingType, // TODO replace arguments??? + arguments = arguments, + isMarkedNullable = isMarkedNullable + ) } } } +} - val descriptorsCanBeCommonized = - /* either class or type alias from Kotlin stdlib */ isClassOrTypeAliasUnderStandardKotlinPackages() - || /* or descriptors themselves can be commonized */ descriptorsCanBeCommonizedThemselves() +private class TypeParameterTypeCommonizer : AbstractStandardCommonizer() { + private lateinit var temp: CirTypeParameterType - if (!descriptorsCanBeCommonized) - return false + override fun commonizationResult() = temp - // N.B. both lists of arguments are already known to be of the same size - for (i in a.arguments.indices) { - val aArg = a.arguments[i] - val bArg = b.arguments[i] + override fun initialize(first: CirTypeParameterType) { + temp = first + } - if (aArg.isStarProjection != bArg.isStarProjection) - return false + override fun doCommonizeWith(next: CirTypeParameterType): Boolean { + // Real type parameter commonization is performed in TypeParameterCommonizer. + // Here it is enough to check that type parameter indices and nullability are equal. + return temp == next + } +} - if (!aArg.isStarProjection) { - if (aArg.projectionKind != bArg.projectionKind) - return false +private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private val lowerBound = TypeCommonizer(cache) + private val upperBound = TypeCommonizer(cache) - if (!areTypesEqual(cache, aArg.type, bArg.type)) - return false + override fun commonizationResult() = CirFlexibleType( + lowerBound = lowerBound.result as CirSimpleType, + upperBound = upperBound.result as CirSimpleType + ) + + override fun initialize(first: CirFlexibleType) = Unit + + override fun doCommonizeWith(next: CirFlexibleType) = + lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound) +} + +private class TypeArgumentCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer() { + private var isStar = false + private lateinit var projectionKind: Variance + private val type = TypeCommonizer(cache) + + 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 } } - return true + override fun doCommonizeWith(next: CirTypeProjection) = when (next) { + is CirStarTypeProjection -> isStar + is CirTypeProjectionImpl -> !isStar && projectionKind == next.projectionKind && type.commonizeWith(next.type) + } } -@Suppress("NOTHING_TO_INLINE") -private inline fun CirNode<*, *>?.canBeCommonized() = - if (this == null) { - // No node means that the class or type alias was not subject for commonization at all, probably it lays - // not in commonized module descriptors but somewhere in their dependencies. - true - } else { - // If entry is present, then contents (common declaration) should not be null. - commonDeclaration() != null +private class TypeArgumentListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer( + singleElementCommonizerFactory = { TypeArgumentCommonizer(cache) } +) + +private inline fun commonizeClassifier( + classifierId: ClassId, + classifierNodes: Map>, +): Pair { + if (classifierId.packageFqName.isUnderStandardKotlinPackages) { + /* either class or type alias from Kotlin stdlib */ + return true to null } + + /* or descriptors themselves can be commonized */ + return when (val node = classifierNodes[classifierId]) { + null -> { + // No node means that the class or type alias was not subject for commonization at all, probably it lays + // not in commonized module descriptors but somewhere in their dependencies. + true to null + } + else -> { + // If entry is present, then contents (common declaration) should not be null. + val commonClassifier = node.commonDeclaration() + (commonClassifier != null) to commonClassifier + } + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt index c2f4b813bc3..d55607fe847 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt @@ -12,15 +12,24 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.descriptorUtil.classId -import org.jetbrains.kotlin.types.AbbreviatedType -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.makeNotNullable internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor")) +// eliminate unnecessary repeated abbreviations +internal fun extractExpandedType(abbreviated: AbbreviatedType): SimpleType { + var expanded = abbreviated.expandedType + while (expanded is AbbreviatedType) { + if (expanded.abbreviation.declarationDescriptor !== abbreviated.abbreviation.declarationDescriptor) + break + else + expanded = expanded.expandedType + } + return expanded +} + internal val ClassifierDescriptorWithTypeParameters.internedClassId: ClassId get() = when (val owner = containingDeclaration) { is PackageFragmentDescriptor -> internedClassId(owner.fqName.intern(), name.intern()) diff --git a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt index b9c447c812e..77e197d25b9 100644 --- a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt +++ b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt @@ -40,3 +40,19 @@ expect fun functionWithTypeParametersInReturnType12(): Box expect fun functionWithUnsubstitutedTypeParametersInReturnType1(): T expect fun functionWithUnsubstitutedTypeParametersInReturnType2(): T expect fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box + +expect class Outer() { + class Nested() { + class Nested() + inner class Inner() + } + inner class Inner() { + inner class Inner() + } +} + +expect fun returnOuter(): Outer +expect fun returnOuterNested(): Outer.Nested +expect fun returnOuterNestedNested(): Outer.Nested.Nested +expect fun returnOuterInner(): Outer.Inner +expect fun returnOuterInnerInner(): Outer.Inner.Inner diff --git a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt index a637f15a8c0..caf75ba0f35 100644 --- a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt +++ b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt @@ -61,3 +61,19 @@ fun functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO() actual fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO() + +actual class Outer actual constructor() { + actual class Nested actual constructor() { + actual class Nested actual constructor() + actual inner class Inner actual constructor() + } + actual inner class Inner actual constructor() { + actual inner class Inner actual constructor() + } +} + +actual fun returnOuter(): Outer = TODO() +actual fun returnOuterNested(): Outer.Nested = TODO() +actual fun returnOuterNestedNested(): Outer.Nested.Nested = TODO() +actual fun returnOuterInner(): Outer.Inner = TODO() +actual fun returnOuterInnerInner(): Outer.Inner.Inner = TODO() diff --git a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt index f48c8e01d4f..23cc88db321 100644 --- a/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt +++ b/native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt @@ -61,3 +61,19 @@ fun functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO() actual fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO() + +actual class Outer actual constructor() { + actual class Nested actual constructor() { + actual class Nested actual constructor() + actual inner class Inner actual constructor() + } + actual inner class Inner actual constructor() { + actual inner class Inner actual constructor() + } +} + +actual fun returnOuter(): Outer = TODO() +actual fun returnOuterNested(): Outer.Nested = TODO() +actual fun returnOuterNestedNested(): Outer.Nested.Nested = TODO() +actual fun returnOuterInner(): Outer.Inner = TODO() +actual fun returnOuterInnerInner(): Outer.Inner.Inner = TODO() diff --git a/native/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt b/native/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt index 1d8883f6b4c..15237587e7f 100644 --- a/native/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt +++ b/native/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt @@ -64,3 +64,19 @@ fun functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO() + +class Outer { + class Nested { + class Nested + inner class Inner + } + inner class Inner { + inner class Inner + } +} + +fun returnOuter(): Outer = TODO() +fun returnOuterNested(): Outer.Nested = TODO() +fun returnOuterNestedNested(): Outer.Nested.Nested = TODO() +fun returnOuterInner(): Outer.Inner = TODO() +fun returnOuterInnerInner(): Outer.Inner.Inner = TODO() diff --git a/native/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt b/native/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt index 820bab8f1fb..8fa0b2b1f3b 100644 --- a/native/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt +++ b/native/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt @@ -64,3 +64,19 @@ fun functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO() + +class Outer { + class Nested { + class Nested + inner class Inner + } + inner class Inner { + inner class Inner + } +} + +fun returnOuter(): Outer = TODO() +fun returnOuterNested(): Outer.Nested = TODO() +fun returnOuterNestedNested(): Outer.Nested.Nested = TODO() +fun returnOuterInner(): Outer.Inner = TODO() +fun returnOuterInnerInner(): Outer.Inner.Inner = TODO() diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_kotlinx_cinterop.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_kotlinx_cinterop.kt index 97a70aad3af..cf366643a8f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_kotlinx_cinterop.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_kotlinx_cinterop.kt @@ -1,5 +1,12 @@ // this is to avoid missing Kotlin/Native stdlib package kotlinx.cinterop -// fake class with the default constructor and no member scope -public abstract class CStructVar() +// fake classes with the default constructor and no member scope +abstract class CStructVar +class CPointer +@Suppress("FINAL_UPPER_BOUND") class UByteVarOf +class UByte + +// fake typealiases +typealias CArrayPointer = CPointer +typealias UByteVar = UByteVarOf diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_root.kt index c953d2dfc19..c20bf9b7dee 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/common/package_root.kt @@ -42,3 +42,9 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS // Supertypes: expect class FILE : kotlinx.cinterop.CStructVar + +typealias uuid_t = kotlinx.cinterop.CPointer> +// ^^^ TODO: ideally, it should be CArrayPointer +typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer + +expect val uuid: uuid_t diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_kotlinx_cinterop.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_kotlinx_cinterop.kt index 97a70aad3af..cf366643a8f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_kotlinx_cinterop.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_kotlinx_cinterop.kt @@ -1,5 +1,12 @@ // this is to avoid missing Kotlin/Native stdlib package kotlinx.cinterop -// fake class with the default constructor and no member scope -public abstract class CStructVar() +// fake classes with the default constructor and no member scope +abstract class CStructVar +class CPointer +@Suppress("FINAL_UPPER_BOUND") class UByteVarOf +class UByte + +// fake typealiases +typealias CArrayPointer = CPointer +typealias UByteVar = UByteVarOf diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_root.kt index f4fafe51685..6e61a83b4a4 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/linux/package_root.kt @@ -20,3 +20,5 @@ typealias X = U? // different nullability of the RHS TA // Supertypes: actual typealias FILE = _IO_FILE final class _IO_FILE : kotlinx.cinterop.CStructVar {} + +actual val uuid: uuid_t get() = TODO() diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_kotlinx_cinterop.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_kotlinx_cinterop.kt index 97a70aad3af..cf366643a8f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_kotlinx_cinterop.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_kotlinx_cinterop.kt @@ -1,5 +1,12 @@ // this is to avoid missing Kotlin/Native stdlib package kotlinx.cinterop -// fake class with the default constructor and no member scope -public abstract class CStructVar() +// fake classes with the default constructor and no member scope +abstract class CStructVar +class CPointer +@Suppress("FINAL_UPPER_BOUND") class UByteVarOf +class UByte + +// fake typealiases +typealias CArrayPointer = CPointer +typealias UByteVar = UByteVarOf diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt index 7f7bd4eecc3..44df04fb334 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt @@ -21,6 +21,8 @@ typealias X = U // different nullability of the RHS TA actual typealias FILE = __sFILE final class __sFILE : kotlinx.cinterop.CStructVar {} +actual val uuid: uuid_t get() = TODO() + // Type alias chain that is present in one target only: class AA typealias BB = AA diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_kotlinx_cinterop.kt b/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_kotlinx_cinterop.kt index 97a70aad3af..cf366643a8f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_kotlinx_cinterop.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_kotlinx_cinterop.kt @@ -1,5 +1,12 @@ // this is to avoid missing Kotlin/Native stdlib package kotlinx.cinterop -// fake class with the default constructor and no member scope -public abstract class CStructVar() +// fake classes with the default constructor and no member scope +abstract class CStructVar +class CPointer +@Suppress("FINAL_UPPER_BOUND") class UByteVarOf +class UByte + +// fake typealiases +typealias CArrayPointer = CPointer +typealias UByteVar = UByteVarOf diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_root.kt index a5d30fd3aa1..da6e54591eb 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/original/linux/package_root.kt @@ -51,3 +51,8 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS // Supertypes: typealias FILE = _IO_FILE final class _IO_FILE : kotlinx.cinterop.CStructVar {} + +typealias uuid_t = __darwin_uuid_t +typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer + +val uuid: uuid_t get() = TODO() diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_kotlinx_cinterop.kt b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_kotlinx_cinterop.kt index 97a70aad3af..cf366643a8f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_kotlinx_cinterop.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_kotlinx_cinterop.kt @@ -1,5 +1,12 @@ // this is to avoid missing Kotlin/Native stdlib package kotlinx.cinterop -// fake class with the default constructor and no member scope -public abstract class CStructVar() +// fake classes with the default constructor and no member scope +abstract class CStructVar +class CPointer +@Suppress("FINAL_UPPER_BOUND") class UByteVarOf +class UByte + +// fake typealiases +typealias CArrayPointer = CPointer +typealias UByteVar = UByteVarOf diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt index 04963264a48..eccc25445c8 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt @@ -52,6 +52,11 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS typealias FILE = __sFILE final class __sFILE : kotlinx.cinterop.CStructVar {} +typealias uuid_t = __darwin_uuid_t +typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer + +val uuid: uuid_t get() = TODO() + // Type alias chain that is present in one target only: class AA typealias BB = AA diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt index 5e3cbd67590..26a7a0e365a 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType @@ -290,7 +290,7 @@ private fun mockAnnotation( constantValueArguments: Map> = emptyMap(), annotationValueArguments: Map = emptyMap() ): CirAnnotation = CirAnnotationFactory.create( - type = CirTypeFactory.create(mockClassType(fqName)) as CirSimpleType, + type = CirTypeFactory.create(mockClassType(fqName)) as CirClassType, constantValueArguments = constantValueArguments, annotationValueArguments = annotationValueArguments ) diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt index 40fd9e42177..fea71c5466c 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType 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.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildTypeAliasNode @@ -274,7 +275,7 @@ class TypeCommonizerTest : AbstractCommonizerTest() { @Test // why success: expect class/actual TAs fun taTypesInUserPackageWithDifferentClasses() = doTestSuccess( - expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") }, + expected = mockClassType("org.sample.FooAlias"), mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Bar") } ) @@ -444,7 +445,7 @@ class TypeCommonizerTest : AbstractCommonizerTest() { @Test // why success: nullability of underlying type does not matter if expect class/actual TAs created fun taTypesInUserPackageWithDifferentNullability3() = doTestSuccess( - expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }, + expected = mockClassType("org.sample.FooAlias"), mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) } ) @@ -452,7 +453,7 @@ class TypeCommonizerTest : AbstractCommonizerTest() { @Test // why success: nullability of underlying type does not matter if expect class/actual TAs created fun taTypesInUserPackageWithDifferentNullability4() = doTestSuccess( - expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }, + expected = mockClassType("org.sample.FooAlias"), mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) } ) @@ -520,5 +521,10 @@ class TypeCommonizerTest : AbstractCommonizerTest() { override fun createCommonizer() = TypeCommonizer(cache) - override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areTypesEqual(cache, a, b)) + override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areEqual(cache, a, b)) + + companion object { + fun areEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean = + TypeCommonizer(cache).run { commonizeWith(a) && commonizeWith(b) } + } } diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt index 71e08906c57..bedd1c0dabf 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual +import org.jetbrains.kotlin.descriptors.commonizer.core.TypeCommonizerTest.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType @@ -181,7 +182,7 @@ internal data class CirTestValueParameter( companion object { fun areEqual(cache: CirClassifiersCache, a: CirValueParameter, b: CirValueParameter): Boolean { if (a.name != b.name - || !areTypesEqual(cache, a.returnType, b.returnType) + || !areEqual(cache, a.returnType, b.returnType) || a.declaresDefaultValue != b.declaresDefaultValue || a.isCrossinline != b.isCrossinline || a.isNoinline != b.isNoinline @@ -194,7 +195,7 @@ internal data class CirTestValueParameter( return (aVarargElementType === bVarargElementType) || (aVarargElementType != null && bVarargElementType != null - && areTypesEqual(cache, aVarargElementType, bVarargElementType)) + && areEqual(cache, aVarargElementType, bVarargElementType)) } } } diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt index 82f84fb9aa0..ea06101a207 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType import kotlin.contracts.ExperimentalContracts import kotlin.reflect.KCallable import kotlin.test.fail @@ -479,17 +478,6 @@ internal class ComparingDeclarationsVisitor( context.assertEquals(!expectedAbbreviated.isNull(), !actualAbbreviated.isNull(), "type is abbreviated") if (expectedAbbreviated != null && actualAbbreviated != null) { - fun extractExpandedType(abbreviated: AbbreviatedType): SimpleType { // eliminate unnecessary repeated abbreviations - var expanded = abbreviated.expandedType - while (expanded is AbbreviatedType) { - if (expanded.abbreviation.declarationDescriptor !== abbreviated.abbreviation.declarationDescriptor) - break - else - expanded = expanded.expandedType - } - return expanded - } - visitType( expectedAbbreviated.abbreviation, actualAbbreviated.abbreviation,