From 5d5628f56e878850af7dd8ab0515e1508ea13d8c Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Fri, 11 Jun 2021 15:35:25 +0300 Subject: [PATCH] Native: apply ObjCExport virtual adapters from interfaces of supers Previously they were skipped, and this was an incorrect optimization: even if super class implements the interface too, this doesn't mean that virtual adapters provided by that interface are inherited by non-exported subclass that needs them; for example, this doesn't happen when the super class is exported (i.e. Obj-C class is not created at runtime). Remove incorrect optimization instead of making it more sophisticated, because it is useless anyway. ^KT-46431 Fixed --- .../tests/objcexport/expectedLazy.h | 18 +++++++++++++++++ .../tests/objcexport/expectedLazyNoGenerics.h | 18 +++++++++++++++++ .../tests/objcexport/kt46431.kt | 20 +++++++++++++++++++ .../tests/objcexport/kt46431.swift | 20 +++++++++++++++++++ .../runtime/src/main/cpp/ObjCExport.mm | 10 ++++++---- 5 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 kotlin-native/backend.native/tests/objcexport/kt46431.kt create mode 100644 kotlin-native/backend.native/tests/objcexport/kt46431.swift diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index dd16057b10f..9535d1fb281 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -731,6 +731,24 @@ __attribute__((swift_name("Kt43599Kt"))) @property (class, readonly) NSString *topLevelLateinitProperty __attribute__((swift_name("topLevelLateinitProperty"))); @end; +__attribute__((swift_name("Host"))) +@protocol KtHost +@required +@property (readonly) NSString *test __attribute__((swift_name("test"))); +@end; + +__attribute__((swift_name("AbstractHost"))) +@interface KtAbstractHost : KtBase +- (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("Kt46431Kt"))) +@interface KtKt46431Kt : KtBase ++ (id)createAbstractHost __attribute__((swift_name("createAbstractHost()"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("KT43780TestObject"))) @interface KtKT43780TestObject : KtBase diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index af91b0fbc1d..a3030e3cfbd 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -673,6 +673,24 @@ __attribute__((swift_name("Kt43599Kt"))) @property (class, readonly) NSString *topLevelLateinitProperty __attribute__((swift_name("topLevelLateinitProperty"))); @end; +__attribute__((swift_name("Host"))) +@protocol KtHost +@required +@property (readonly) NSString *test __attribute__((swift_name("test"))); +@end; + +__attribute__((swift_name("AbstractHost"))) +@interface KtAbstractHost : KtBase +- (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("Kt46431Kt"))) +@interface KtKt46431Kt : KtBase ++ (id)createAbstractHost __attribute__((swift_name("createAbstractHost()"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("KT43780TestObject"))) @interface KtKT43780TestObject : KtBase diff --git a/kotlin-native/backend.native/tests/objcexport/kt46431.kt b/kotlin-native/backend.native/tests/objcexport/kt46431.kt new file mode 100644 index 00000000000..87298724a00 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt46431.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kt43599 + +// Based on https://youtrack.jetbrains.com/issue/KT-46431 + +interface Host { + val test: String +} +abstract class AbstractHost : Host + +fun createAbstractHost(): Host { + return object : AbstractHost() { + override val test: String + get() = "1234" + } +} diff --git a/kotlin-native/backend.native/tests/objcexport/kt46431.swift b/kotlin-native/backend.native/tests/objcexport/kt46431.swift new file mode 100644 index 00000000000..b6326699e72 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt46431.swift @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +// Based on https://youtrack.jetbrains.com/issue/KT-46431. + +private func test1() throws { + try assertEquals(actual: Kt46431Kt.createAbstractHost().test, expected: "1234") +} + +class Kt46431Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm index ac847d484b4..64aaecdcbe2 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm @@ -1027,10 +1027,12 @@ static Class createClass(const TypeInfo* typeInfo, Class superClass) { for (int i = 0; i < typeInfo->implementedInterfacesCount_; ++i) { const TypeInfo* interface = typeInfo->implementedInterfaces_[i]; - if (superImplementedInterfaces.find(interface) == superImplementedInterfaces.end()) { - const ObjCTypeAdapter* typeAdapter = getTypeAdapter(interface); - if (typeAdapter != nullptr) { - addVirtualAdapters(result, typeAdapter); + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(interface); + if (typeAdapter != nullptr) { + // Note: we could avoid adding virtual adapters if inherited from super type, + // but what's the point? + addVirtualAdapters(result, typeAdapter); + if (superImplementedInterfaces.find(interface) == superImplementedInterfaces.end()) { addProtocolForAdapter(result, typeAdapter); } }