From ef1388e5147e5d27f2c161ea6421042c959948dd Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Fri, 1 Nov 2019 11:13:45 +0300 Subject: [PATCH] Fix #3525 (#3528) Workaround https://bugs.swift.org/browse/SR-11686 --- .../objcexport/ObjCExportHeaderGenerator.kt | 34 +++++++++---------- .../tests/framework/values/expectedLazy.h | 24 +++++++++++-- .../tests/framework/values/values.kt | 16 +++++++++ .../tests/framework/values/values.swift | 22 ++++++++++++ 4 files changed, 76 insertions(+), 20 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index 7ccd62f9c7d..5a107be7111 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -339,6 +339,23 @@ internal class ObjCExportTranslatorImpl( +ObjCMethod(descriptor, false, ObjCInstanceType, listOf("allocWithZone:"), listOf(parameter), listOf("unavailable")) } + // Hide "unimplemented" super constructors: + superClass?.constructors + ?.asSequence() + ?.filter { mapper.shouldBeExposed(it) } + ?.forEach { + val selector = getSelector(it) + if (selector !in presentConstructors) { + +buildMethod(it, it, ObjCNoneExportScope, unavailable = true) + + if (selector == "init") { + +ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable")) + } + + // TODO: consider adding exception-throwing impls for these. + } + } + // TODO: consider adding exception-throwing impls for these. when (descriptor.kind) { ClassKind.OBJECT -> { @@ -362,23 +379,6 @@ internal class ObjCExportTranslatorImpl( } } - // Hide "unimplemented" super constructors: - superClass?.constructors - ?.asSequence() - ?.filter { mapper.shouldBeExposed(it) } - ?.forEach { - val selector = getSelector(it) - if (selector !in presentConstructors) { - +buildMethod(it, it, ObjCNoneExportScope, unavailable = true) - - if (selector == "init") { - +ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable")) - } - - // TODO: consider adding exception-throwing impls for these. - } - } - translateClassMembers(descriptor) } diff --git a/backend.native/tests/framework/values/expectedLazy.h b/backend.native/tests/framework/values/expectedLazy.h index da5129b86d4..e9fa9c0ba66 100644 --- a/backend.native/tests/framework/values/expectedLazy.h +++ b/backend.native/tests/framework/values/expectedLazy.h @@ -189,10 +189,10 @@ __attribute__((swift_name("Enumeration"))) @interface ValuesEnumeration : ValuesKotlinEnum + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); @property (class, readonly) ValuesEnumeration *answer __attribute__((swift_name("answer"))); @property (class, readonly) ValuesEnumeration *year __attribute__((swift_name("year"))); @property (class, readonly) ValuesEnumeration *temperature __attribute__((swift_name("temperature"))); -- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); - (int32_t)compareToOther:(ValuesEnumeration *)other __attribute__((swift_name("compareTo(other:)"))); @property (readonly) int32_t enumValue __attribute__((swift_name("enumValue"))); @end; @@ -250,9 +250,9 @@ __attribute__((swift_name("WithCompanionAndObject.Named"))) @interface ValuesWithCompanionAndObjectNamed : ValuesOpenClassI + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); -+ (instancetype)named __attribute__((swift_name("init()"))); - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); + (instancetype)new __attribute__((unavailable)); ++ (instancetype)named __attribute__((swift_name("init()"))); - (NSString *)iFun __attribute__((swift_name("iFun()"))); @end; @@ -625,11 +625,11 @@ __attribute__((swift_name("TestInvalidIdentifiers.E"))) @interface ValuesTestInvalidIdentifiersE : ValuesKotlinEnum + (instancetype)alloc __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); @property (class, readonly) ValuesTestInvalidIdentifiersE *_4_ __attribute__((swift_name("_4_"))); @property (class, readonly) ValuesTestInvalidIdentifiersE *_5_ __attribute__((swift_name("_5_"))); @property (class, readonly) ValuesTestInvalidIdentifiersE *__ __attribute__((swift_name("__"))); @property (class, readonly) ValuesTestInvalidIdentifiersE *__ __attribute__((swift_name("__"))); -- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); - (int32_t)compareToOther:(ValuesTestInvalidIdentifiersE *)other __attribute__((swift_name("compareTo(other:)"))); @property (readonly) int32_t value __attribute__((swift_name("value"))); @end; @@ -1014,6 +1014,22 @@ __attribute__((swift_name("AbstractInterfaceBase3"))) - (int32_t)foo __attribute__((swift_name("foo()"))); @end; +__attribute__((swift_name("GH3525Base"))) +@interface ValuesGH3525Base : ValuesBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH3525"))) +@interface ValuesGH3525 : ValuesGH3525Base ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); ++ (instancetype)gH3525 __attribute__((swift_name("init()"))); +@end; + @interface ValuesEnumeration (ValuesKt) - (ValuesEnumeration *)getAnswer __attribute__((swift_name("getAnswer()"))); @end; @@ -1129,5 +1145,7 @@ __attribute__((swift_name("ValuesKt"))) @property (class) id _Nullable errorVar __attribute__((swift_name("errorVar"))) __attribute__((unavailable("error"))); @property (class, readonly) id _Nullable warningVal __attribute__((swift_name("warningVal"))) __attribute__((deprecated("warning"))); @property (class) id _Nullable warningVar __attribute__((swift_name("warningVar"))) __attribute__((deprecated("warning"))); +@property (class) int32_t gh3525BaseInitCount __attribute__((swift_name("gh3525BaseInitCount"))); +@property (class) int32_t gh3525InitCount __attribute__((swift_name("gh3525InitCount"))); @end; diff --git a/backend.native/tests/framework/values/values.kt b/backend.native/tests/framework/values/values.kt index 6ca3ce01918..031f6a3bad4 100644 --- a/backend.native/tests/framework/values/values.kt +++ b/backend.native/tests/framework/values/values.kt @@ -810,4 +810,20 @@ abstract class AbstractInterfaceBase2 : IAbstractInterface2 abstract class AbstractInterfaceBase3 : IAbstractInterface { abstract override fun foo(): Int +} + +var gh3525BaseInitCount = 0 + +open class GH3525Base { + init { + gh3525BaseInitCount++ + } +} + +var gh3525InitCount = 0 + +object GH3525 : GH3525Base() { + init { + gh3525InitCount++ + } } \ No newline at end of file diff --git a/backend.native/tests/framework/values/values.swift b/backend.native/tests/framework/values/values.swift index de88a55e4a3..e07d94fab35 100644 --- a/backend.native/tests/framework/values/values.swift +++ b/backend.native/tests/framework/values/values.swift @@ -1058,6 +1058,25 @@ func testGH3503_3() throws { try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface3()), expected: 42) } +func testGH3525() throws { + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 0) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 0) + + let gh3525_1 = GH3525() + try assertTrue(gh3525_1 is GH3525) + + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) + + let gh3525_2 = GH3525() + try assertTrue(gh3525_2 is GH3525) + + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) + + try assertTrue(gh3525_1 === gh3525_2) +} + // -------- Execution of the test -------- class ValuesTests : TestProvider { @@ -1112,6 +1131,9 @@ class ValuesTests : TestProvider { TestCase(name: "TestGH3503_1", method: withAutorelease(testGH3503_1)), TestCase(name: "TestGH3503_2", method: withAutorelease(testGH3503_2)), TestCase(name: "TestGH3503_3", method: withAutorelease(testGH3503_3)), + TestCase(name: "TestGH3525", method: withAutorelease(testGH3525)), + + // Stress test, must remain the last one: TestCase(name: "TestGH2931", method: withAutorelease(testGH2931)), ] }