From eab51649934b70d2d01e4069ea41bb291837dfaa Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 15 Feb 2024 12:32:04 +0100 Subject: [PATCH] Scripting: fix script lowering in case of out of order declarations The problem was that in K2 for some top-level script declarations we need to add a dispatch receiver parameter (because frontend do not assign any, but representing script as a class requires it to be the script class) and at the same time, calls to these declarations rely on properly set dispatch receiver parameter. The simplest solution found is to have an additional traversal on the relevan top-level declarations and assigning the dispatch receiver, before running the main transformation. #KT-64502 fixed --- .../backend/jvm/lower/ScriptLowering.kt | 22 ++++++++++++++ .../codegen/script/kt48025.jvm_abi.txt | 23 ++++++++++++++ compiler/testData/codegen/script/kt48025.kts | 2 +- ...nonymousObjectCapturesProperty.jvm_abi.txt | 30 +++++++++++++++++++ .../anonymousObjectCapturesProperty.kts | 2 +- .../testScripts/declarationsOrder1.test.kts | 7 +++++ .../testScripts/declarationsOrder2.test.kts | 6 ++++ ...CustomDefBlackBoxCodegenTestGenerated.java | 12 ++++++++ 8 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/script/kt48025.jvm_abi.txt create mode 100644 compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.jvm_abi.txt create mode 100644 plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder1.test.kts create mode 100644 plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder2.test.kts diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ScriptLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ScriptLowering.kt index 03523dab973..e77fbeea8ab 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ScriptLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ScriptLowering.kt @@ -201,6 +201,8 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner ) val lambdaPatcher = ScriptFixLambdasTransformer(irScriptClass) + irScript.patchDeclarationsDispatchReceiver(context, scriptTransformer.scriptClassReceiver.type) + irScriptClass.thisReceiver = scriptTransformer.scriptClassReceiver fun E.patchDeclarationForClass(): IrElement { @@ -439,6 +441,26 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner } } +private fun IrScript.patchDeclarationsDispatchReceiver(context: JvmBackendContext, scriptClassReceiverType: IrType) { + + fun IrFunction.addScriptDispatchReceiverIfNeeded() { + if (dispatchReceiverParameter == null) { + dispatchReceiverParameter = + createThisReceiverParameter(context, IrDeclarationOrigin.SCRIPT_THIS_RECEIVER, scriptClassReceiverType) + } + } + + statements.forEach { scriptStatement -> + when (scriptStatement) { + is IrProperty -> { + scriptStatement.getter?.addScriptDispatchReceiverIfNeeded() + scriptStatement.setter?.addScriptDispatchReceiverIfNeeded() + } + is IrFunction -> scriptStatement.addScriptDispatchReceiverIfNeeded() + } + } +} + private fun IrBuilderWithScope.makeScriptClassConstructorBody( irScript: IrScript, irScriptClass: IrClass, diff --git a/compiler/testData/codegen/script/kt48025.jvm_abi.txt b/compiler/testData/codegen/script/kt48025.jvm_abi.txt new file mode 100644 index 00000000000..660a5afb9b9 --- /dev/null +++ b/compiler/testData/codegen/script/kt48025.jvm_abi.txt @@ -0,0 +1,23 @@ +MODULE main + CLASS Kt48025.class + CLASS METADATA + K1 + ([Ljava/lang/String;)V + K2 + --- + Property: class.metadata.superTypes + K1 + [kotlin/script/templates/standard/ScriptTemplateWithArgs] + K2 + [] + Property: class.metadata.contextReceiverTypes + K1 + [] + K2 + [kotlin/script/templates/standard/ScriptTemplateWithArgs] + PROPERTY getC()LKt48025$ReducedFraction; + Property: class.metadata.property.returnType + K1 + Kt48025.ReducedFraction + K2 + ReducedFraction diff --git a/compiler/testData/codegen/script/kt48025.kts b/compiler/testData/codegen/script/kt48025.kts index 732bdc7be2b..aca132db21a 100644 --- a/compiler/testData/codegen/script/kt48025.kts +++ b/compiler/testData/codegen/script/kt48025.kts @@ -1,4 +1,4 @@ -// IGNORE_BACKEND_K2: JVM_IR +// JVM_ABI_K1_K2_DIFF: KT-63960, KT-63963, KT-63964 val p = 0 diff --git a/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.jvm_abi.txt b/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.jvm_abi.txt new file mode 100644 index 00000000000..8588c65f85f --- /dev/null +++ b/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.jvm_abi.txt @@ -0,0 +1,30 @@ +MODULE main + CLASS AnonymousObjectCapturesProperty.class + CLASS METADATA + K1 + ([Ljava/lang/String;)V + K2 + --- + Property: class.metadata.superTypes + K1 + [kotlin/script/templates/standard/ScriptTemplateWithArgs] + K2 + [] + Property: class.metadata.contextReceiverTypes + K1 + [] + K2 + [kotlin/script/templates/standard/ScriptTemplateWithArgs] + PROPERTY getB()LAnonymousObjectCapturesProperty$A; + Property: class.metadata.property.returnType + K1 + AnonymousObjectCapturesProperty.A + K2 + A + CLASS AnonymousObjectCapturesProperty$B$1.class + CLASS METADATA + Property: class.metadata.superTypes + K1 + [AnonymousObjectCapturesProperty.A] + K2 + [A] diff --git a/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.kts b/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.kts index ca5a0c61e54..8efad7b4cce 100644 --- a/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.kts +++ b/compiler/testData/codegen/script/scriptInstanceCapturing/anonymousObjectCapturesProperty.kts @@ -1,5 +1,5 @@ // IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM -// IGNORE_BACKEND_K2: JVM_IR +// JVM_ABI_K1_K2_DIFF: KT-63960, KT-63963, KT-63964 // expected: rv: 42 diff --git a/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder1.test.kts b/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder1.test.kts new file mode 100644 index 00000000000..8aeff68b5fe --- /dev/null +++ b/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder1.test.kts @@ -0,0 +1,7 @@ +// code from KT-64502 +fun foo() { + bar() +} + +fun bar() {} + diff --git a/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder2.test.kts b/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder2.test.kts new file mode 100644 index 00000000000..8131eba79ae --- /dev/null +++ b/plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder2.test.kts @@ -0,0 +1,6 @@ + +fun foo() { + x +} + +val x: Int get() = 42 diff --git a/plugins/scripting/scripting-tests/tests-gen/org/jetbrains/kotlin/scripting/test/ScriptWithCustomDefBlackBoxCodegenTestGenerated.java b/plugins/scripting/scripting-tests/tests-gen/org/jetbrains/kotlin/scripting/test/ScriptWithCustomDefBlackBoxCodegenTestGenerated.java index 2d6b8dafbc3..7204659cd0a 100644 --- a/plugins/scripting/scripting-tests/tests-gen/org/jetbrains/kotlin/scripting/test/ScriptWithCustomDefBlackBoxCodegenTestGenerated.java +++ b/plugins/scripting/scripting-tests/tests-gen/org/jetbrains/kotlin/scripting/test/ScriptWithCustomDefBlackBoxCodegenTestGenerated.java @@ -25,6 +25,18 @@ public class ScriptWithCustomDefBlackBoxCodegenTestGenerated extends AbstractScr KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/scripting/scripting-tests/testData/codegen/testScripts"), Pattern.compile("^(.+)\\.kts$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("declarationsOrder1.test.kts") + public void testDeclarationsOrder1_test() { + runTest("plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder1.test.kts"); + } + + @Test + @TestMetadata("declarationsOrder2.test.kts") + public void testDeclarationsOrder2_test() { + runTest("plugins/scripting/scripting-tests/testData/codegen/testScripts/declarationsOrder2.test.kts"); + } + @Test @TestMetadata("params.test.kts") public void testParams_test() {