Fix reification for crossinline lambdas inlined into object literal
Inline lambda could capture reified parameter of containing inline function ('a' function)
when it is inlined in another one.
If it's inlined in any anonymous object we should track it and
add reification marker to such anonymous object instance creation
to rewrite it on inlining bytecode of 'a' function.
#KT-15997 Fixed
This commit is contained in:
@@ -252,6 +252,7 @@ public class MethodInliner {
|
|||||||
//TODO add skipped this and receiver
|
//TODO add skipped this and receiver
|
||||||
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);
|
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);
|
||||||
result.mergeWithNotChangeInfo(lambdaResult);
|
result.mergeWithNotChangeInfo(lambdaResult);
|
||||||
|
result.getReifiedTypeParametersUsages().mergeAll(lambdaResult.getReifiedTypeParametersUsages());
|
||||||
|
|
||||||
//return value boxing/unboxing
|
//return value boxing/unboxing
|
||||||
Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor()));
|
Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor()));
|
||||||
@@ -486,6 +487,11 @@ public class MethodInliner {
|
|||||||
);
|
);
|
||||||
awaitClassReification = false;
|
awaitClassReification = false;
|
||||||
}
|
}
|
||||||
|
else if (inliningContext.isInliningLambda && ReifiedTypeInliner.Companion.isOperationReifiedMarker(cur)) {
|
||||||
|
ReificationArgument reificationArgument = ReifiedTypeInlinerKt.getReificationArgument((MethodInsnNode) cur);
|
||||||
|
String parameterName = reificationArgument.getParameterName();
|
||||||
|
result.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cur.getOpcode() == Opcodes.GETSTATIC) {
|
else if (cur.getOpcode() == Opcodes.GETSTATIC) {
|
||||||
FieldInsnNode fieldInsnNode = (FieldInsnNode) cur;
|
FieldInsnNode fieldInsnNode = (FieldInsnNode) cur;
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val MethodInsnNode.reificationArgument: ReificationArgument?
|
val MethodInsnNode.reificationArgument: ReificationArgument?
|
||||||
get() {
|
get() {
|
||||||
val prev = previous!!
|
val prev = previous!!
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
// FULL_JDK
|
||||||
|
// WITH_REFLECT
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
|
||||||
|
var result = "fail"
|
||||||
|
|
||||||
|
inline fun <reified T : Any> crashMe(): ReadWriteProperty<Any?, Unit> {
|
||||||
|
return Delegates.observable(Unit, { a, b, c -> result = T::class.java.simpleName })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
|
||||||
|
class OK {
|
||||||
|
var value by crashMe<OK>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
OK().value = Unit
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
// FULL_JDK
|
||||||
|
// WITH_REFLECT
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
import kotlin.properties.ObservableProperty
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
var result = "fail"
|
||||||
|
|
||||||
|
public inline fun <reified T> myObservable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
|
||||||
|
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
|
||||||
|
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//samely named reified parameter (T) as in myObservable
|
||||||
|
inline fun <reified T : Any> crashMe(): ReadWriteProperty<Any?, Unit> {
|
||||||
|
return myObservable(Unit, { a, b, c -> result = T::class.java.simpleName })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
|
||||||
|
class OK {
|
||||||
|
var value by crashMe<OK>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
OK().value = Unit
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -1886,6 +1886,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt15997.kt")
|
||||||
|
public void testKt15997() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt15997.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt15997_2.kt")
|
||||||
|
public void testKt15997_2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt15997_2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt6988.kt")
|
@TestMetadata("kt6988.kt")
|
||||||
public void testKt6988() throws Exception {
|
public void testKt6988() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt6988.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt6988.kt");
|
||||||
|
|||||||
+12
@@ -1886,6 +1886,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt15997.kt")
|
||||||
|
public void testKt15997() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt15997.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt15997_2.kt")
|
||||||
|
public void testKt15997_2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt15997_2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt6988.kt")
|
@TestMetadata("kt6988.kt")
|
||||||
public void testKt6988() throws Exception {
|
public void testKt6988() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt6988.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt6988.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user