From de0b6e06cf2531e0656ec19177d3b54f304628f3 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Thu, 13 Aug 2020 11:53:51 +0700 Subject: [PATCH] [Commonizer] Keep parameters names hash in approximation keys for ObjC callables ^KT-34602 --- .../mergedtree/approximationKeys.kt | 30 +++++++++++++------ .../descriptors/commonizer/utils/fqName.kt | 9 ++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt index 69073237d41..e642dcfa562 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt @@ -5,16 +5,12 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature import org.jetbrains.kotlin.descriptors.commonizer.core.Commonizer +import org.jetbrains.kotlin.descriptors.commonizer.utils.* import org.jetbrains.kotlin.descriptors.commonizer.utils.intern import org.jetbrains.kotlin.descriptors.commonizer.utils.signature -import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode -import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.name.Name /** Used for approximation of [PropertyDescriptor]s before running concrete [Commonizer]s */ @@ -32,11 +28,13 @@ data class PropertyApproximationKey( class FunctionApproximationKey( private val name: Name, private val valueParametersTypes: Array, + private val additionalValueParametersNamesHash: Int, private val extensionReceiverParameterType: CirTypeSignature? ) { constructor(function: SimpleFunctionDescriptor) : this( function.name.intern(), function.valueParameters.toTypeSignatures(), + additionalValueParameterNamesHash(function), function.extensionReceiverParameter?.type?.signature ) @@ -45,6 +43,7 @@ class FunctionApproximationKey( return false return name == other.name + && additionalValueParametersNamesHash == other.additionalValueParametersNamesHash && valueParametersTypes.contentEquals(other.valueParametersTypes) && extensionReceiverParameterType == other.extensionReceiverParameterType } @@ -52,26 +51,39 @@ class FunctionApproximationKey( override fun hashCode() = hashCode(name) .appendHashCode(valueParametersTypes) .appendHashCode(extensionReceiverParameterType) + .appendHashCode(additionalValueParametersNamesHash) } /** Used for approximation of [ConstructorDescriptor]s before running concrete [Commonizer]s */ class ConstructorApproximationKey( - private val valueParametersTypes: Array + private val valueParametersTypes: Array, + private val additionalValueParametersNamesHash: Int ) { constructor(constructor: ConstructorDescriptor) : this( - constructor.valueParameters.toTypeSignatures() + constructor.valueParameters.toTypeSignatures(), + additionalValueParameterNamesHash(constructor) ) override fun equals(other: Any?): Boolean { if (other !is ConstructorApproximationKey) return false - return valueParametersTypes.contentEquals(other.valueParametersTypes) + return additionalValueParametersNamesHash == other.additionalValueParametersNamesHash + && valueParametersTypes.contentEquals(other.valueParametersTypes) } override fun hashCode() = hashCode(valueParametersTypes) + .appendHashCode(additionalValueParametersNamesHash) } @Suppress("NOTHING_TO_INLINE") private inline fun List.toTypeSignatures(): Array = Array(size) { index -> this[index].type.signature } + +private fun additionalValueParameterNamesHash(callable: FunctionDescriptor): Int { + // TODO: add more precise checks when more languages than C & ObjC are supported + if (callable.annotations.none { it.isObjCInteropCallableAnnotation }) + return 0 // do not calculate hash for non-ObjC callables + + return callable.valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name) } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt index fbfce5b9216..6d21bb5ba19 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames @@ -58,3 +60,10 @@ private fun String.hasPrefix(prefix: String): Boolean { internal val ClassId.isObjCInteropCallableAnnotation: Boolean get() = packageFqName.asString() == CINTEROP_PACKAGE && relativeClassName.asString() in OBJC_INTEROP_CALLABLE_ANNOTATIONS + +internal val AnnotationDescriptor.isObjCInteropCallableAnnotation: Boolean + get() { + val classifier = type.declarationDescriptor + return classifier.name.asString() in OBJC_INTEROP_CALLABLE_ANNOTATIONS + && (classifier.containingDeclaration as? PackageFragmentDescriptor)?.fqName?.asString() == CINTEROP_PACKAGE + }