diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 712381b324a..71489b6daa4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -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 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 valueParameters, + boolean isStatic, + KotlinTypeMapper typeMapper, + int shiftForDestructuringVariables ) { Iterator valueParameterIterator = valueParameters.iterator(); List params = jvmMethodSignature.getValueParameters(); @@ -557,6 +578,7 @@ public class FunctionCodegen { shift += type.getSize(); } + shift += shiftForDestructuringVariables; for (ValueParameterDescriptor parameter : valueParameters) { List destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter); if (destructuringVariables == null) continue; diff --git a/compiler/testData/checkLocalVariablesTable/destructuringInlineLambda.kt b/compiler/testData/checkLocalVariablesTable/destructuringInlineLambda.kt new file mode 100644 index 00000000000..0ead9a4a08e --- /dev/null +++ b/compiler/testData/checkLocalVariablesTable/destructuringInlineLambda.kt @@ -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 diff --git a/compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt new file mode 100644 index 00000000000..13280feb86e --- /dev/null +++ b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt @@ -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" +} diff --git a/compiler/testData/codegen/boxInline/simple/destructuring.kt b/compiler/testData/codegen/boxInline/simple/destructuring.kt new file mode 100644 index 00000000000..ea489b8e8d7 --- /dev/null +++ b/compiler/testData/codegen/boxInline/simple/destructuring.kt @@ -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" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/simple/destructuringIndexClash.kt b/compiler/testData/codegen/boxInline/simple/destructuringIndexClash.kt new file mode 100644 index 00000000000..eeb9f2bfefb --- /dev/null +++ b/compiler/testData/codegen/boxInline/simple/destructuringIndexClash.kt @@ -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 +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 8e5cbba0249..b40e9cdff8e 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1a082403cfb..20809cae57a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index bc0de056b8d..dc70c94557d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java index 830a8cc700e..1c79d312805 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 88e5abb449f..1dd1f19ad1a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -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");