diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt index 6e50a0c63e4..22ab97598ce 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt @@ -15,6 +15,8 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommo import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer +import org.jetbrains.kotlin.commonizer.transformer.ReApproximationCirNodeTransformer +import org.jetbrains.kotlin.commonizer.transformer.ReApproximationCirNodeTransformer.SignatureBuildingContextProvider import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer import org.jetbrains.kotlin.commonizer.tree.mergeCirTree @@ -63,6 +65,19 @@ internal fun commonizeTarget( InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree) + /* + ReApproximationCirNodeTransformer( + parameters.storageManager, classifiers, + SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = false) + ).invoke(mergedTree) + + */ + + ReApproximationCirNodeTransformer( + parameters.storageManager, classifiers, + SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = true) + ).invoke(mergedTree) + mergedTree.accept(CommonizationVisitor(mergedTree), Unit) return mergedTree diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSignature.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSignature.kt new file mode 100644 index 00000000000..747a8775a83 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSignature.kt @@ -0,0 +1,213 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.commonizer.mergedtree + +import gnu.trove.TIntHashSet +import org.jetbrains.kotlin.commonizer.cir.* +import org.jetbrains.kotlin.commonizer.utils.Interner +import org.jetbrains.kotlin.types.Variance + +class CirTypeSignature { + private val elements = ArrayList() + + private var hashCode = 0 + + fun add(element: Any) { + elements.add(element) + hashCode = 31 * hashCode + element.hashCode() + } + + override fun hashCode(): Int = hashCode + + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is CirTypeSignature) return false + if (other.hashCode != this.hashCode) return false + if (other.elements != this.elements) return false + return true + } + + override fun toString(): String { + return elements.joinToString("") + } + + companion object { + val interner = Interner() + } +} + +internal fun SignatureBuildingContext( + memberContext: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters, + classifierSignatureBuildingContext: ClassifierSignatureBuildingContext = ClassifierSignatureBuildingContext.Default, + argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext = ArgumentsSignatureBuildingContext.Default, +): SignatureBuildingContext { + return DefaultSignatureBuildingContext( + memberContext, classifierSignatureBuildingContext, argumentsSignatureBuildingContext, functionOrPropertyOrConstructor + ) +} + +internal sealed interface SignatureBuildingContext { + val memberContext: CirMemberContext + val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext + val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext +} + +internal sealed interface ClassifierSignatureBuildingContext { + fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId) + + object Default : ClassifierSignatureBuildingContext { + override fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId) = signature.add(classifierId) + } + + class TypeAliasInvariant(private val commonIdResolver: CirCommonClassifierIdResolver) : ClassifierSignatureBuildingContext { + override fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId) { + return signature.add(commonIdResolver.findCommonId(classifierId) ?: classifierId) + } + } +} + +internal sealed interface ArgumentsSignatureBuildingContext { + fun appendSignature(signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List) + + object Default : ArgumentsSignatureBuildingContext { + override fun appendSignature(signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List) { + if (arguments.isEmpty()) return + signature.add(TypeSignatureElements.ArgumentsStartToken) + arguments.forEachIndexed { index, argument -> + when (argument) { + is CirRegularTypeProjection -> { + when (argument.projectionKind) { + Variance.INVARIANT -> Unit + Variance.IN_VARIANCE -> signature.add(TypeSignatureElements.InVariance) + Variance.OUT_VARIANCE -> signature.add(TypeSignatureElements.OutVariance) + } + signature.appendTypeApproximationSignature(context, argument.type) + } + is CirStarTypeProjection -> signature.add(TypeSignatureElements.StarProjection) + } + if (index != arguments.lastIndex) { + signature.add(TypeSignatureElements.ArgumentsSeparator) + } + } + signature.add(TypeSignatureElements.ArgumentsEndToken) + } + } + + /** + * Won't render any type arguments + */ + object Skip : ArgumentsSignatureBuildingContext { + override fun appendSignature( + signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List + ) = Unit + } +} + + +private enum class TypeSignatureElements(val stringRepresentation: String) { + ArgumentsStartToken("<"), + ArgumentsEndToken(">"), + ArgumentsSeparator(", "), + NullableToken("?"), + UpperBoundsStartToken(" : ["), + UpperBoundsEndToken("]"), + InVariance("in "), + OutVariance("out "), + StarProjection("*"), + FlexibleTypeSeparator(".."); + + override fun toString(): String { + return stringRepresentation + } +} + + +internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature { + val signature = CirTypeSignature() + signature.appendTypeApproximationSignature(context, type) + return CirTypeSignature.interner.intern(signature) +} + +internal fun CirTypeSignature.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) { + return when (type) { + is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type) + is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type) + is CirClassOrTypeAliasType -> appendClassOrTypeAliasTypeApproximationSignature(context, type) + } +} + +internal fun CirTypeSignature.appendClassOrTypeAliasTypeApproximationSignature( + context: SignatureBuildingContext, type: CirClassOrTypeAliasType +) { + context.classifierSignatureBuildingContext.appendSignature(this, type.classifierId) + context.argumentsSignatureBuildingContext.appendSignature(this, context, type.arguments) + if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken) +} + +private fun CirTypeSignature.appendTypeParameterTypeApproximationSignature( + context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType +) { + val typeParameter = context.resolveTypeParameter(type.index) + add(typeParameter.name) + if (context.isVisitedFirstTime(type.index)) { + add(TypeSignatureElements.UpperBoundsStartToken) + typeParameter.upperBounds.forEachIndexed { index, upperBound -> + appendTypeApproximationSignature(context, upperBound) + if (index != typeParameter.upperBounds.lastIndex) add(TypeSignatureElements.ArgumentsSeparator) + } + add(TypeSignatureElements.UpperBoundsEndToken) + } + if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken) +} + +private fun CirTypeSignature.appendFlexibleTypeApproximationSignature( + context: SignatureBuildingContext, type: CirFlexibleType +) { + appendTypeApproximationSignature(context, type.lowerBound) + add(TypeSignatureElements.FlexibleTypeSeparator) + appendTypeApproximationSignature(context, type.upperBound) +} + +private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) { + is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext( + memberContext, classifierSignatureBuildingContext, argumentsSignatureBuildingContext, functionOrPropertyOrConstructor + ) + is TypeParameterTypeSignatureBuildingContext -> this +} + +private class DefaultSignatureBuildingContext( + override val memberContext: CirMemberContext, + override val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext, + override val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext, + val functionOrPropertyOrConstructor: CirHasTypeParameters +) : SignatureBuildingContext + +private class TypeParameterTypeSignatureBuildingContext( + override val memberContext: CirMemberContext, + override val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext, + override val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext, + private val functionOrPropertyOrConstructor: CirHasTypeParameters +) : SignatureBuildingContext { + + private val alreadyVisitedParameterTypeIndices = TIntHashSet() + + fun isVisitedFirstTime(typeParameterIndex: Int): Boolean { + return alreadyVisitedParameterTypeIndices.add(typeParameterIndex) + } + + fun resolveTypeParameter(index: Int): CirTypeParameter { + var indexOffset = 0 + memberContext.classes.forEach { clazz -> + val indexInClass = index - indexOffset + if (indexInClass >= 0 && indexInClass <= clazz.typeParameters.lastIndex) { + return clazz.typeParameters[indexInClass] + } + indexOffset += clazz.typeParameters.size + } + + return functionOrPropertyOrConstructor.typeParameters[index - indexOffset] + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSubstitutor.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSubstitutor.kt deleted file mode 100644 index 4ad2f66a45b..00000000000 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeSubstitutor.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.commonizer.mergedtree - -import org.jetbrains.kotlin.commonizer.cir.CirFunction -import org.jetbrains.kotlin.commonizer.cir.CirProperty -import org.jetbrains.kotlin.commonizer.cir.CirType -import org.jetbrains.kotlin.commonizer.cir.CirValueParameter.Companion.copyInterned - -interface CirTypeSubstitutor { - fun substitute(targetIndex: Int, type: CirType): CirType -} - -fun CirTypeSubstitutor.substitute(index: Int, property: CirProperty): CirProperty { - val newReturnType = substitute(index, property.returnType) - return if (newReturnType != property.returnType) property.copy(returnType = newReturnType) else property -} - -fun CirTypeSubstitutor.substitute(index: Int, function: CirFunction): CirFunction { - val newExtensionReceiverType = function.extensionReceiver?.type?.let { substitute(index, it) } - - val newExtensionReceiver = if (newExtensionReceiverType != function.extensionReceiver?.type) - function.extensionReceiver?.copy(type = checkNotNull(newExtensionReceiverType)) - else function.extensionReceiver - - val newValueParameters = function.valueParameters.map { valueParameter -> - val newReturnType = substitute(index, valueParameter.returnType) - if (newReturnType != valueParameter.returnType) valueParameter.copyInterned(returnType = newReturnType) else valueParameter - } - - val newReturnType = substitute(index, function.returnType) - - return if ( - newExtensionReceiver != function.extensionReceiver || - newValueParameters != function.valueParameters || - newReturnType != function.returnType - ) function.copy( - extensionReceiver = newExtensionReceiver, - valueParameters = newValueParameters, - returnType = newReturnType - ) else function -} \ No newline at end of file diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/approximationKeys.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/approximationKeys.kt index 40a1f6e0127..cb063207499 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/approximationKeys.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/approximationKeys.kt @@ -7,38 +7,11 @@ package org.jetbrains.kotlin.commonizer.mergedtree -import gnu.trove.TIntHashSet import org.jetbrains.kotlin.commonizer.cir.* -import org.jetbrains.kotlin.commonizer.utils.Interner import org.jetbrains.kotlin.commonizer.utils.appendHashCode import org.jetbrains.kotlin.commonizer.utils.hashCode import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation -import org.jetbrains.kotlin.types.Variance -class CirTypeSignature { - private val elements = ArrayList() - - private var hashCode = 0 - - fun add(element: Any) { - elements.add(element) - hashCode = 31 * hashCode + element.hashCode() - } - - override fun hashCode(): Int = hashCode - - override fun equals(other: Any?): Boolean { - if (other === this) return true - if (other !is CirTypeSignature) return false - if (other.hashCode != this.hashCode) return false - if (other.elements != this.elements) return false - return true - } - - override fun toString(): String { - return elements.joinToString("") - } -} typealias ObjCFunctionApproximation = Int @@ -48,14 +21,13 @@ data class PropertyApproximationKey( ) { companion object { internal fun create( - context: CirMemberContext, - commonClassifierIdResolver: CirCommonClassifierIdResolver, - property: CirProperty + property: CirProperty, + signatureBuildingContext: SignatureBuildingContext ): PropertyApproximationKey { return PropertyApproximationKey( name = property.name, extensionReceiverParameterType = property.extensionReceiver?.let { - buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, property), it.type) + buildApproximationSignature(signatureBuildingContext, it.type) } ) } @@ -71,15 +43,14 @@ data class FunctionApproximationKey( companion object { internal fun create( - context: CirMemberContext, - commonClassifierIdResolver: CirCommonClassifierIdResolver, - function: CirFunction + function: CirFunction, + signatureBuildingContext: SignatureBuildingContext ): FunctionApproximationKey { return FunctionApproximationKey( name = function.name, - valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, function), + valueParametersTypes = valueParameterTypes(function, signatureBuildingContext), extensionReceiverParameterType = function.extensionReceiver?.let { - buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, function), it.type) + buildApproximationSignature(signatureBuildingContext, it.type) }, objCFunctionApproximation = objCFunctionApproximation(function) ) @@ -102,7 +73,6 @@ data class FunctionApproximationKey( .appendHashCode(objCFunctionApproximation) } -private val typeSignatureInterner = Interner() data class ConstructorApproximationKey( val valueParametersTypes: Array, @@ -111,10 +81,10 @@ data class ConstructorApproximationKey( companion object { internal fun create( - context: CirMemberContext, commonClassifierIdResolver: CirCommonClassifierIdResolver, constructor: CirClassConstructor + constructor: CirClassConstructor, signatureBuildingContext: SignatureBuildingContext ): ConstructorApproximationKey { return ConstructorApproximationKey( - valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, constructor), + valueParametersTypes = valueParameterTypes(constructor, signatureBuildingContext), objCFunctionApproximation = objCFunctionApproximation(constructor) ) } @@ -140,150 +110,13 @@ private fun objCFunctionApproximation(value: T): ObjCFunctionApproximation } private fun valueParameterTypes( - context: CirMemberContext, - commonClassifierIdResolver: CirCommonClassifierIdResolver, - callable: T + callable: T, + signatureBuildingContext: SignatureBuildingContext, ): Array where T : CirHasTypeParameters, T : CirCallableMemberWithParameters, T : CirMaybeCallableMemberOfClass { if (callable.valueParameters.isEmpty()) return emptyArray() return Array(callable.valueParameters.size) { index -> val parameter = callable.valueParameters[index] - buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, callable), parameter.returnType) - } -} - -private enum class TypeSignatureElements(val stringRepresentation: String) { - ArgumentsStartToken("<"), - ArgumentsEndToken(">"), - ArgumentsSeparator(", "), - NullableToken("?"), - UpperBoundsStartToken(" : ["), - UpperBoundsEndToken("]"), - InVariance("in "), - OutVariance("out "), - StarProjection("*"), - FlexibleTypeSeparator(".."); - - override fun toString(): String { - return stringRepresentation - } -} - - -internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature { - val signature = CirTypeSignature() - signature.appendTypeApproximationSignature(context, type) - return typeSignatureInterner.intern(signature) -} - -internal fun CirTypeSignature.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) { - return when (type) { - is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type) - is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type) - is CirClassOrTypeAliasType -> appendClassOrTypeAliasTypeApproximationSignature(context, type) - } -} - -internal fun CirTypeSignature.appendClassOrTypeAliasTypeApproximationSignature( - context: SignatureBuildingContext, type: CirClassOrTypeAliasType -) { - add(context.commonClassifierIdResolver.findCommonId(type.classifierId) ?: type.classifierId) - if (type.arguments.isNotEmpty()) { - add(TypeSignatureElements.ArgumentsStartToken) - type.arguments.forEachIndexed { index, argument -> - when (argument) { - is CirRegularTypeProjection -> { - when (argument.projectionKind) { - Variance.INVARIANT -> Unit - Variance.IN_VARIANCE -> add(TypeSignatureElements.InVariance) - Variance.OUT_VARIANCE -> add(TypeSignatureElements.OutVariance) - } - appendTypeApproximationSignature(context, argument.type) - } - is CirStarTypeProjection -> add(TypeSignatureElements.StarProjection) - } - if (index != type.arguments.lastIndex) { - add(TypeSignatureElements.ArgumentsSeparator) - } - } - add(TypeSignatureElements.ArgumentsEndToken) - } - if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken) -} - -private fun CirTypeSignature.appendTypeParameterTypeApproximationSignature( - context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType -) { - val typeParameter = context.resolveTypeParameter(type.index) - add(typeParameter.name) - if (context.isVisitedFirstTime(type.index)) { - add(TypeSignatureElements.UpperBoundsStartToken) - typeParameter.upperBounds.forEachIndexed { index, upperBound -> - appendTypeApproximationSignature(context, upperBound) - if (index != typeParameter.upperBounds.lastIndex) add(TypeSignatureElements.ArgumentsSeparator) - } - add(TypeSignatureElements.UpperBoundsEndToken) - } - if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken) -} - -private fun CirTypeSignature.appendFlexibleTypeApproximationSignature( - context: SignatureBuildingContext, type: CirFlexibleType -) { - appendTypeApproximationSignature(context, type.lowerBound) - add(TypeSignatureElements.FlexibleTypeSeparator) - appendTypeApproximationSignature(context, type.upperBound) -} - -internal sealed interface SignatureBuildingContext { - val commonClassifierIdResolver: CirCommonClassifierIdResolver - - companion object { - fun create( - memberContext: CirMemberContext, - commonClassifierIdResolver: CirCommonClassifierIdResolver, - functionOrPropertyOrConstructor: CirHasTypeParameters - ): SignatureBuildingContext { - return DefaultSignatureBuildingContext(memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor) - } - } -} - -private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) { - is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext( - memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor - ) - is TypeParameterTypeSignatureBuildingContext -> this -} - -private class DefaultSignatureBuildingContext( - val memberContext: CirMemberContext, - override val commonClassifierIdResolver: CirCommonClassifierIdResolver, - val functionOrPropertyOrConstructor: CirHasTypeParameters -) : SignatureBuildingContext - -private class TypeParameterTypeSignatureBuildingContext( - private val memberContext: CirMemberContext, - override val commonClassifierIdResolver: CirCommonClassifierIdResolver, - private val functionOrPropertyOrConstructor: CirHasTypeParameters -) : SignatureBuildingContext { - - private val alreadyVisitedParameterTypeIndices = TIntHashSet() - - fun isVisitedFirstTime(typeParameterIndex: Int): Boolean { - return alreadyVisitedParameterTypeIndices.add(typeParameterIndex) - } - - fun resolveTypeParameter(index: Int): CirTypeParameter { - var indexOffset = 0 - memberContext.classes.forEach { clazz -> - val indexInClass = index - indexOffset - if (indexInClass >= 0 && indexInClass <= clazz.typeParameters.lastIndex) { - return clazz.typeParameters[indexInClass] - } - indexOffset += clazz.typeParameters.size - } - - return functionOrPropertyOrConstructor.typeParameters[index - indexOffset] + buildApproximationSignature(signatureBuildingContext, parameter.returnType) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/transformer/ReApproximationCirNodeTransformer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/transformer/ReApproximationCirNodeTransformer.kt new file mode 100644 index 00000000000..70bb40bee38 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/transformer/ReApproximationCirNodeTransformer.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.commonizer.transformer + +import org.jetbrains.kotlin.commonizer.cir.CirHasTypeParameters +import org.jetbrains.kotlin.commonizer.mergedtree.* +import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode +import org.jetbrains.kotlin.commonizer.mergedtree.ClassifierSignatureBuildingContext.TypeAliasInvariant +import org.jetbrains.kotlin.commonizer.utils.fastForEach +import org.jetbrains.kotlin.storage.StorageManager + +internal class ReApproximationCirNodeTransformer( + private val storageManager: StorageManager, + private val classifiers: CirKnownClassifiers, + private val signatureBuildingContextProvider: SignatureBuildingContextProvider +) : CirNodeTransformer { + + internal class SignatureBuildingContextProvider( + private val classifiers: CirKnownClassifiers, + private val typeAliasInvariant: Boolean, + private val skipArguments: Boolean + ) { + operator fun invoke(member: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters): SignatureBuildingContext { + return SignatureBuildingContext( + memberContext = member, functionOrPropertyOrConstructor = functionOrPropertyOrConstructor, + classifierSignatureBuildingContext = if (typeAliasInvariant) TypeAliasInvariant(classifiers.commonClassifierIdResolver) + else ClassifierSignatureBuildingContext.Default, + argumentsSignatureBuildingContext = if (skipArguments) ArgumentsSignatureBuildingContext.Skip + else ArgumentsSignatureBuildingContext.Default + ) + } + } + + override fun invoke(root: CirRootNode) { + for (index in 0 until root.targetDeclarations.size) { + root.modules.forEach { (_, module) -> this(module, index) } + } + } + + private operator fun invoke(module: CirModuleNode, index: Int) { + module.packages.forEach { (_, pkg) -> this(pkg, index) } + } + + private operator fun invoke(pkg: CirPackageNode, index: Int) { + pkg.functions.values.toTypedArray().fastForEach { function -> this(pkg, function, index, CirMemberContext.empty) } + pkg.properties.values.toTypedArray().fastForEach { property -> this(pkg, property, index, CirMemberContext.empty) } + pkg.classes.values.toTypedArray().fastForEach { clazz -> this(clazz, index, CirMemberContext.empty) } + } + + private operator fun invoke(clazz: CirClassNode, index: Int, context: CirMemberContext) { + val contextWithClass = context.withContextOf(clazz.targetDeclarations[index] ?: return) + clazz.functions.values.toTypedArray().fastForEach { function -> this(clazz, function, index, contextWithClass) } + clazz.properties.values.toTypedArray().fastForEach { property -> this(clazz, property, index, contextWithClass) } + clazz.constructors.values.toTypedArray().fastForEach { constructor -> this(clazz, constructor, index, contextWithClass) } + clazz.classes.values.toTypedArray().fastForEach { innerClass -> this(innerClass, index, contextWithClass) } + } + + private operator fun invoke(parent: CirNodeWithMembers<*, *>, function: CirFunctionNode, index: Int, context: CirMemberContext) { + /* Only perform re-approximation to nodes that are not 'complete' */ + if (function.targetDeclarations.none { it == null }) return + val functionAtIndex = function.targetDeclarations[index] ?: return + + val approximationKey = FunctionApproximationKey.create(functionAtIndex, signatureBuildingContextProvider(context, functionAtIndex)) + val newNode = parent.functions.getOrPut(approximationKey) { + buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent)) + } + + newNode.targetDeclarations.setIfAbsent(index, functionAtIndex) + } + + private operator fun invoke(parent: CirNodeWithMembers<*, *>, property: CirPropertyNode, index: Int, context: CirMemberContext) { + /* Only perform re-approximation to nodes that are not 'complete' */ + if (property.targetDeclarations.none { it == null }) return + val propertyAtIndex = property.targetDeclarations[index] ?: return + + val approximationKey = PropertyApproximationKey.create(propertyAtIndex, signatureBuildingContextProvider(context, propertyAtIndex)) + val newNode = parent.properties.getOrPut(approximationKey) { + buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent)) + } + + newNode.targetDeclarations.setIfAbsent(index, propertyAtIndex) + } + + private operator fun invoke( + parent: CirClassNode, constructor: CirClassConstructorNode, index: Int, context: CirMemberContext + ) { + /* Only perform re-approximation to nodes that are not 'complete' */ + if (constructor.targetDeclarations.none { it == null }) return + val constructorAtIndex = constructor.targetDeclarations[index] ?: return + + val approximationKey = + ConstructorApproximationKey.create(constructorAtIndex, signatureBuildingContextProvider(context, constructorAtIndex)) + + val newNode = parent.constructors.getOrPut(approximationKey) { + buildClassConstructorNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent)) + } + + newNode.targetDeclarations.setIfAbsent(index, constructorAtIndex) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/mergeCirTree.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/mergeCirTree.kt index 006a003d28d..474b1367f12 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/mergeCirTree.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/mergeCirTree.kt @@ -82,33 +82,36 @@ internal fun CirNodeWithMembers<*, *>.buildFunction( context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null ) { val functionNode = functions.getOrPut( - FunctionApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, function) + FunctionApproximationKey.create(function, SignatureBuildingContext(context.memberContext, function)) ) { buildFunctionNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) } - functionNode.targetDeclarations[context.targetIndex] = function + /* Multiple type substitutions could in result in the same commonization result */ + functionNode.targetDeclarations.setIfAbsent(context.targetIndex, function) } internal fun CirNodeWithMembers<*, *>.buildProperty( context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null ) { val propertyNode = properties.getOrPut( - PropertyApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, property) + PropertyApproximationKey.create(property, SignatureBuildingContext(context.memberContext, property)) ) { buildPropertyNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) } - propertyNode.targetDeclarations[context.targetIndex] = property + /* Multiple type substitutions could in result in the same commonization result */ + propertyNode.targetDeclarations.setIfAbsent(context.targetIndex, property) } internal fun CirClassNode.buildConstructor( context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *> ) { val constructorNode = constructors.getOrPut( - ConstructorApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, constructor) + ConstructorApproximationKey.create(constructor, SignatureBuildingContext(context.memberContext, constructor)) ) { buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) } - constructorNode.targetDeclarations[context.targetIndex] = constructor + /* Multiple type substitutions could in result in the same commonization result */ + constructorNode.targetDeclarations.setIfAbsent(context.targetIndex, constructor) } internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/commonizedGroup.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/commonizedGroup.kt index 1bb612d8129..8e397e16e05 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/commonizedGroup.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/utils/commonizedGroup.kt @@ -32,8 +32,7 @@ class CommonizedGroup( elements[index] = value } - internal fun setAllowingOverride(index: Int, value: T?) { - elements[index] = value + fun setIfAbsent(index: Int, value: T?) { + if (this[index] == null) set(index, value) } } - diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeCommonizerTest.kt index e5e74bb9eb6..8681797a767 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/core/TypeCommonizerTest.kt @@ -371,7 +371,7 @@ class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() { } ) assertEquals( - mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, commonizer( + mockClassType("kotlin/sequences/SequenceScope"), commonizer( listOf( mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/ParameterizedTypesCommonizationTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/ParameterizedTypesCommonizationTest.kt index 05210cbcfa6..9c6f11d345c 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/ParameterizedTypesCommonizationTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/ParameterizedTypesCommonizationTest.kt @@ -110,11 +110,7 @@ class ParameterizedTypesCommonizationTest : AbstractInlineSourcesCommonizationTe typealias TA2 = TA1 typealias TA3 = TA2 - /* - Desirable solution below! - Test ensures that no wrong commonization is emitted for now. - */ - //expect fun x1(x: TA1) + expect fun x1(x: TA1) """.trimIndent() ) }