diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt index 9d0ea0a21b2..e5f0b619786 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt @@ -31,6 +31,8 @@ object BinaryOptions : BinaryOptionRegistry() { val objcExportDisableSwiftMemberNameMangling by booleanOption() + val objcExportIgnoreInterfaceMethodCollisions by booleanOption() + val gcSchedulerType by option() val gcMarkSingleThreaded by booleanOption() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt index a4e3f9783b8..a39ec71f406 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt @@ -45,6 +45,9 @@ internal fun StorageComponentContainer.initContainer(config: KonanConfig) { override val unitSuspendFunctionExport: UnitSuspendFunctionObjCExport get() = config.unitSuspendFunctionObjCExport + + override val ignoreInterfaceMethodCollisions: Boolean + get() = config.configuration.getBoolean(BinaryOptions.objcExportIgnoreInterfaceMethodCollisions) }) } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index 3b07a39871d..296c2a7b3d6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -49,6 +49,7 @@ internal fun produceObjCExportInterface( val moduleDescriptors = listOf(moduleDescriptor) + moduleDescriptor.getExportedDependencies(config) val objcGenerics = config.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS) val disableSwiftMemberNameMangling = config.configuration.getBoolean(BinaryOptions.objcExportDisableSwiftMemberNameMangling) + val ignoreInterfaceMethodCollisions = config.configuration.getBoolean(BinaryOptions.objcExportIgnoreInterfaceMethodCollisions) val namer = ObjCExportNamerImpl( moduleDescriptors.toSet(), moduleDescriptor.builtIns, @@ -57,6 +58,7 @@ internal fun produceObjCExportInterface( local = false, objcGenerics = objcGenerics, disableSwiftMemberNameMangling = disableSwiftMemberNameMangling, + ignoreInterfaceMethodCollisions = ignoreInterfaceMethodCollisions, ) val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer, objcGenerics) headerGenerator.translateModule() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt index 1c48dab1dd3..52148b2621a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt @@ -49,6 +49,8 @@ interface ObjCExportLazy { get() = false val unitSuspendFunctionExport: UnitSuspendFunctionObjCExport + val ignoreInterfaceMethodCollisions: Boolean + get() = false } fun generateBase(): List> @@ -452,6 +454,8 @@ internal fun createNamerConfiguration(configuration: ObjCExportLazy.Configuratio override val objcGenerics = configuration.objcGenerics override val disableSwiftMemberNameMangling = configuration.disableSwiftMemberNameMangling + + override val ignoreInterfaceMethodCollisions: Boolean = configuration.ignoreInterfaceMethodCollisions } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt index e62699c59bf..8e3d90b37b1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt @@ -57,6 +57,8 @@ interface ObjCExportNamer { val disableSwiftMemberNameMangling: Boolean get() = false + val ignoreInterfaceMethodCollisions: Boolean + get() = false } val topLevelNamePrefix: String @@ -283,6 +285,7 @@ internal class ObjCExportNamerImpl( local: Boolean, objcGenerics: Boolean = false, disableSwiftMemberNameMangling: Boolean = false, + ignoreInterfaceMethodCollisions: Boolean = false, ) : this( object : ObjCExportNamer.Configuration { override val topLevelNamePrefix: String @@ -297,6 +300,8 @@ internal class ObjCExportNamerImpl( override val disableSwiftMemberNameMangling: Boolean get() = disableSwiftMemberNameMangling + override val ignoreInterfaceMethodCollisions: Boolean + get() = ignoreInterfaceMethodCollisions }, builtIns, mapper, @@ -335,13 +340,13 @@ internal class ObjCExportNamerImpl( override fun reserved(name: String) = name in reserved override fun conflict(first: FunctionDescriptor, second: FunctionDescriptor): Boolean = - !mapper.canHaveSameSelector(first, second) + !mapper.canHaveSameSelector(first, second, configuration.ignoreInterfaceMethodCollisions) } private val methodSwiftNames = object : Mapping() { override fun conflict(first: FunctionDescriptor, second: FunctionDescriptor): Boolean { if (configuration.disableSwiftMemberNameMangling) return false // Ignore all conflicts. - return !mapper.canHaveSameSelector(first, second) + return !mapper.canHaveSameSelector(first, second, configuration.ignoreInterfaceMethodCollisions) } // Note: this condition is correct but can be too strict. } @@ -351,7 +356,7 @@ internal class ObjCExportNamerImpl( override fun conflict(first: PropertyDescriptor, second: PropertyDescriptor): Boolean { if (forSwift && configuration.disableSwiftMemberNameMangling) return false // Ignore all conflicts. - return !mapper.canHaveSameName(first, second) + return !mapper.canHaveSameName(first, second, configuration.ignoreInterfaceMethodCollisions) } } @@ -873,7 +878,7 @@ private inline fun StringBuilder.mangledSequence(crossinline mangle: StringBuild private fun StringBuilder.mangledBySuffixUnderscores() = this.mangledSequence { append("_") } -private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second: ClassDescriptor): Boolean { +private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second: ClassDescriptor, ignoreInterfaceMethodCollisions: Boolean): Boolean { if (first.isSubclassOf(second) || second.isSubclassOf(first)) { return true } @@ -882,12 +887,13 @@ private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second return false } - return first.isInterface || second.isInterface + return (first.isInterface || second.isInterface) && !ignoreInterfaceMethodCollisions } private fun ObjCExportMapper.canBeInheritedBySameClass( first: CallableMemberDescriptor, - second: CallableMemberDescriptor + second: CallableMemberDescriptor, + ignoreInterfaceMethodCollisions: Boolean ): Boolean { if (this.isTopLevel(first) || this.isTopLevel(second)) { return this.isTopLevel(first) && this.isTopLevel(second) && @@ -905,14 +911,14 @@ private fun ObjCExportMapper.canBeInheritedBySameClass( return secondClass == firstClass || first !is ConstructorDescriptor && secondClass.isSubclassOf(firstClass) } - return canHaveCommonSubtype(firstClass, secondClass) + return canHaveCommonSubtype(firstClass, secondClass, ignoreInterfaceMethodCollisions) } -private fun ObjCExportMapper.canHaveSameSelector(first: FunctionDescriptor, second: FunctionDescriptor): Boolean { +private fun ObjCExportMapper.canHaveSameSelector(first: FunctionDescriptor, second: FunctionDescriptor, ignoreInterfaceMethodCollisions: Boolean): Boolean { assert(isBaseMethod(first)) assert(isBaseMethod(second)) - if (!canBeInheritedBySameClass(first, second)) { + if (!canBeInheritedBySameClass(first, second, ignoreInterfaceMethodCollisions)) { return true } @@ -940,13 +946,13 @@ private fun ObjCExportMapper.canHaveSameSelector(first: FunctionDescriptor, seco return bridgeMethod(first) == bridgeMethod(second) } -private fun ObjCExportMapper.canHaveSameName(first: PropertyDescriptor, second: PropertyDescriptor): Boolean { +private fun ObjCExportMapper.canHaveSameName(first: PropertyDescriptor, second: PropertyDescriptor, ignoreInterfaceMethodCollisions: Boolean): Boolean { assert(isBaseProperty(first)) assert(isObjCProperty(first)) assert(isBaseProperty(second)) assert(isObjCProperty(second)) - if (!canBeInheritedBySameClass(first, second)) { + if (!canBeInheritedBySameClass(first, second, ignoreInterfaceMethodCollisions)) { return true } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 94eab88e246..ff1c608c9b4 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -5820,6 +5820,38 @@ if (isAppleTarget(project)) { } } + frameworkTest('testObjCExportNoInterfaceMemberNameMangling') { + final String frameworkName = 'KtNoInterfaceMemberNameMangling' + final String frameworkArtifactName = 'Kt' + final String dir = "$testOutputFramework/testObjCExportNoInterfaceMemberNameMangling" + + def libraryName = frameworkName + "Library" + konanArtifacts { + library(libraryName, targets: [target.name]) { + srcDir "objcexport/library" + artifactName "test-library" + + if (!useCustomDist) { + dependsOn ":${target.name}CrossDistRuntime", ':distCompiler' + } + + extraOpts "-Xshort-module-name=MyLibrary" + extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library" + } + } + framework(frameworkName) { + sources = ['objcexport'] + artifact = frameworkArtifactName + library = libraryName + opts = ["-Xbinary=objcExportIgnoreInterfaceMethodCollisions=true"] + } + swiftSources = ['objcexport'] + swiftExtraOpts = [ '-D', 'DISABLE_INTERFACE_METHOD_NAME_MANGLING' ] + if (isNoopGC) { + swiftExtraOpts += ["-D", "NOOP_GC"] + } + } + frameworkTest('testObjCExportStatic') { final String frameworkName = 'KtStatic' final String frameworkArtifactName = 'Kt' diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index cd9338e16db..a2a7aa83b07 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -657,6 +657,53 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((swift_name("InterfaceNameManglingI1"))) +@protocol KtInterfaceNameManglingI1 +@required +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((swift_name("InterfaceNameManglingI2"))) +@protocol KtInterfaceNameManglingI2 +@required +- (id)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (id)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (id)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (id)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) id clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC1"))) +@interface KtInterfaceNameManglingC1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) NSString *clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC2"))) +@interface KtInterfaceNameManglingC2 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceMethodNameManglingKt"))) +@interface KtInterfaceMethodNameManglingKt : KtBase ++ (id)i1 __attribute__((swift_name("i1()"))); ++ (id)i2 __attribute__((swift_name("i2()"))); ++ (KtInterfaceNameManglingC1 *)o1 __attribute__((swift_name("o1()"))); ++ (KtInterfaceNameManglingC2 *)o2 __attribute__((swift_name("o2()"))); +@end + /** * Summary class [KDocExport]. diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h index 0c13e8b9b9f..5466af3adba 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h @@ -657,6 +657,53 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((swift_name("InterfaceNameManglingI1"))) +@protocol KtInterfaceNameManglingI1 +@required +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((swift_name("InterfaceNameManglingI2"))) +@protocol KtInterfaceNameManglingI2 +@required +- (id)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (id)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (id)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (id)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) id clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC1"))) +@interface KtInterfaceNameManglingC1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) NSString *clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC2"))) +@interface KtInterfaceNameManglingC2 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceMethodNameManglingKt"))) +@interface KtInterfaceMethodNameManglingKt : KtBase ++ (id)i1 __attribute__((swift_name("i1()"))); ++ (id)i2 __attribute__((swift_name("i2()"))); ++ (KtInterfaceNameManglingC1 *)o1 __attribute__((swift_name("o1()"))); ++ (KtInterfaceNameManglingC2 *)o2 __attribute__((swift_name("o2()"))); +@end + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("KDocExport"))) @interface KtKDocExport : KtBase diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index d5156d32588..e69286ea481 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -657,6 +657,53 @@ __attribute__((swift_name("TestGH3992.B"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end +__attribute__((swift_name("InterfaceNameManglingI1"))) +@protocol KtInterfaceNameManglingI1 +@required +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (int32_t)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((swift_name("InterfaceNameManglingI2"))) +@protocol KtInterfaceNameManglingI2 +@required +- (id)clashingMethod __attribute__((swift_name("clashingMethod()"))); +- (id)interfaceClashingMethodWithObjCNameInI1 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI1()"))); +- (id)interfaceClashingMethodWithObjCNameInI2 __attribute__((swift_name("interfaceClashingMethodWithObjCNameInI2()"))); +- (id)interfaceClashingMethodWithObjCNameInBoth __attribute__((swift_name("interfaceClashingMethodWithObjCNameInBoth()"))); +@property (readonly) id clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC1"))) +@interface KtInterfaceNameManglingC1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) NSString *clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceNameManglingC2"))) +@interface KtInterfaceNameManglingC2 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)clashingMethod __attribute__((swift_name("clashingMethod()"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("InterfaceMethodNameManglingKt"))) +@interface KtInterfaceMethodNameManglingKt : KtBase ++ (id)i1 __attribute__((swift_name("i1()"))); ++ (id)i2 __attribute__((swift_name("i2()"))); ++ (KtInterfaceNameManglingC1 *)o1 __attribute__((swift_name("o1()"))); ++ (KtInterfaceNameManglingC2 *)o2 __attribute__((swift_name("o2()"))); +@end + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("KDocExport"))) @interface KtKDocExport : KtBase diff --git a/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.kt b/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.kt new file mode 100644 index 00000000000..23fee8da25a --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.kt @@ -0,0 +1,73 @@ +@file:OptIn(kotlin.experimental.ExperimentalObjCName::class) + +package objcNameMangling + +interface InterfaceNameManglingI1 { + val clashingProperty: Int + + fun clashingMethod(): Int + + @ObjCName(name = "interfaceClashingMethodWithObjCNameInI1") + fun clashingMethodWithObjCNameInI1(): Int + + fun interfaceClashingMethodWithObjCNameInI2(): Int + + @ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth") + fun clashingMethodWithObjCNameInBoth(): Int +} + +fun i1() = object : InterfaceNameManglingI1 { + override val clashingProperty: Int + get() = 1 + + override fun clashingMethod(): Int = 2 + + override fun clashingMethodWithObjCNameInI1(): Int = 3 + + override fun interfaceClashingMethodWithObjCNameInI2(): Int = 4 + + override fun clashingMethodWithObjCNameInBoth(): Int = 5 +} + +interface InterfaceNameManglingI2 { + val clashingProperty: Any + + fun clashingMethod(): Any + + fun interfaceClashingMethodWithObjCNameInI1(): Any + + @ObjCName(name = "interfaceClashingMethodWithObjCNameInI2") + fun clashingMethodWithObjCNameInI2(): Any + + @ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth") + fun clashingMethodWithObjCNameInBoth(): Any +} + +fun i2() = object : InterfaceNameManglingI2 { + override val clashingProperty: Any + get() = "one" + + override fun clashingMethod(): Any = "two" + + override fun interfaceClashingMethodWithObjCNameInI1(): Any = "three" + + override fun clashingMethodWithObjCNameInI2(): Any = "four" + + override fun clashingMethodWithObjCNameInBoth(): Any = "five" +} + +class InterfaceNameManglingC1 { + val clashingProperty: String = "one" + + fun clashingMethod(): String = "two" +} + +final class InterfaceNameManglingC2 { + val clashingProperty: Int = 1 + + fun clashingMethod(): Int = 2 +} + +fun o1() = InterfaceNameManglingC1() + +fun o2() = InterfaceNameManglingC2() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.swift b/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.swift new file mode 100644 index 00000000000..28cbaa58bae --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/interfaceMethodNameMangling.swift @@ -0,0 +1,35 @@ +import Kt + +private func test1() throws { + let i1 = InterfaceMethodNameManglingKt.i1() + let i2 = InterfaceMethodNameManglingKt.i2() + let o1 = InterfaceMethodNameManglingKt.o1() + let o2 = InterfaceMethodNameManglingKt.o2() + +#if DISABLE_MEMBER_NAME_MANGLING || DISABLE_INTERFACE_METHOD_NAME_MANGLING + try assertEquals(actual: i1.clashingProperty, expected: 1) + try assertEquals(actual: i1.clashingMethod(), expected: 2) + try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI1(), expected: 3) + try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI2(), expected: 4) + try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInBoth(), expected: 5) + + try assertEquals(actual: i2.clashingProperty as! String, expected: "one") + try assertEquals(actual: i2.clashingMethod() as! String, expected: "two") + try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI1() as! String, expected: "three") + try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI2() as! String, expected: "four") + try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInBoth() as! String, expected: "five") + + try assertEquals(actual: o1.clashingProperty, expected: "one") + try assertEquals(actual: o1.clashingMethod(), expected: "two") +#endif + try assertEquals(actual: o2.clashingProperty, expected: 1) + try assertEquals(actual: o2.clashingMethod(), expected: 2) +} + +class InterfaceMethodNameManglingTests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/swiftNameMangling.swift b/kotlin-native/backend.native/tests/objcexport/swiftNameMangling.swift index f03cfa7abe4..9bce032f716 100644 --- a/kotlin-native/backend.native/tests/objcexport/swiftNameMangling.swift +++ b/kotlin-native/backend.native/tests/objcexport/swiftNameMangling.swift @@ -4,7 +4,7 @@ private func test1() throws { let i1 = SwiftNameManglingKt.i1() let i2 = SwiftNameManglingKt.i2() -#if DISABLE_MEMBER_NAME_MANGLING +#if DISABLE_MEMBER_NAME_MANGLING || DISABLE_INTERFACE_METHOD_NAME_MANGLING try assertEquals(actual: i1.clashingProperty, expected: 1) try assertEquals(actual: i1.clashingMethod(), expected: 2) try assertEquals(actual: i1.swiftClashingMethodWithObjCNameInI1(), expected: 3) diff --git a/kotlin-native/backend.native/tests/objcexport/values.swift b/kotlin-native/backend.native/tests/objcexport/values.swift index ad3abf957c6..b8251abbab0 100644 --- a/kotlin-native/backend.native/tests/objcexport/values.swift +++ b/kotlin-native/backend.native/tests/objcexport/values.swift @@ -727,7 +727,7 @@ func testClashes() throws { try assertEquals(actual: 1, expected: test1.clashingProperty) -#if !DISABLE_MEMBER_NAME_MANGLING +#if !DISABLE_MEMBER_NAME_MANGLING && !DISABLE_INTERFACE_METHOD_NAME_MANGLING try assertEquals(actual: 1, expected: test2.clashingProperty_ as! Int32) try assertEquals(actual: 2, expected: test2.clashingProperty__ as! Int32) #endif