From ea7160947ad541c35dbad90174b972fe9e16d29d Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 10 Nov 2021 12:30:12 +0000 Subject: [PATCH] Native: enable lazy IR generation before running fake override builder ^KT-48816 Fixed Native compiler uses lazy IR for declarations provided by cinterop. The problem: `FakeOverrideBuilder` requests super types during type checking, accessing `.owner` for them. So if a type and super type are represented as lazy IR, and lazy IR generation is not enabled yet, then the super type symbol won't be bound by this moment, and the access will fail. This happens in KT-48816: fake override builder tries to access `.owner` for `IrClassSymbol` of `NSObject` (super type of `NSDate` and `NSUUID`). Fix this by enabling lazy IR generation before building fake overrides. --- .../konan/serialization/KonanIrlinker.kt | 3 +- .../backend.native/tests/build.gradle | 18 +++++++ .../tests/interop/objc/kt48816/main.kt | 51 +++++++++++++++++++ .../tests/interop/objc/kt48816/objclib.def | 2 + .../tests/interop/objc/kt48816/objclib.h | 9 ++++ 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt48816/main.kt create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.def create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.h diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt index fa836b01f67..ea66e8072c6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -363,8 +363,7 @@ internal class KonanIrLinker( } override fun postProcess() { - if (lazyIrForCaches) - stubGenerator.unboundSymbolGeneration = true + stubGenerator.unboundSymbolGeneration = true super.postProcess() } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 279ccf8007a..03f188f23d0 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -4327,6 +4327,10 @@ if (PlatformInfo.isAppleTarget(project)) { it.defFile 'interop/objc/kt42172/objclib.def' it.headers "$projectDir/interop/objc/kt42172/objclib.h" } + createInterop("objc_kt48816") { + it.defFile 'interop/objc/kt48816/objclib.def' + it.headers "$projectDir/interop/objc/kt48816/objclib.h" + } } createInterop("withSpaces") { @@ -4952,6 +4956,20 @@ if (PlatformInfo.isAppleTarget(project)) { } } + interopTest("interop_objc_kt48816_without_lazy_ir_for_caches") { + // Without a fix, fails in two-stage mode. + source = "interop/objc/kt48816/main.kt" + interop = "objc_kt48816" + // The bug was accidentally fixed with lazy IR for caches, so testing it with this feature disabled: + flags = ["-Xlazy-ir-for-caches=disable"] + } + + interopTest("interop_objc_kt48816_with_lazy_ir_for_caches") { + source = "interop/objc/kt48816/main.kt" + interop = "objc_kt48816" + flags = ["-Xlazy-ir-for-caches=enable"] + } + standaloneTest("objc_arc_contract") { doBeforeBuild { mkdir(buildDir) diff --git a/kotlin-native/backend.native/tests/interop/objc/kt48816/main.kt b/kotlin-native/backend.native/tests/interop/objc/kt48816/main.kt new file mode 100644 index 00000000000..3d97bf3750b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt48816/main.kt @@ -0,0 +1,51 @@ +import kotlin.reflect.* +import kotlin.test.* +import objclib.* + +// https://youtrack.jetbrains.com/issue/KT-48816 +open class Base { + operator fun KProperty1.getValue(ref: Base, property: KProperty<*>): NSUUID? { + return null + } + operator fun KProperty1.getValue(ref: Base, property: KProperty<*>): NSDate? { + return null + } +} +class Usage: Base() +class B + +// The compilation should fail with the above; +// but anyway try to actually use the code, just to ensure it doesn't get DCEd: + +val B.uuid: NSUUID get() = fail() +val B.date: NSDate get() = fail() + +fun test1() { + val uuidProperty = B::uuid + val dateProperty = B::date + val usage = Usage() + with(usage) { + assertNull(uuidProperty.getValue(usage, uuidProperty)) + assertNull(dateProperty.getValue(usage, dateProperty)) + } +} + +// One more reproducer, just in case: +class Property + +open class Base2 { + fun getValue(property: Property) = null + fun getValue(property: Property) = null +} +class Usage2 : Base2() + +fun test2() { + val usage = Usage2() + assertNull(usage.getValue(Property())) + assertNull(usage.getValue(Property())) +} + +fun main() { + test1() + test2() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.def b/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.def new file mode 100644 index 00000000000..8dfe477cdbd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.def @@ -0,0 +1,2 @@ +language = Objective-C +headerFilter = **/objclib.h **/NSObject.h **/NSDate.h **/NSUUID.h diff --git a/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.h b/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.h new file mode 100644 index 00000000000..783eca32a8f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt48816/objclib.h @@ -0,0 +1,9 @@ +#import +#import +#import + +@interface MyClass1 : NSObject +@end; + +@interface MyClass2 : NSObject +@end;