From 3ab2b82878348fe44d059117325ed2502002040f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 1 Dec 2022 01:27:08 +0100 Subject: [PATCH] JVM IR: script is a valid container for local delegated properties When serializing metadata for local delegated properties, we need to find a valid container class where to put it, and where kotlin-reflect will be able to find that metadata at runtime. Taking just the closest class lexically doesn't work, because in the attached test, it is a class for a lambda which does not have metadata and thus does not have a way to store any extra information. So, in 16636196061 we started to look for the closest "non-synthetic" class to store this metadata. But apparently it was missed that script is a valid container class. In the test, this meant that no non-synthetic container classes were found to store the metadata, so we falled back to using the closest class anyway (see `?: this` in `rememberLocalProperty`), which turned out to be the lambda. After this change, metadata for local delegated property in a lambda will be stored in the script class, just like it's stored in the file class in the non-script case. #KT-55065 Fixed --- .../jvm/lower/PropertyReferenceLowering.kt | 3 ++- .../script/localDelegatedPropertyInLambda.kts | 17 +++++++++++++++++ .../codegen/AbstractScriptCodegenTest.java | 14 ++++++++------ .../codegen/ScriptCodegenTestGenerated.java | 5 +++++ .../ir/IrScriptCodegenTestGenerated.java | 5 +++++ 5 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt index a18fa537eda..d834e20f9d0 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt @@ -202,7 +202,8 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle val localProperties = mutableListOf() val localPropertyIndices = mutableMapOf() - val isSynthetic = irClass.metadata !is MetadataSource.File && irClass.metadata !is MetadataSource.Class + val isSynthetic = irClass.metadata !is MetadataSource.File && irClass.metadata !is MetadataSource.Class && + irClass.metadata !is MetadataSource.Script fun localPropertyIndex(getter: IrSymbol): Int? = localPropertyIndices[getter] ?: parent?.localPropertyIndex(getter) diff --git a/compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts b/compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts new file mode 100644 index 00000000000..1453eed0595 --- /dev/null +++ b/compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts @@ -0,0 +1,17 @@ +// WITH_REFLECT + +import kotlin.reflect.KProperty + +class Delegate { + operator fun getValue(t: Any?, p: KProperty<*>): String = + if (p.returnType.toString() == "kotlin.String") "OK" else "Fail: ${p.returnType}" +} + +fun f(lambda: () -> String): String = lambda() + +val x = f { + val prop: String by Delegate() + prop +} + +// expected: x: OK diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractScriptCodegenTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractScriptCodegenTest.java index f129f4b6b50..6663a8a3bd3 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractScriptCodegenTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractScriptCodegenTest.java @@ -17,25 +17,23 @@ package org.jetbrains.kotlin.codegen; import com.intellij.openapi.util.Pair; +import kotlin.io.FilesKt; +import kotlin.text.Charsets; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.test.ConfigurationKind; +import org.jetbrains.kotlin.test.InTextDirectivesUtils; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.util.List; import static org.jetbrains.kotlin.script.ScriptTestUtilKt.loadScriptingPlugin; public abstract class AbstractScriptCodegenTest extends CodegenTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); - } - @Override protected void updateConfiguration(@NotNull CompilerConfiguration configuration) { super.updateConfiguration(configuration); @@ -44,6 +42,10 @@ public abstract class AbstractScriptCodegenTest extends CodegenTestCase { @Override protected void doTest(@NotNull String filename) { + configurationKind = InTextDirectivesUtils.findLinesWithPrefixesRemoved( + FilesKt.readText(new File(filename), Charsets.UTF_8), "// WITH_REFLECT" + ).isEmpty() ? ConfigurationKind.JDK_ONLY : ConfigurationKind.ALL; + createEnvironmentWithMockJdkAndIdeaAnnotations(configurationKind); loadFileByFullPath(filename); try { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java index 1a49963af2b..41df3551dc7 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java @@ -90,6 +90,11 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest { runTest("compiler/testData/codegen/script/localDelegatedProperty.kts"); } + @TestMetadata("localDelegatedPropertyInLambda.kts") + public void testLocalDelegatedPropertyInLambda() throws Exception { + runTest("compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts"); + } + @TestMetadata("localDelegatedPropertyNoExplicitType.kts") public void testLocalDelegatedPropertyNoExplicitType() throws Exception { runTest("compiler/testData/codegen/script/localDelegatedPropertyNoExplicitType.kts"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrScriptCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrScriptCodegenTestGenerated.java index 94b61c0e22f..c1ed6e9c353 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrScriptCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrScriptCodegenTestGenerated.java @@ -90,6 +90,11 @@ public class IrScriptCodegenTestGenerated extends AbstractIrScriptCodegenTest { runTest("compiler/testData/codegen/script/localDelegatedProperty.kts"); } + @TestMetadata("localDelegatedPropertyInLambda.kts") + public void testLocalDelegatedPropertyInLambda() throws Exception { + runTest("compiler/testData/codegen/script/localDelegatedPropertyInLambda.kts"); + } + @TestMetadata("localDelegatedPropertyNoExplicitType.kts") public void testLocalDelegatedPropertyNoExplicitType() throws Exception { runTest("compiler/testData/codegen/script/localDelegatedPropertyNoExplicitType.kts");