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:
+2
-1
@@ -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
|
||||
+8
-6
@@ -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 {
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user