diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt index 60ddd6222eb..6f0b6495bec 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt @@ -14,8 +14,10 @@ import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.FqName @@ -28,6 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.supertypes +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal val interopPackageName = InteropFqNames.packageName internal val objCObjectFqName = interopPackageName.child(Name.identifier("ObjCObject")) @@ -40,17 +43,20 @@ private val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFa private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames") fun ClassDescriptor.isObjCClass(): Boolean = - this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } && // TODO: this is not cheap. Cache me! - this.containingDeclaration.fqNameSafe != interopPackageName + this.containingDeclaration.fqNameSafe != interopPackageName && + this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } // TODO: this is not cheap. Cache me! fun KotlinType.isObjCObjectType(): Boolean = (this.supertypes() + this).any { TypeUtils.getClassDescriptor(it)?.fqNameSafe == objCObjectFqName } -private fun IrClass.getAllSuperClassifiers(): List = - listOf(this) + this.superTypes.flatMap { (it.classifierOrFail.owner as IrClass).getAllSuperClassifiers() } +private fun IrClass.selfOrAnySuperClass(pred: (IrClass) -> Boolean): Boolean { + if (pred(this)) return true -internal fun IrClass.isObjCClass() = this.getAllSuperClassifiers().any { it.fqNameForIrSerialization == objCObjectFqName } && - this.parent.fqNameForIrSerialization != interopPackageName + return superTypes.any { it.classOrNull!!.owner.selfOrAnySuperClass(pred) } +} + +internal fun IrClass.isObjCClass() = this.parent.fqNameForIrSerialization != interopPackageName && + selfOrAnySuperClass { it.fqNameForIrSerialization == objCObjectFqName } fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() && this.parentsWithSelf.filterIsInstance().any { @@ -68,7 +74,7 @@ fun ClassDescriptor.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().a it.fqNameSafe == objCClassFqName } -fun IrClass.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().any { +fun IrClass.isObjCMetaClass(): Boolean = selfOrAnySuperClass { it.fqNameForIrSerialization == objCClassFqName } @@ -142,7 +148,7 @@ private fun FunctionDescriptor.getObjCMethodInfo(onlyExternal: Boolean): ObjCMet } } - return this.overriddenDescriptors.asSequence().mapNotNull { it.getObjCMethodInfo(onlyExternal) }.firstOrNull() + return overriddenDescriptors.firstNotNullResult { it.getObjCMethodInfo(onlyExternal) } } /** @@ -157,7 +163,7 @@ private fun IrSimpleFunction.getObjCMethodInfo(onlyExternal: Boolean): ObjCMetho } } - return this.overriddenSymbols.mapNotNull { it.owner.getObjCMethodInfo(onlyExternal) }.firstOrNull() + return overriddenSymbols.firstNotNullResult { it.owner.getObjCMethodInfo(onlyExternal) } } fun FunctionDescriptor.getExternalObjCMethodInfo(): ObjCMethodInfo? = this.getObjCMethodInfo(onlyExternal = true) @@ -268,9 +274,16 @@ fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? { fun ConstructorDescriptor.getObjCInitMethod(): FunctionDescriptor? { return this.annotations.findAnnotation(objCConstructorFqName)?.let { val initSelector = it.getAnnotationStringValue("initSelector") - this.constructedClass.unsubstitutedMemberScope.getContributedDescriptors().asSequence() - .filterIsInstance() - .single { it.getExternalObjCMethodInfo()?.selector == initSelector } + val memberScope = constructedClass.unsubstitutedMemberScope + val functionNames = memberScope.getFunctionNames() + for (name in functionNames) { + val functions = memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + for (function in functions) { + val objectInfo = function.getExternalObjCMethodInfo() ?: continue + if (objectInfo.selector == initSelector) return function + } + } + error("Cannot find ObjInitMethod for $this") } }