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 1663619606 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
This commit is contained in:
Alexander Udalov
2022-12-01 01:27:08 +01:00
parent fe81ad0bbe
commit 3ab2b82878
5 changed files with 37 additions and 7 deletions
@@ -202,7 +202,8 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
val localProperties = mutableListOf<IrLocalDelegatedPropertySymbol>()
val localPropertyIndices = mutableMapOf<IrSymbol, Int>()
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)
@@ -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
@@ -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 {
@@ -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");
@@ -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");