From efb6756cbc88fec140c547cc51d1528b8cca8dd3 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 10 Jul 2017 15:44:50 +0300 Subject: [PATCH] Initialize property metadata array before class body generation Initialization of companion object members (e.g., delegate properties using provideDelegate convention) can depend on property metadata array, which in turn can be initialized before other class members. #KT-18902 Fixed Target versions 1.1.5 --- .../codegen/ImplementationBodyCodegen.java | 5 ++++- .../codegen/InterfaceImplBodyCodegen.kt | 2 +- .../kotlin/codegen/MemberCodegen.java | 18 +++++++++++---- .../codegen/MultifileClassPartCodegen.kt | 2 +- .../kotlin/codegen/PackagePartCodegen.java | 2 +- .../kotlin/codegen/ScriptCodegen.java | 6 ++++- .../provideDelegate/kt18902.kt | 22 +++++++++++++++++++ .../topLevelPropertyWithProvideDelegate.kts | 21 ++++++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ .../LightAnalysisModeTestGenerated.java | 6 +++++ .../codegen/ScriptCodegenTestGenerated.java | 6 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 6 +++++ 13 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt create mode 100644 compiler/testData/codegen/script/topLevelPropertyWithProvideDelegate.kts diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 54e0abecba4..40385c0e140 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -348,9 +348,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } @Override - protected void generateSyntheticParts() { + protected void generateSyntheticPartsBeforeBody() { generatePropertyMetadataArrayFieldIfNeeded(classAsmType); + } + @Override + protected void generateSyntheticPartsAfterBody() { generateFieldForSingleton(); generateCompanionObjectBackingFieldCopies(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt index ba0fcf9541b..0b293609837 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt @@ -70,7 +70,7 @@ class InterfaceImplBodyCodegen( return classDescriptorImpl } - override fun generateSyntheticParts() { + override fun generateSyntheticPartsAfterBody() { for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) { if (memberDescriptor !is CallableMemberDescriptor) continue diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index e97fa53a854..db3688df1a8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -131,11 +131,18 @@ public abstract class MemberCodegen { } @Override - protected void generateSyntheticParts() { + protected void generateSyntheticPartsAfterBody() { generateSyntheticAccessors(); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java index ddcffcdf5bb..d30f3388bef 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java @@ -105,10 +105,14 @@ public class ScriptCodegen extends MemberCodegen { } @Override - protected void generateSyntheticParts() { + protected void generateSyntheticPartsBeforeBody() { generatePropertyMetadataArrayFieldIfNeeded(classAsmType); } + @Override + protected void generateSyntheticPartsAfterBody() { + } + @Override protected void generateKotlinMetadataAnnotation() { generateKotlinClassMetadataAnnotation(scriptDescriptor, true); diff --git a/compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt b/compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt new file mode 100644 index 00000000000..9b20ca39800 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt @@ -0,0 +1,22 @@ +// WITH_RUNTIME + +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +class Delegate: ReadOnlyProperty { + override fun getValue(thisRef: Test, property: KProperty<*>) = "OK" +} + +class Provider { + operator fun provideDelegate(thisRef: Test, property: KProperty<*>) = Delegate() +} + +class Test { + companion object { + val instance = Test() + } + + val message by Provider() +} + +fun box() = Test.instance.message \ No newline at end of file diff --git a/compiler/testData/codegen/script/topLevelPropertyWithProvideDelegate.kts b/compiler/testData/codegen/script/topLevelPropertyWithProvideDelegate.kts new file mode 100644 index 00000000000..2736b571048 --- /dev/null +++ b/compiler/testData/codegen/script/topLevelPropertyWithProvideDelegate.kts @@ -0,0 +1,21 @@ +import kotlin.reflect.KProperty + +class Delegate { + operator fun getValue(thisRef: Test, property: KProperty<*>) = "OK" +} + +class Provider { + operator fun provideDelegate(thisRef: Test, property: KProperty<*>) = Delegate() +} + +class Test { + companion object { + val instance = Test() + } + + val message by Provider() +} + +val x = Test.instance.message + +// expected: x: OK \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9b71798c5a9..74727ea1751 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7030,6 +7030,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("kt18902.kt") + public void testKt18902() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt"); + doTest(fileName); + } + @TestMetadata("local.kt") public void testLocal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/local.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 29342fbc97d..4619f4eb2cf 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7030,6 +7030,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt18902.kt") + public void testKt18902() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt"); + doTest(fileName); + } + @TestMetadata("local.kt") public void testLocal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/local.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 3ff36f5a864..7d09abf41b5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7030,6 +7030,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("kt18902.kt") + public void testKt18902() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt"); + doTest(fileName); + } + @TestMetadata("local.kt") public void testLocal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/local.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java index 4e534d2ab6c..428119fff92 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java @@ -186,6 +186,12 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest { doTest(fileName); } + @TestMetadata("topLevelPropertyWithProvideDelegate.kts") + public void testTopLevelPropertyWithProvideDelegate() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelPropertyWithProvideDelegate.kts"); + doTest(fileName); + } + @TestMetadata("topLevelTypealias.kts") public void testTopLevelTypealias() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelTypealias.kts"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index bcabe9defa1..cbc136fb267 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -7810,6 +7810,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("kt18902.kt") + public void testKt18902() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/kt18902.kt"); + doTest(fileName); + } + @TestMetadata("local.kt") public void testLocal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate/local.kt");