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,