diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index b42a56d8d81..1532a88e7ed 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -97,7 +97,9 @@ internal object Devirtualization { moduleDFG.symbolTable.functionMap.values.filter { it.explicitlyExported } + externalModulesDFG.functionDFGs.keys.filter { it.explicitlyExported } - // Conservatively assume each associated object could be instantiated. + // Conservatively assume each associated object could be called. + // Note: for constructors there is additional parameter () and its type will be added + // to instantiating classes since all objects are final types. val associatedObjects = mutableListOf() context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid { override fun visitElement(element: IrElement) { @@ -898,6 +900,8 @@ internal object Devirtualization { } if (entryPoint == null) { // For library assume all public non-abstract classes could be instantiated. + // Note: for constructors there is additional parameter () and for associated objects + // its type will be added to instantiating classes since all objects are final types. symbolTable.classMap.values .filterIsInstance() .filter { !it.isAbstract } @@ -907,20 +911,6 @@ internal object Devirtualization { addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()) addEdge(concreteClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()), fieldNode(constraintGraph.arrayItemField)) - // Conservatively assume each associated object could be instantiated. - context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitClass(declaration: IrClass) { - context.getLayoutBuilder(declaration).associatedObjects.values.forEach { - assert (it.kind == ClassKind.OBJECT) { "An object expected but was ${it.dump()}" } - addInstantiatingClass(symbolTable.mapType(it.defaultType).resolved()) - } - super.visitClass(declaration) - } - }) } rootSet.forEach { createFunctionConstraintGraph(it, true) } while (stack.isNotEmpty()) { diff --git a/backend.native/tests/objcexport/expectedLazy.h b/backend.native/tests/objcexport/expectedLazy.h index a90ae1b33ce..a233bc6e11c 100644 --- a/backend.native/tests/objcexport/expectedLazy.h +++ b/backend.native/tests/objcexport/expectedLazy.h @@ -204,6 +204,12 @@ __attribute__((swift_name("GH4002Argument"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt35940Kt"))) +@interface KtKt35940Kt : KtBase ++ (NSString *)testKt35940 __attribute__((swift_name("testKt35940()"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("LibraryKt"))) @interface KtLibraryKt : KtBase diff --git a/backend.native/tests/objcexport/kt35940.kt b/backend.native/tests/objcexport/kt35940.kt new file mode 100644 index 00000000000..7a032bfcdcf --- /dev/null +++ b/backend.native/tests/objcexport/kt35940.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2020 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 kt35940 + +import kotlin.reflect.* + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated(val kClass: KClass<*>) + +private interface I1 { + val s: String +} + +private class I1Impl : I1 { + override val s = "zzz" +} + +private class C(var i1: I1?) + +private interface I2 { + fun bar(c: C) +} + +private object I2Impl : I2 { + override fun bar(c: C) { + c.i1 = I1Impl() + } +} + +@Associated(I2Impl::class) +private class I2ImplHolder + +@OptIn(ExperimentalAssociatedObjects::class) +fun testKt35940(): String { + val i2 = I2ImplHolder::class.findAssociatedObject()!! as I2 + val c = C(null) + i2.bar(c) + return c.i1!!.s +} diff --git a/backend.native/tests/objcexport/kt35940.swift b/backend.native/tests/objcexport/kt35940.swift new file mode 100644 index 00000000000..6fba9a53182 --- /dev/null +++ b/backend.native/tests/objcexport/kt35940.swift @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 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 + +private func test1() throws { + try assertEquals(actual: Kt35940Kt.testKt35940(), expected: "zzz") +} + +class Kt35940Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file