Properly generate indices for destructured parameters in inline case

#KT-14399 Fixed
This commit is contained in:
Denis Zharkov
2016-10-19 09:30:15 +03:00
parent 32290ec1d3
commit 4793f71da2
10 changed files with 159 additions and 5 deletions
@@ -216,8 +216,8 @@ public class FunctionCodegen {
new Label(),
new Label(),
contextKind,
typeMapper
);
typeMapper,
0);
mv.visitEnd();
return;
@@ -457,8 +457,11 @@ public class FunctionCodegen {
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
generateLocalVariableTable(
mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper);
mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper,
(functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0)
);
//TODO: it's best to move all below logic to 'generateLocalVariableTable' method
if (context.isInlineMethodContext() && functionFakeIndex != -1) {
mv.visitLocalVariable(
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + functionDescriptor.getName().asString(),
@@ -499,11 +502,13 @@ public class FunctionCodegen {
@NotNull Label methodBegin,
@NotNull Label methodEnd,
@NotNull OwnerKind ownerKind,
@NotNull KotlinTypeMapper typeMapper
@NotNull KotlinTypeMapper typeMapper,
int shiftForDestructuringVariables
) {
generateLocalVariablesForParameters(mv, jvmMethodSignature, thisType, methodBegin, methodEnd,
functionDescriptor.getValueParameters(),
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), typeMapper);
AsmUtil.isStaticMethod(ownerKind, functionDescriptor), typeMapper, shiftForDestructuringVariables
);
}
public static void generateLocalVariablesForParameters(
@@ -515,6 +520,22 @@ public class FunctionCodegen {
Collection<ValueParameterDescriptor> valueParameters,
boolean isStatic,
KotlinTypeMapper typeMapper
) {
generateLocalVariablesForParameters(
mv, jvmMethodSignature, thisType, methodBegin, methodEnd, valueParameters, isStatic, typeMapper, 0
);
}
private static void generateLocalVariablesForParameters(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature jvmMethodSignature,
@Nullable Type thisType,
@NotNull Label methodBegin,
@NotNull Label methodEnd,
Collection<ValueParameterDescriptor> valueParameters,
boolean isStatic,
KotlinTypeMapper typeMapper,
int shiftForDestructuringVariables
) {
Iterator<ValueParameterDescriptor> valueParameterIterator = valueParameters.iterator();
List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
@@ -557,6 +578,7 @@ public class FunctionCodegen {
shift += type.getSize();
}
shift += shiftForDestructuringVariables;
for (ValueParameterDescriptor parameter : valueParameters) {
List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
if (destructuringVariables == null) continue;
@@ -0,0 +1,22 @@
inline fun foo(x: (Int, Station) -> Unit) {
x(1, Station(null, "", 1))
}
data class Station(
val id: String?,
val name: String,
val distance: Int)
fun box(): String {
foo { i, (a1, a2, a3) -> i + a3 }
return "OK"
}
// METHOD : DestructuringInlineLambdaKt.box()Ljava/lang/String;
// VARIABLE : NAME=i TYPE=I INDEX=1
// VARIABLE : NAME=$a1_a2_a3 TYPE=LStation; INDEX=0
// VARIABLE : NAME=a1 TYPE=Ljava/lang/String; INDEX=2
// VARIABLE : NAME=a2 TYPE=Ljava/lang/String; INDEX=3
// VARIABLE : NAME=a3 TYPE=I INDEX=4
// VARIABLE : NAME=$i$a$1$foo TYPE=I INDEX=5
// VARIABLE : NAME=$i$f$foo TYPE=I INDEX=6
@@ -0,0 +1,13 @@
// WITH_RUNTIME
data class Station(
val id: String?,
val name: String,
val distance: Int)
fun box(): String {
var result = ""
// See KT-14399
listOf(Station("O", "K", 56)).forEachIndexed { i, (id, name, distance) -> result += "$id$name$distance" }
if (result != "OK56") return "fail: $result"
return "OK"
}
@@ -0,0 +1,20 @@
// FILE: 1.kt
package test
inline fun foo(x: (Int, Station) -> Unit) {
x(1, Station(null, "", 1))
}
data class Station(
val id: String?,
val name: String,
val distance: Int)
// FILE: 2.kt
import test.*
fun box(): String {
foo { i, (a1, a2, a3) -> i + a3 }
return "OK"
}
@@ -0,0 +1,35 @@
// for android
// FILE: 1.kt
package test
var res = "fail"
inline fun foo(x: (Int, Station) -> Unit) {
x(1, Station("a", "b", "c"))
res = "O"
}
inline fun foo2(x: (Int, StationInt) -> Unit) {
x(1, StationInt(1, 2, 3))
res += "K"
}
data class Station(
val id: String,
val name: String,
val distance: String)
data class StationInt(
val id: Int,
val name: Int,
val distance: Int)
// FILE: 2.kt
import test.*
fun box(): String {
foo { i, (a1, a2, a3) -> a3 + i }
foo2 { i, (a1, a2, a3) -> i + a3 }
return res
}
@@ -5775,6 +5775,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/stdlibUsages.kt");
doTest(fileName);
}
@TestMetadata("withIndexed.kt")
public void testWithIndexed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/diagnostics")
@@ -5775,6 +5775,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/stdlibUsages.kt");
doTest(fileName);
}
@TestMetadata("withIndexed.kt")
public void testWithIndexed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/diagnostics")
@@ -1906,6 +1906,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTest(fileName);
}
@TestMetadata("destructuring.kt")
public void testDestructuring() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/destructuring.kt");
doTest(fileName);
}
@TestMetadata("destructuringIndexClash.kt")
public void testDestructuringIndexClash() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/destructuringIndexClash.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/extension.kt");
@@ -53,6 +53,12 @@ public class CheckLocalVariablesTableTestGenerated extends AbstractCheckLocalVar
doTest(fileName);
}
@TestMetadata("destructuringInlineLambda.kt")
public void testDestructuringInlineLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/checkLocalVariablesTable/destructuringInlineLambda.kt");
doTest(fileName);
}
@TestMetadata("inlineLambdaWithItParam.kt")
public void testInlineLambdaWithItParam() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/checkLocalVariablesTable/inlineLambdaWithItParam.kt");
@@ -1906,6 +1906,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doTest(fileName);
}
@TestMetadata("destructuring.kt")
public void testDestructuring() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/destructuring.kt");
doTest(fileName);
}
@TestMetadata("destructuringIndexClash.kt")
public void testDestructuringIndexClash() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/destructuringIndexClash.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/simple/extension.kt");