Skip to content

Commit

Permalink
JVM IR: script is a valid container for local delegated properties
Browse files Browse the repository at this point in the history
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 1663619 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

(cherry picked from commit 3ab2b82)
  • Loading branch information
udalov authored and qodana-bot committed Dec 12, 2022
1 parent c32cd10 commit ea33e72
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -44,6 +42,10 @@ protected void updateConfiguration(@NotNull CompilerConfiguration configuration)

@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 {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ea33e72

Please sign in to comment.